<?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=Gshugh</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=Gshugh"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Gshugh"/>
	<updated>2026-08-20T16:51:09Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124802</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124802"/>
		<updated>2019-05-01T00:31:23Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Code Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This [http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation Expertiza] project, completed in the Spring of 2019, aimed to improve the charts instructors could view to see the grade statistics for a given assignment. Two charts already existed, one showing the grade distribution for all teams, and another simply showing the class average grade. Our goal for this project was to add a third chart, using [https://developers.google.com/chart/ Google Charts], which would show grade statistics for the various [https://en.wikipedia.org/wiki/Rubric_(academic) rubric] grades within that assignment. The chart is interactive so the user (instructor) can toggle which rubric criteria, and which statistics, to display.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Along with displaying the rubric criteria for a single assignment, we aimed to add a feature which would allow the comparison of compatible rubric grades from two different assignments. Again, this functionality is interactive, allowing the instructor to choose which statistics will be populated in the chart. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
By viewing our new visualization of rubric grades, an instructor can better judge which aspects of the course are well-understood, and which may need a bit more attention.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Problem Statement ==&lt;br /&gt;
'''E1929 - Visualizations for Instructors''' - Class performance on specific rubrics&lt;br /&gt;
&lt;br /&gt;
An interactive visualization or table that shows how a class performed on selected rubric criteria would be immensely helpful. It would show the instructor what he / she will need to focus more attention on. For example, could you create a graph showing the range and clustering of scores for the 5 main rubric criteria? And, if these same 5 criteria are used in the preliminary and final assignments, it would be nice to be able to compare performance between assignments in a visualization that showed the class results on 3 separate artifacts.&lt;br /&gt;
&lt;br /&gt;
Webpage: login as instructor -&amp;gt; Manage -&amp;gt; Assignments -&amp;gt; View scores&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Old Charts ===&lt;br /&gt;
[[File:Existing_Assignment_Grades_Wed.png|frame|centre|'''Figure 1: Existing assignment grade charts - '''The existing assignment grade charts show the average grade for the assignment and the grade distribution. During this project, we aimed to add a third chart which shows the distribution for specific rubric criteria within the assignment.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Accomplished ==&lt;br /&gt;
&lt;br /&gt;
=== Executed on Plans ===&lt;br /&gt;
We successfully executed all of the ideas we had during the planning phase:&lt;br /&gt;
* Add new feature to show mean and median data for rubric criteria in a given assignment&lt;br /&gt;
* Add new feature to show comparison&lt;br /&gt;
* Performed UI testing to ensure features were operational, including edge cases&lt;br /&gt;
* Added and ran RSpec and Capybara automated tests&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Charts Inserted ===&lt;br /&gt;
[[File:AnalyzeAssignmentWed.png|frame|centre|'''Figure 2: New Rubric Statistic Visualization - '''Added in the center of the existing two charts is an interactive chart the instructor can use to see the mean or median scores for whichever criteria they select. This is done on the &amp;quot;Analyze Assignment&amp;quot; tab, which is selected by default when the &amp;quot;View Scores&amp;quot; page is loaded.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CompareAssignmentsWed.png|frame|centre|'''Figure 3: New Rubric Cross-Assignment Comparison Visualization - '''The instructor can see a comparison between selected criteria between the current assignment and the selected assignment. The rubric criteria must be compatible in order for it to even show up in the selection list. This comparison visualization is done on the &amp;quot;Compare Assignments&amp;quot; tab which must be selected after the &amp;quot;View Scores&amp;quot; page has been loaded.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Extra Issues Fixed ===&lt;br /&gt;
&lt;br /&gt;
* Refactored [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_team_charts.html.erb _team_charts.html.erb] partial view to use partials for each graphic. Previously both charts were defined together in _team_charts.html.erb, but now each graphic has its own partial view ([https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_team_charts_averages.html.erb _team_charts_averages.html.erb], [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_team_charts_distribution.html.erb _team_charts_distribution.html.erb], [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_team_charts_rubric_stats.html.erb _team_charts_rubric_stats.html.erb]). This allows more flexibility going forward, if it's decided one chart should move to a new place on the page, or to a new page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Code Changes ===&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1440/files Files Added/Modified]&lt;br /&gt;
&lt;br /&gt;
Added: 10 + Modified: 13 = Total: 23&lt;br /&gt;
&lt;br /&gt;
* app/assets/javascripts/rubric_stats.js '''(new)'''&lt;br /&gt;
* app/controllers/grades_controller.rb&lt;br /&gt;
* app/helpers/assignment_stats_helper.rb '''(new)'''&lt;br /&gt;
* app/models/assignment.rb&lt;br /&gt;
* app/models/assignment_questionnaire.rb&lt;br /&gt;
* app/models/assignment_stats.rb '''(new)'''&lt;br /&gt;
* app/models/criterion_stats.rb '''(new)'''&lt;br /&gt;
* app/models/question.rb&lt;br /&gt;
* app/models/questionnaire.rb&lt;br /&gt;
* app/models/review_round_stats.rb '''(new)'''&lt;br /&gt;
* app/models/score_view.rb&lt;br /&gt;
* app/views/grades/_team_charts.html.erb&lt;br /&gt;
* app/views/grades/_team_charts_averages.html.erb '''(new)'''&lt;br /&gt;
* app/views/grades/_team_charts_distribution.html.erb '''(new)'''&lt;br /&gt;
* app/views/grades/_team_charts_rubric_stats.html.erb '''(new)'''&lt;br /&gt;
* spec/controllers/grades_controller_spec.rb&lt;br /&gt;
* spec/factories/factories.rb&lt;br /&gt;
* spec/features/grade_interface_spec.rb '''(new)'''&lt;br /&gt;
* spec/features/helpers/grade_interface_helper.rb '''(new)'''&lt;br /&gt;
* spec/models/assignment_spec.rb&lt;br /&gt;
* spec/models/questionnaire_spec.rb&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
We performed automated tests using RSpec Framework and Capybara. In addition, we performed manual tests of the user interface (UI), by using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, was used to verify the models of the Expertiza web application feature set. Since this feature is dealing with visualizations (charts) that are intimately tied with Active Record models, we seeded the testing database with known data via FactoryBot gem. These changes were automatically rolled-back once the testing was complete.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to increase/maintain automated test coverage for the methods that we added into assignment and questionnaire models. Mocks and stubs were utilized in order to decouple the model under test from dependencies of other models. This will allow us to identify easily if our model updates are causing an issue.&lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
RSpec Capybara was used to provide integration testing of the charts. The Test Database was seeded with the appropriate information for executing the results of the charts. An additional GEM was needed, webdrivers, to utilize the predefined drivers of Selenium. The default web driver, Rack-Test, does not execute java scripts. Since the graphs that we are using require java script, thus soliciting the necessity of Selenium with its predefined web driver, selenium_chrome_headless. This provides the required functionality to process the java scripts and to automatically ensure that they exist in the DOM. &lt;br /&gt;
&lt;br /&gt;
In order to use the headless web driver with the seeded Test Database, a different database strategy was required. As a result, for this test only, the database strategy was changed to truncation. Ruby 2.2.7 is used in the current version of Expertiza. This version does not allow for sharing of the database thread, and thus requires the to be written to the database outside of a transaction block. This allows for the headless web driver to see that the data is persisted the Test Database and is able to run as normal. Once the test is completed, the database tables are truncated and all data is removed.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we also performed manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* The new feature properly initializes&lt;br /&gt;
*# Analyze Assignment tab is loaded by default&lt;br /&gt;
*# Chart is in between the other two existing charts&lt;br /&gt;
*# Round 1, all Criteria selected, and Mean are selected by default&lt;br /&gt;
* Analyze Assignment tab operating correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
* Compare Assignments tab operating correctly&lt;br /&gt;
*# Compare Assignments tab is only displayed if compatible assignments exist&lt;br /&gt;
*# Clicking Compare Assignments tab loads that tab&lt;br /&gt;
*# (All tests from Analyze Assignment tab apply to this tab as well)&lt;br /&gt;
*# The two colors for assignment comparison are correct&lt;br /&gt;
&lt;br /&gt;
=== Testing Issues ===&lt;br /&gt;
Using the Ubuntu image, one issue was discovered was with the ScoreView view. The migration files is building the view out as a table instead of a view as required, this can be seen in the schema file. The Development database shows the ScoreView as a view, but the Test database shows it as an table. It appears that the Development database was altered outside of migrations to force the ScoreView to be a view instead of table. With this scenario, the automated integration testing was forced to seed the ScoreView as a table. Further gems are available to alleviate this issue.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Shortcomings ==&lt;br /&gt;
* We were unable to find two compatible assignments in the Expertiza test database to fully test our Compare Assignments feature. We did test all the functionality using hard-coded data, but weren't able to do it pulling real data like we did for the Analyze Assignments feature.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Decisions ==&lt;br /&gt;
1. Put our new chart on the View Scores page, rather than on a new page&lt;br /&gt;
* Since it was able to fit on the existing page while displaying all the necessary info, we figured it'd be beneficial to have all grade statistics charts together.&lt;br /&gt;
2. Use GoogleCharts for our new charts&lt;br /&gt;
* The group who previously attempted this project chose GoogleCharts because it has a high compatibility and its charts look of similar quality to those already existing in Expertiza. We agreed with this, and determined GoogleCharts had all of the features we would need.&lt;br /&gt;
3. Added the AssignmentStats, CriterionStats, and ReviewRoundStats models&lt;br /&gt;
* This was a logical, structured way to organize the various data and methods we needed.&lt;br /&gt;
4. Encapsulation of the data within the new models&lt;br /&gt;
* Since the various statistics we needed to form our chart were stored in multiple models, there would be no good place to put the new methods we'd need. The way we did it promotes cohesion, since the new classes have the sole focus of computing statistics. This also allows for future refactoring of other sporadic statistics methods.&lt;br /&gt;
5. Placed AssignmentStats methods in assignment_stats_helper.rb rather than in the model or controller.&lt;br /&gt;
* The methods of interest were really not business logic, but more like massaging of data. For that reason it belonged more in the controller than the model. However, to keep things neat and clean in the controller, the methods were moved out to the helper file.&lt;br /&gt;
6. The exposure of mean and median as the metric_names in grades_controller.rb&lt;br /&gt;
* Since we are explicitly calling the avg_data and med_data methods in the controller, we thought it made sense to name the metric_names nearby, within the controller, rather than hidden off in the helper file.&lt;br /&gt;
7. Moved most of the javascript code in _team_charts_rubric_stats.html.erb into app/assets/javascripts/rubric_stats.js. We had to keep our dynamic references of Ruby code in the view.&lt;br /&gt;
* This keeps the view more clean and concise. Also, in the previous semester, one of the reasons the team's pull request was rejected was because they had too much javascript code in their views.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/1440 Pull Request]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/gshugh/expertiza/tree/OSS-HW4 GitHub Repo]&lt;br /&gt;
&lt;br /&gt;
[https://drive.google.com/file/d/1jmOYfbNOlXQObtsK4MoIti-LsjJ_Y88P/view Demo Video]&lt;br /&gt;
&lt;br /&gt;
[https://docs.google.com/document/d/1Ozw2Bj2u_LyeKUdDqAyQtz1stEIKrxkmRnwmNyUgmzw/edit#heading=h.5kwrelqdnewh Problem Statement]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Team ==&lt;br /&gt;
* Akshay Ravichandran '''(Mentor)'''&lt;br /&gt;
* Chris Adkins&lt;br /&gt;
* Bobby DeMarco&lt;br /&gt;
* George Hugh&lt;br /&gt;
* John Warren&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124032</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124032"/>
		<updated>2019-04-13T02:44:17Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to fine-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|'''Figure 1: Existing assignment grade page header - '''The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
==== Interactive Example ====&lt;br /&gt;
&lt;br /&gt;
   https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
==== New View Examples ====&lt;br /&gt;
&lt;br /&gt;
[[File:AnalyzeAssignmentNew.png|frame|centre|'''Figure 2: New Rubric Statistic Visualization - '''Added in the center of the existing two charts is an interactive chart the instructor can use to see the mean or median scores for whichever criteria they select. This is done on the &amp;quot;Analyze Assignment&amp;quot; tab, which is selected by default when the &amp;quot;View Scores&amp;quot; page is loaded.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CompareAssignmentsNew.png|frame|centre|'''Figure 3: New Rubric Cross-Assignment Comparison Visualization - '''The instructor can see a comparison between selected criteria between the current assignment and the selected assignment. The rubric criteria must be compatible in order for it to even show up in the selection list. This comparison visualization is done on the &amp;quot;Compare Assignments&amp;quot; tab which must be selected after the &amp;quot;View Scores&amp;quot; page has been loaded.]]&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
During the integration of rubric statistics and assignment grade statistics, this project expects to change controller files, view files and JavaScript files. For methods that are modified by this project, the team will also ensure that Code Climate (an automated code quality checker) issues are resolved. This project will also refactor changed methods to reflect common Ruby and Rails practices.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Code Changes ===&lt;br /&gt;
The amount of methods and files to be changed during the integration of rubric statistics and assignment grade statistics is minimal. The team proposes changing a controller file, a view file, a JavaScript file, and an RSpec files. The team does not expect to change the database nor do we expect to change the model files. Other files will be changed as required to support the integration. A preliminary list of files to be changed is given below:&lt;br /&gt;
&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/controllers/grades_controller.rb grades_controller.rb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/assets/javascripts/grading.js grading.js]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_participant_charts.html.erb _participant_charts.html.erb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/spec/controllers/grades_controller_spec.rb grades_controllers_spec.rb]&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
[[File:DesignFlowSingle.png|frame|center|'''Figure 4: Rubric Statistic Design Flow - '''Instructor wants to view student scores on individual rubric criteria.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png|frame|center|'''Figure 5: Cross-Assignment Comparison Design Flow - '''Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments.]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries are given below:&lt;br /&gt;
&lt;br /&gt;
    [http://www.highcharts.com/ Highcharts]&lt;br /&gt;
    [http://g.raphaeljs.com/ RaphaelJS]&lt;br /&gt;
    [http://dygraphs.com/ dygraphs]&lt;br /&gt;
    [http://vis.stanford.edu/protovis/ Protovis]&lt;br /&gt;
    [http://grafico.kilianvalkhof.com/ Grafico]&lt;br /&gt;
    [https://chartkick.com/ ChartKick]&lt;br /&gt;
    [http://www.vancharts.com/ VanCharts]&lt;br /&gt;
    [https://developers.google.com/chart/ GoogleCharts]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124031</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124031"/>
		<updated>2019-04-13T02:43:27Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Proposed Code Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to fine-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|'''Figure 1: Existing assignment grade page header - '''The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
==== Interactive Example ====&lt;br /&gt;
&lt;br /&gt;
   https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
==== New View Examples ====&lt;br /&gt;
&lt;br /&gt;
[[File:AnalyzeAssignmentNew.png|frame|centre|'''Figure 2: New Rubric Statistic Visualization - '''Added in the center of the existing two charts is an interactive chart the instructor can use to see the mean or median scores for whichever criteria they select. This is done on the &amp;quot;Analyze Assignment&amp;quot; tab, which is selected by default when the &amp;quot;View Scores&amp;quot; page is loaded.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CompareAssignmentsNew.png|frame|centre|'''Figure 3: New Rubric Cross-Assignment Comparison Visualization - '''The instructor can see a comparison between selected criteria between the current assignment and the selected assignment. The rubric criteria must be compatible in order for it to even show up in the selection list. This comparison visualization is done on the &amp;quot;Compare Assignments&amp;quot; tab which must be selected after the &amp;quot;View Scores&amp;quot; page has been loaded.]]&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
During the integration of rubric statistics and assignment grade statistics, this project expects to change controller files, view files and JavaScript files. For methods that are modified by this project, the team will also ensure that Code Climate (an automated code quality checker) issues are resolved and refactor those methods to reflect common Ruby and Rails practices.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Code Changes ===&lt;br /&gt;
The amount of methods and files to be changed during the integration of rubric statistics and assignment grade statistics is minimal. The team proposes changing a controller file, a view file, a JavaScript file, and an RSpec files. The team does not expect to change the database nor do we expect to change the model files. Other files will be changed as required to support the integration. A preliminary list of files to be changed is given below:&lt;br /&gt;
&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/controllers/grades_controller.rb grades_controller.rb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/assets/javascripts/grading.js grading.js]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_participant_charts.html.erb _participant_charts.html.erb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/spec/controllers/grades_controller_spec.rb grades_controllers_spec.rb]&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
[[File:DesignFlowSingle.png|frame|center|'''Figure 4: Rubric Statistic Design Flow - '''Instructor wants to view student scores on individual rubric criteria.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png|frame|center|'''Figure 5: Cross-Assignment Comparison Design Flow - '''Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments.]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries are given below:&lt;br /&gt;
&lt;br /&gt;
    [http://www.highcharts.com/ Highcharts]&lt;br /&gt;
    [http://g.raphaeljs.com/ RaphaelJS]&lt;br /&gt;
    [http://dygraphs.com/ dygraphs]&lt;br /&gt;
    [http://vis.stanford.edu/protovis/ Protovis]&lt;br /&gt;
    [http://grafico.kilianvalkhof.com/ Grafico]&lt;br /&gt;
    [https://chartkick.com/ ChartKick]&lt;br /&gt;
    [http://www.vancharts.com/ VanCharts]&lt;br /&gt;
    [https://developers.google.com/chart/ GoogleCharts]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124029</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124029"/>
		<updated>2019-04-13T02:37:48Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Tools and Design Choices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to fine-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|'''Figure 1: Existing assignment grade page header - '''The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
==== Interactive Example ====&lt;br /&gt;
&lt;br /&gt;
   https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
==== New View Examples ====&lt;br /&gt;
&lt;br /&gt;
[[File:AnalyzeAssignmentNew.png|frame|centre|'''Figure 2: New Rubric Statistic Visualization - '''Added in the center of the existing two charts is an interactive chart the instructor can use to see the mean or median scores for whichever criteria they select. This is done on the &amp;quot;Analyze Assignment&amp;quot; tab, which is selected by default when the &amp;quot;View Scores&amp;quot; page is loaded.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CompareAssignmentsNew.png|frame|centre|'''Figure 3: New Rubric Cross-Assignment Comparison Visualization - '''The instructor can see a comparison between selected criteria between the current assignment and the selected assignment. The rubric criteria must be compatible in order for it to even show up in the selection list. This comparison visualization is done on the &amp;quot;Compare Assignments&amp;quot; tab which must be selected after the &amp;quot;View Scores&amp;quot; page has been loaded.]]&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
During the integration of rubric statistics and assignment grade statistics, this project expects to change controller files, view files and JavaScript files. For methods that are modified by this project, the team will also ensure that Code Climate (an automated code quality checker) issues are resolved and refactor those methods to reflect common Ruby and Rails practices.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Code Changes ===&lt;br /&gt;
The amount of methods and files to be changed during the integration of rubric statistics and assignment grade statistics is minimal. The team proposes changing a controller file, a view file, JavaScript file, and RSpec files. The team does not expect to change the database nor do we expect to change the model files. A preliminary list of files to be changed is given below:&lt;br /&gt;
&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/controllers/grades_controller.rb grades_controller.rb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/assets/javascripts/grading.js grading.js]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_participant_charts.html.erb _participant_charts.html.erb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/spec/controllers/grades_controller_spec.rb grades_controllers_spec.rb]&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
[[File:DesignFlowSingle.png|frame|center|'''Figure 4: Rubric Statistic Design Flow - '''Instructor wants to view student scores on individual rubric criteria.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png|frame|center|'''Figure 5: Cross-Assignment Comparison Design Flow - '''Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments.]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries are given below:&lt;br /&gt;
&lt;br /&gt;
    [http://www.highcharts.com/ Highcharts]&lt;br /&gt;
    [http://g.raphaeljs.com/ RaphaelJS]&lt;br /&gt;
    [http://dygraphs.com/ dygraphs]&lt;br /&gt;
    [http://vis.stanford.edu/protovis/ Protovis]&lt;br /&gt;
    [http://grafico.kilianvalkhof.com/ Grafico]&lt;br /&gt;
    [https://chartkick.com/ ChartKick]&lt;br /&gt;
    [http://www.vancharts.com/ VanCharts]&lt;br /&gt;
    [https://developers.google.com/chart/ GoogleCharts]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124027</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124027"/>
		<updated>2019-04-13T02:33:37Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Proposed Code Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to fine-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|'''Figure 1: Existing assignment grade page header - '''The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
==== Interactive Example ====&lt;br /&gt;
&lt;br /&gt;
   https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
==== New View Examples ====&lt;br /&gt;
&lt;br /&gt;
[[File:AnalyzeAssignmentNew.png|frame|centre|'''Figure 2: New Rubric Statistic Visualization - '''Added in the center of the existing two charts is an interactive chart the instructor can use to see the mean or median scores for whichever criteria they select. This is done on the &amp;quot;Analyze Assignment&amp;quot; tab, which is selected by default when the &amp;quot;View Scores&amp;quot; page is loaded.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CompareAssignmentsNew.png|frame|centre|'''Figure 3: New Rubric Cross-Assignment Comparison Visualization - '''The instructor can see a comparison between selected criteria between the current assignment and the selected assignment. The rubric criteria must be compatible in order for it to even show up in the selection list. This comparison visualization is done on the &amp;quot;Compare Assignments&amp;quot; tab which must be selected after the &amp;quot;View Scores&amp;quot; page has been loaded.]]&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
During the integration of rubric statistics and assignment grade statistics, this project expects to change controller files, view files and JavaScript files. For methods that are modified by this project, the team will also ensure that Code Climate (an automated code quality checker) issues are resolved and refactor those methods to reflect common Ruby and Rails practices.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Code Changes ===&lt;br /&gt;
The amount of methods and files to be changed during the integration of rubric statistics and assignment grade statistics is minimal. The team proposes changing a controller file, a view file, JavaScript file, and RSpec files. The team does not expect to change the database nor do we expect to change the model files. A preliminary list of files to be changed is given below:&lt;br /&gt;
&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/controllers/grades_controller.rb grades_controller.rb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/assets/javascripts/grading.js grading.js]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/app/views/grades/_participant_charts.html.erb _participant_charts.html.erb]&lt;br /&gt;
    [https://github.com/gshugh/expertiza/blob/OSS-HW4/spec/controllers/grades_controller_spec.rb grades_controllers_spec.rb]&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
[[File:DesignFlowSingle.png|frame|center|'''Figure 4: Rubric Statistic Design Flow - '''Instructor wants to view student scores on individual rubric criteria.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png|frame|center|'''Figure 5: Cross-Assignment Comparison Design Flow - '''Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments.]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries are given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124020</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=124020"/>
		<updated>2019-04-13T02:19:59Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to fine-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|'''Figure 1: Existing assignment grade page header - '''The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
==== Interactive Example ====&lt;br /&gt;
&lt;br /&gt;
   https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
==== New View Examples ====&lt;br /&gt;
&lt;br /&gt;
[[File:AnalyzeAssignmentNew.png|frame|centre|'''Figure 2: New Rubric Statistic Visualization - '''Added in the center of the existing two charts is an interactive chart the instructor can use to see the mean or median scores for whichever criteria they select. This is done on the &amp;quot;Analyze Assignment&amp;quot; tab, which is selected by default when the &amp;quot;View Scores&amp;quot; page is loaded.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CompareAssignmentsNew.png|frame|centre|'''Figure 3: New Rubric Cross-Assignment Comparison Visualization - '''The instructor can see a comparison between selected criteria between the current assignment and the selected assignment. The rubric criteria must be compatible in order for it to even show up in the selection list. This comparison visualization is done on the &amp;quot;Compare Assignments&amp;quot; tab which must be selected after the &amp;quot;View Scores&amp;quot; page has been loaded.]]&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
During the integration of rubric statistics and assignment grade statistics, this project expects to change controller files, view files and JavaScript files. For methods that are modified by this project, the team will also ensure that Code Climate (an automated code quality checker) issues are resolved and refactor those methods to reflect common Ruby and Rails practices.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Code Changes ===&lt;br /&gt;
The amount of methods and files to be changed during the integration of rubric statistics and assignment grade statistics is minimal. The team proposes changing a controller file, a view file, JavaScript file, and RSpec files. The team does not expect to change the database nor do we expect to change the model files. A list of expected RSpec files to be changed is listed in the Test Plan. A preliminary list of files to be changed is given below:&lt;br /&gt;
&lt;br /&gt;
    app/controllers/grades_controller.rb&lt;br /&gt;
    assets/javascripts/grading.js&lt;br /&gt;
    spec/controllers/grades_controllers_spec.rb&lt;br /&gt;
    app/views/grades/_participant_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
[[File:DesignFlowSingle.png|frame|center|'''Figure 4: Rubric Statistic Design Flow - '''Instructor wants to view student scores on individual rubric criteria.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png|frame|center|'''Figure 5: Cross-Assignment Comparison Design Flow - '''Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments.]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries are given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123992</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123992"/>
		<updated>2019-04-13T02:02:50Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Design Flow */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to fine-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
==== Interactive Example ====&lt;br /&gt;
&lt;br /&gt;
   https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
==== New View Examples ====&lt;br /&gt;
&lt;br /&gt;
[[File:AnalyzeAssignmentNew.png|frame|centre|Figure 2: New Rubric Statistic Visualization\n Added in the center of the existing two charts is an interactive chart the instructor can use to see the mean or median scores for whichever criteria they select. This is done on the &amp;quot;Analyze Assignment&amp;quot; tab, which is selected by default when the &amp;quot;View Scores&amp;quot; page is loaded.]]&lt;br /&gt;
&lt;br /&gt;
[[File:CompareAssignmentsNew.png|frame|centre|Figure 3: New Rubric Cross-Assignment Comparison Visualization\n The instructor can see a comparison between selected criteria between the current assignment and the selected assignment. The rubric criteria must be compatible in order for it to even show up in the selection list. This comparison visualization is done on the &amp;quot;Compare Assignments&amp;quot; tab which must be selected after the &amp;quot;View Scores&amp;quot; page has been loaded.]]&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
During the integration of rubric statistics and assignment grade statistics, this project expects to change the grades_controller file, an unspecified number of files in the views/grades subdirectory, assets/javascripts/grading.js, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
[[File:DesignFlowSingle.png|frame|center|Figure 4: Instructor wants to view student scores on individual rubric criteria.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png|frame|center|Figure 5: Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments.]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries are given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123661</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123661"/>
		<updated>2019-04-09T00:49:44Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to fine-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
During the integration of rubric statistics and assignment grade statistics, this project expects to change the grades_controller file, an unspecified number of files in the views/grades subdirectory, assets/javascripts/grading.js, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
[[File:DesignFlowSingle.png|frame|center|Figure 2: Instructor wants to view student scores on individual rubric criteria.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png|frame|center|Figure 3: Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments.]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries are given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123613</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123613"/>
		<updated>2019-04-08T17:11:40Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
It is the desire of all instructors to emphasize course material that students have trouble understanding and de-emphasize those aspects of the course material which students readily grasp. One method used by instructors is the creation of questionnaires, or rubrics. A rubric consists of a number of questions, or criterion, that give instructors a glimpse into student understanding of course materials. Use of rubrics and their association with a course assignment allow instructors to find-tune their lesson plans to their students' understanding.&lt;br /&gt;
&lt;br /&gt;
Creation of assignments, and their associated rubrics, can be a daunting task that can be made easier through the use of online platforms. Expertiza is one such online assignment grading platform. Within Expertiza, instructors create courses and assignments. For each assignment, instructors create one or more peer review rubrics for students to complete. After each round of rubrics, students can submit changes to their assignment based on these rubrics, with each submission and rubric considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors using Expertiza display assignment scores on one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores. This, in turn, minimizes the likelihood that instructors will integrate this information to fine-tune their course material.&lt;br /&gt;
&lt;br /&gt;
This project proposes to overcome this weakness in Expertiza by integrating the display of assignment scores and rubric scores onto a single page. This integration will allow instructors to more easily associate low rubric average scores with assignment scores. The ability to visualize assignment scores and rubric scores in a single location will reduce the workload on instructors when the scores. This, in turn, will increase the likelihood that instructors will change their lesson plans to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries is given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123610</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123610"/>
		<updated>2019-04-08T16:43:46Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires, or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average score on a rubric's particular question, or criterion, can indicate that the class has issues with a particular part of the assignment. Currently, instructors can display assignment score one pages, but need to visit a completely separate page to display rubric scores. This separation of information hinders the instructor's ability to fully comprehend the associations between the assignment scores and the rubric scores.&lt;br /&gt;
&lt;br /&gt;
This project proposes to integrate the display of assignment scores and rubric scores onto a single page so that instructors can more easily associate low rubric averages with assignment scores. Allowing easier visualizations will reduce the workload of instructors and increase the chances that instructors change their lesson plan to reflect the students' understanding of the course material.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries is given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123609</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123609"/>
		<updated>2019-04-08T16:35:05Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires, or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds with each round associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the submitted rubric(s) associated with the assignment to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubric scores is on a second page. This project proposes to integrate the assignment grades and rubric scores so that instructor visualizations are easier.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries is given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123600</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123600"/>
		<updated>2019-04-08T15:02:24Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Tools and Design Choices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choices ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Examples of client-side visualization libraries is given below:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123599</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123599"/>
		<updated>2019-04-08T14:59:38Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Tools and Design Choice */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
This project proposes using a third party JavaScript library for rendering the rubric statistics. This project proposes two requirements for the visualization library. The first requirement is to use a visualization library that performs client-side rendering. Using a client-side rendering library will minimize the number of server interactions as the instructor changes which rubric statistics to display. This minimization of server interaction will maximize the response time of Expertiza.&lt;br /&gt;
&lt;br /&gt;
The second requirement for the visualization library is compatibility with current Expertiza graphics. The compatibility requirement implies that the visualization library is one that is already being used in Expertiza or a visualization library that could be used to render the current graphics.&lt;br /&gt;
&lt;br /&gt;
Below, is a list of client-side visualization libraries that this project will examine:&lt;br /&gt;
&lt;br /&gt;
    Highcharts (http://www.highcharts.com/)&lt;br /&gt;
    RaphaelJS (http://g.raphaeljs.com/)&lt;br /&gt;
    dygraphs (http://dygraphs.com/)&lt;br /&gt;
    Protovis (http://vis.stanford.edu/protovis/)&lt;br /&gt;
    Grafico (http://grafico.kilianvalkhof.com/)&lt;br /&gt;
    ChartKick (https://chartkick.com/)&lt;br /&gt;
    VanCharts (http://www.vancharts.com/)&lt;br /&gt;
    GoogleCharts (https://developers.google.com/chart/)&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123594</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123594"/>
		<updated>2019-04-08T11:31:19Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Test Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
This project proposes using a third party library for displaying the rubric statistics. The criteria for this third party library will include TBS.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123593</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123593"/>
		<updated>2019-04-08T11:30:34Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Files Involved */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
This project proposes using a third party library for displaying the rubric statistics. The criteria for this third party library will include TBS.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123592</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123592"/>
		<updated>2019-04-08T11:29:35Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
This project proposes using a third party library for displaying the rubric statistics. The criteria for this third party library will include TBS.&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123591</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123591"/>
		<updated>2019-04-08T11:26:13Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
This project expects to change controller files, view files, JavaScript files, and RSpec files. This project does not expect to change any model files, though models will be changed if model data needs to be reformatted. This project does not expect to change the database.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
This project proposes using a third party library for displaying the rubric statistics. The criteria for this third party library will include TBS.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123590</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123590"/>
		<updated>2019-04-08T11:21:13Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
This project proposes using a third party library for displaying the rubric statistics. The criteria for this third party library will include TBS.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123589</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123589"/>
		<updated>2019-04-08T11:14:16Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Proposed Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project integrate rubric statistics to the above assignment grade view. Rubric statistic integration into the assignment grade view allow two types of visualizations. The first visualization allows the instructor to display rubric statistics within a single assignment. The second visualization allows the instructor to display rubric statistics between different assignments in the same course.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Assignment Grade Visualization ===&lt;br /&gt;
&lt;br /&gt;
This project proposes the integration of rubric statistic visualization for both single assignments and multiple assignments into the assignment grade view. The integration occurs with a single change to the header of the assignment grade view, and retains the list of student grades. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123588</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123588"/>
		<updated>2019-04-08T10:58:43Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Proposed Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
=== Existing Views ===&lt;br /&gt;
&lt;br /&gt;
In both cases, the project will add rubric statistics to the assignment grade view. The current assignment grade view consists of a header containing grade statistics followed by a table of the individual grades. In the assignment grade view header, the left side fo the header shows the average assignment grade as a circle, while the right side of the assignment grade view header shows the assignment grade distribution. Figure 1 shows the current header in the grade assignment view page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Existing_Assignment_Grades.JPG|frame|centre|Figure 1: Existing assignment grade page header. The existing assignment grade page header has both the average grade for the assignment and the grade distribution for the assignment. The left side shows the average as the percentage of a circle. The right side of the header shows the grade distribution for the assignment. The grade distribution shows the minimum and maximum grade for the assignment. Under the header is a list of the grades for each student.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The changes proposed by this project add rubric statistics to this assignment grade view. This project proposes to integrate rubric statistics visualization within a single assignment and to integrate rubric statistics visualization between multiple assignments.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Changes for Single Assignment ===&lt;br /&gt;
&lt;br /&gt;
The first visualization change proposed by this project is the integration of rubric statistic visualization within a single assignment. The rubric statistics are integrated into the assignment grade view header. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/single.html&lt;br /&gt;
&lt;br /&gt;
The rubric statistics are shown in the upper middle section of the header, while the options used to filter out the statistics are shown in the lower middle section of the header. The left and right side of the header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consists of five criteria, while the rubric in round 2 consists of 4 criteria. The drop-down menu on the left side selects the round of interest. The radio buttons next to each criterion selects the bar graphs shown. The bar graphs represent the percentage score of the selected criterion. Finally, the drop-down menu on the right side selects the statistic shown. This project proposes that the rubric statistic be limited to either the mean of the score or the median of the score. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
=== Proposed Changes for Multiple Assignments ===&lt;br /&gt;
&lt;br /&gt;
Along with the integration of the rubric statistics within a single assignment, this project also proposes integrating rubric statistic visualizations between multiple assignments. The rubric statistics are integrated into the assignment grade view header. The following HTML mock-up shows the proposed changes to the header. The list of student grades is not changed and therefore not shown.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/tabs.html&lt;br /&gt;
&lt;br /&gt;
The upper part of the rubric statistic visualization displays a set of tabs that allow the instructor to analyze the rubric within a single assignment or to compare the rubric statistics between multiple assignments. The middle part of the rubric statistic visualization displays the statistics for each selected criteria as a bar graph. The heights of the bars are shown as a percentage of the maximum value for each criteria. The bottom part of the rubric statistic visualization displays a set of options that allow the instructor to filter the statistics shown in the bar graph. The left side (assignment average) and right side (assignment distribution) of the assignment grade view header are not changed.&lt;br /&gt;
&lt;br /&gt;
In the integration of the rubric statistic visualization mock-up within a single assignment, there are two rounds of rubrics for the students to fill out. The rubric in round 1 consisted of five criteria, while the rubric in round 2 consisted of 4 criteria. The round of interest is selected using the drop-down menu on the left side. The criteria shown in the bar graph are selected using radio buttons next to each criterion. Finally, the type of statistic shown is selected using a drop-down menu on the right side of the options. Currently, the statistic is limited to either mean or median. Hovering the mouse over each of the bars in the bar graph shows the numerical value of the chosen statistic.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics within a single assignment starts by selecting the left tab titled &amp;quot;Analyze Assignment&amp;quot;. The default displays the mean of all criteria from the first round. Changing the round, the type of statistic, and the particular criteria are controlled from the drop-down menus and radio buttons below the bar graph.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics between assignments starts by selecting the right tab titled &amp;quot;Compare Assignments&amp;quot;. The default displays the comparisons between round one and all criteria of an assignment in the same course. The default assignment is the chronologically earliest assignment. The current assignment is shown in red while the rubric being compared is shown in blue.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
Instructor wants to view student scores on individual rubric criteria:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowSingle.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instructor wants to compare student scores on individual rubric criteria between two compatible rounds of two different assignments:&lt;br /&gt;
&lt;br /&gt;
[[File:DesignFlowCompare.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Existing_Assignment_Grades.JPG&amp;diff=123542</id>
		<title>File:Existing Assignment Grades.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Existing_Assignment_Grades.JPG&amp;diff=123542"/>
		<updated>2019-04-08T02:49:49Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123495</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123495"/>
		<updated>2019-04-08T02:06:10Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Existing View and Proposed Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Existing Views and Proposed Changes ==&lt;br /&gt;
To help instructors understand the relationship between assignment scores and rubric scores, this project proposes two types of visualizations. The first type of visualization allows instructors to examine the rubric statistics for a single assignment. The second type of visualization allows instructors to compare the rubric statistics between two different assignments when the criteria for each assignment is the same.&lt;br /&gt;
&lt;br /&gt;
Visualizing the rubric statistics for a single assignment is accomplished by adding the rubric statistics to the assignment grade view.&lt;br /&gt;
&lt;br /&gt;
https://jwarren3.github.io/expertiza/single.html&lt;br /&gt;
&lt;br /&gt;
The visualizations are divided into two separate features. The first feature displays a statistic for each criteria in a given assignment rubric. Currently, the view only displays the overall average and a distribution of the scores from each student. This project adds the mean (or median) for each criteria within the chosen rubric.&lt;br /&gt;
&lt;br /&gt;
The second feature of the project is ability to visualize different rubric criteria for different assignments in the same course.&lt;br /&gt;
The visualizations will be implemented as either a single or stacked bar chart with a bar for each of the selected criteria to be observed. If a single bar, then the height of the bar will be the total class average, but a stacked bar chart may be better to show the percentage of the class that received each score.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. On clicking Manage and then on assignments, following page appears.&lt;br /&gt;
&lt;br /&gt;
2. Click on 'view score' icon of an assignment. The summary report page of the selected assignment comes up.&lt;br /&gt;
&lt;br /&gt;
3. Following are mockup screens which we wish to create:&lt;br /&gt;
&lt;br /&gt;
a) Instructor would select the round and rubric criteria of the assignment for which he/she wants to view the class performance.&lt;br /&gt;
 &lt;br /&gt;
b) The bar graph of the class performance for those criteria would be displayed.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
The flowchart representing graphical flow of an instructor visiting view scores under assignments is given below:&lt;br /&gt;
&lt;br /&gt;
[[File:A3.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123468</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123468"/>
		<updated>2019-04-08T01:43:29Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
The visualizations are divided into two separate features. The first feature displays a statistic for each criteria in a given assignment rubric. Currently, the view only displays the overall average and a distribution of the scores from each student. This project adds the mean (or median) for each criteria within the chosen rubric.&lt;br /&gt;
&lt;br /&gt;
The second feature of the project is ability to visualize different rubric criteria for different assignments in the same course.&lt;br /&gt;
The visualizations will be implemented as either a single or stacked bar chart with a bar for each of the selected criteria to be observed. If a single bar, then the height of the bar will be the total class average, but a stacked bar chart may be better to show the percentage of the class that received each score.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. On clicking Manage and then on assignments, following page appears.&lt;br /&gt;
&lt;br /&gt;
2. Click on 'view score' icon of an assignment. The summary report page of the selected assignment comes up.&lt;br /&gt;
&lt;br /&gt;
3. Following are mockup screens which we wish to create:&lt;br /&gt;
&lt;br /&gt;
a) Instructor would select the round and rubric criteria of the assignment for which he/she wants to view the class performance.&lt;br /&gt;
 &lt;br /&gt;
b) The bar graph of the class performance for those criteria would be displayed.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
The flowchart representing graphical flow of an instructor visiting view scores under assignments is given below:&lt;br /&gt;
&lt;br /&gt;
[[File:A3.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123467</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123467"/>
		<updated>2019-04-08T01:43:17Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online, assignment, grading platform for courses associated with instructors. Each instructor creates courses and assignments associated with those courses. For each assignment, students peer review other students' assignments via questionnaires or rubrics. After each round of rubrics, students can submit changes to their assignment based on these rubrics. Each submission and rubric is considered a round. Hence, assignments have multiple rounds each associated with a rubric.&lt;br /&gt;
&lt;br /&gt;
Instructors use the association between the assignment and the rubrics to understand what subjects need more focus. For example, a low average on a particular question, or criterion, on a rubric can indicate that the class has issues with a particular part of the assignment. Currently, the information about assignment grades is on one pages, while the information on rubrics is on a second page. This project intends to make the visualization of assignment grades and rubric scores easier by showing rubric statistics on the assignment grade page.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
The visualizations are divided into two separate features. The first feature displays a statistic for each criteria in a given assignment rubric. Currently, the view only displays the overall average and a distribution of the scores from each student. This project adds the mean (or median) for each criteria within the chosen rubric.&lt;br /&gt;
&lt;br /&gt;
The second feature of the project is ability to visualize different rubric criteria for different assignments in the same course.&lt;br /&gt;
The visualizations will be implemented as either a single or stacked bar chart with a bar for each of the selected criteria to be observed. If a single bar, then the height of the bar will be the total class average, but a stacked bar chart may be better to show the percentage of the class that received each score.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. On clicking Manage and then on assignments, following page appears.&lt;br /&gt;
&lt;br /&gt;
2. Click on 'view score' icon of an assignment. The summary report page of the selected assignment comes up.&lt;br /&gt;
&lt;br /&gt;
3. Following are mockup screens which we wish to create:&lt;br /&gt;
&lt;br /&gt;
a) Instructor would select the round and rubric criteria of the assignment for which he/she wants to view the class performance.&lt;br /&gt;
 &lt;br /&gt;
b) The bar graph of the class performance for those criteria would be displayed.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
The flowchart representing graphical flow of an instructor visiting view scores under assignments is given below:&lt;br /&gt;
&lt;br /&gt;
[[File:A3.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123457</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123457"/>
		<updated>2019-04-08T00:18:23Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online assignment grading platform for courses associated with instructors. Each instructor can create a course. Within each course instructors create assignments and within each assignment, instructors can create review rounds. During each round, the instructor designs a rubric so that students can review. Instructors can create assignments and implement peer reviews for submitted assignments. This project concerns the creation of a system for visualizing student performance on those assignments, primarily as graded in peer reviews. Graphs will be made to show various rubric criteria and the class' performance on the criteria. If the criteria are the same for multiple stages of review, an instructor should be able to compare performance over time or between reviews. Our task is to provide an interactive visualization or a table for instructors that shows how their class performed on selected rubric criteria. Such feature would be immensely helpful for instructors as it would assist them to identify what they need to focus more attention on. For example, creating a graph showing the average scores for all or a certain subset of main rubric criteria (questionnaire). If the average score of the class on selected criteria (question) is low means the instructor can emphasize more on the learning materials related to it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
The visualizations are divided into two separate features. The first feature displays a statistic for each criteria in a given assignment rubric. Currently, the view only displays the overall average and a distribution of the scores from each student. This project adds the mean (or median) for each criteria within the chosen rubric.&lt;br /&gt;
&lt;br /&gt;
The second feature of the project is ability to visualize different rubric criteria for different assignments in the same course.&lt;br /&gt;
The visualizations will be implemented as either a single or stacked bar chart with a bar for each of the selected criteria to be observed. If a single bar, then the height of the bar will be the total class average, but a stacked bar chart may be better to show the percentage of the class that received each score.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. On clicking Manage and then on assignments, following page appears.&lt;br /&gt;
&lt;br /&gt;
2. Click on 'view score' icon of an assignment. The summary report page of the selected assignment comes up.&lt;br /&gt;
&lt;br /&gt;
3. Following are mockup screens which we wish to create:&lt;br /&gt;
&lt;br /&gt;
a) Instructor would select the round and rubric criteria of the assignment for which he/she wants to view the class performance.&lt;br /&gt;
 &lt;br /&gt;
b) The bar graph of the class performance for those criteria would be displayed.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
The flowchart representing graphical flow of an instructor visiting view scores under assignments is given below:&lt;br /&gt;
&lt;br /&gt;
[[File:A3.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123444</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123444"/>
		<updated>2019-04-07T23:26:48Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Proposed Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online assignment grading platform. Instructors can create assignments and implement peer reviews for submitted assignments. This project concerns the creation of a system for visualizing student performance on those assignments, primarily as graded in peer reviews. Graphs will be made to show various rubric criteria and the class' performance on the criteria. If the criteria are the same for multiple stages of review, an instructor should be able to compare performance over time or between reviews. Our task is to provide an interactive visualization or a table for instructors that shows how their class performed on selected rubric criteria. Such feature would be immensely helpful for instructors as it would assist them to identify what they need to focus more attention on. For example, creating a graph showing the average scores for all or a certain subset of main rubric criteria (questionnaire). If the average score of the class on selected criteria (question) is low means the instructor can emphasize more on the learning materials related to it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
The visualizations are divided into two separate features. The first feature displays a statistic for each criteria in a given assignment rubric. Currently, the view only displays the overall average and a distribution of the scores from each student. This project adds the mean (or median) for each criteria within the chosen rubric.&lt;br /&gt;
&lt;br /&gt;
The second feature of the project is ability to visualize different rubric criteria for different assignments in the same course.&lt;br /&gt;
The visualizations will be implemented as either a single or stacked bar chart with a bar for each of the selected criteria to be observed. If a single bar, then the height of the bar will be the total class average, but a stacked bar chart may be better to show the percentage of the class that received each score.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. On clicking Manage and then on assignments, following page appears.&lt;br /&gt;
&lt;br /&gt;
2. Click on 'view score' icon of an assignment. The summary report page of the selected assignment comes up.&lt;br /&gt;
&lt;br /&gt;
3. Following are mockup screens which we wish to create:&lt;br /&gt;
&lt;br /&gt;
a) Instructor would select the round and rubric criteria of the assignment for which he/she wants to view the class performance.&lt;br /&gt;
 &lt;br /&gt;
b) The bar graph of the class performance for those criteria would be displayed.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
The flowchart representing graphical flow of an instructor visiting view scores under assignments is given below:&lt;br /&gt;
&lt;br /&gt;
[[File:A3.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123438</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123438"/>
		<updated>2019-04-07T21:48:29Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Proposed Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online assignment grading platform. Instructors can create assignments and implement peer reviews for submitted assignments. This project concerns the creation of a system for visualizing student performance on those assignments, primarily as graded in peer reviews. Graphs will be made to show various rubric criteria and the class' performance on the criteria. If the criteria are the same for multiple stages of review, an instructor should be able to compare performance over time or between reviews. Our task is to provide an interactive visualization or a table for instructors that shows how their class performed on selected rubric criteria. Such feature would be immensely helpful for instructors as it would assist them to identify what they need to focus more attention on. For example, creating a graph showing the average scores for all or a certain subset of main rubric criteria (questionnaire). If the average score of the class on selected criteria (question) is low means the instructor can emphasize more on the learning materials related to it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
The visualizations are divided into two separate features. The first feature displays a statistic for each criteria in a given assignment rubric. Currently, the view only displays the overall average and a distribution of the scores from each student. This project adds the mean (or median) for each criteria within the chosen rubric.&lt;br /&gt;
&lt;br /&gt;
The visualizations will be implemented as either a single or stacked bar chart with a bar for each of the selected criteria to be observed. If a single bar, then the height of the bar will be the total class average, but a stacked bar chart may be better to show the percentage of the class that received each score.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. On clicking Manage and then on assignments, following page appears.&lt;br /&gt;
&lt;br /&gt;
2. Click on 'view score' icon of an assignment. The summary report page of the selected assignment comes up.&lt;br /&gt;
&lt;br /&gt;
3. Following are mockup screens which we wish to create:&lt;br /&gt;
&lt;br /&gt;
a) Instructor would select the round and rubric criteria of the assignment for which he/she wants to view the class performance.&lt;br /&gt;
 &lt;br /&gt;
b) The bar graph of the class performance for those criteria would be displayed.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
The flowchart representing graphical flow of an instructor visiting view scores under assignments is given below:&lt;br /&gt;
&lt;br /&gt;
[[File:A3.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests using frameworks RSpec and Capybara. In addition, we will perform manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
The RSpec Testing Framework, automated testing, will be used to verify the Models of the Expertiza Rails Web application feature set. Since this feature is dealing with Visualizations (charts) that is intimately tied with an Active Record Models, we will seed the Testing Database with known data via RSpec. These changes will be automatically rolled-back once the testing is complete.  &lt;br /&gt;
&lt;br /&gt;
=== Capybara Tests ===&lt;br /&gt;
Another automated testing framework that will be used is Capybara. Capybara is an browser type test to simulate a user clicking through your site. We will use this testing framework to verify that our charting object is present on the page and contains the seeded data that we had loaded.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
In addition to the automated tests above we will also perform manual testing of the newly added features to include:&lt;br /&gt;
&lt;br /&gt;
* Chart is displaying correctly&lt;br /&gt;
*# Bars are showing up where expected&lt;br /&gt;
*# Bar annotations are showing the expected value&lt;br /&gt;
*# Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
*# Hover text is displaying the correct values&lt;br /&gt;
*# Null values are not present on the chart&lt;br /&gt;
*# Correct colors are used for the multi-round view&lt;br /&gt;
* Show Labels checkbox works as expected&lt;br /&gt;
* Round Criteria is displaying correctly&lt;br /&gt;
*# Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
*# Selecting a round changes the criteria checkboxes&lt;br /&gt;
*# All checkboxes are displayed with appropriate text&lt;br /&gt;
*# Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123186</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123186"/>
		<updated>2019-04-04T17:44:39Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Expertiza is an online assignment grading platform. Instructors can create assignments and implement peer reviews for submitted assignments. This project concerns the creation of a system for visualizing student performance on those assignments, primarily as graded in peer reviews. Graphs will be made to show various rubric criteria and the class' performance on the criteria. If the criteria are the same for multiple stages of review, an instructor should be able to compare performance over time or between reviews. Our task is to provide an interactive visualization or a table for instructors that shows how their class performed on selected rubric criteria. Such feature would be immensely helpful for instructors as it would assist them to identify what they need to focus more attention on. For example, creating a graph showing the average scores for all or a certain subset of main rubric criteria (questionnaire). If the average score of the class on selected criteria (question) is low means the instructor can emphasize more on the learning materials related to it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Proposed Changes ==&lt;br /&gt;
The visualizations will be implemented as either a single or stacked bar chart with a bar for each of the selected criteria to be observed. If a single bar, then the height of the bar will be the total class average, but a stacked bar chart may be better to show the percentage of the class that received each score.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. On clicking Manage and then on assignments, following page appears.&lt;br /&gt;
&lt;br /&gt;
2. Click on 'view score' icon of an assignment. The summary report page of the selected assignment comes up.&lt;br /&gt;
&lt;br /&gt;
3. Following are mockup screens which we wish to create:&lt;br /&gt;
&lt;br /&gt;
a) Instructor would select the round and rubric criteria of the assignment for which he/she wants to view the class performance.&lt;br /&gt;
 &lt;br /&gt;
b) The bar graph of the class performance for those criteria would be displayed.&lt;br /&gt;
&lt;br /&gt;
== Project Design ==&lt;br /&gt;
 The changes made to the expertiza project will primarily include HTML/ERB changes to the view files to accommodate the added charts on the page and the necessary javascript to allow responsive design. Brief controller modifications will be made to facilitate database filtering to get the displayed data.&lt;br /&gt;
&lt;br /&gt;
=== Design Flow ===&lt;br /&gt;
The flowchart representing graphical flow of an instructor visiting view scores under assignments is given below:&lt;br /&gt;
&lt;br /&gt;
[[File:A3.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tools and Design Choice ===&lt;br /&gt;
We have used the lightweight [https://developers.google.com/chart/ Google Charts] library for displaying the chart data on the page, with standard HTML for all of the options and dropdowns for option selection. Google Charts was chosen because of its high compatibility, full option set, and comparable graphical quality to the rest of expertiza while keeping a small JS footprint, which should help prevent slow page responsiveness.&lt;br /&gt;
&lt;br /&gt;
=== Visualization ===&lt;br /&gt;
The following graph shows the view of the 'view scores' page after the modifications. The instructor selects a subset of rubric criteria for which he/she wants to know how a class performed for a particular round. A bar graph of the average score of the class for that subset of criteria is displayed. &lt;br /&gt;
&lt;br /&gt;
The above graph shows an average score of the class for 10 rubric criteria in Round 1 for assignment &amp;quot;OSS project/Writing assignment 2&amp;quot; selected by the instructor. A live demo with randomly generated data can be found on [https://jsfiddle.net/Jereman/5uxqr92y/ JSFiddle]&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
The team plans to perform both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Framework Tests ===&lt;br /&gt;
Automated tests, using the RSpec framework, will be run against our project changes. Both test-driven development (TDD) and behavior-driven development (BDD) will be used during the project. For each existing model/controller that is changed in the project, the team will ensure that existing unit/integration test specs still pass and create additional tests to ensure that new functionality is working correctly. For each new model/controller, the team will create new unit/integration tests and ensure both 100% code coverage and complete testing of functionality.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;br /&gt;
&lt;br /&gt;
== Files Involved ==&lt;br /&gt;
We have implemented a new partial file criteria_charts to the team_chart that display the bar graph with existing data collected by the grades controller methods to the view page.&lt;br /&gt;
&lt;br /&gt;
Modified files:&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
app/controllers/grades_controller.rb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_teams.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_criteria_charts.html.erb&lt;br /&gt;
&lt;br /&gt;
app/views/grades/_team_charts.html.erb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_criteria_charts.html.erb ===&lt;br /&gt;
 &amp;lt;html&amp;gt;&lt;br /&gt;
  &amp;lt;head&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;chartdata_information&amp;quot;, data: {chartdata: @chartdata} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;%= content_tag :div, class: &amp;quot;text_information&amp;quot;, data: {text: @text} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;%= content_tag :div, class: &amp;quot;minmax_information&amp;quot;, data: {minmax: @minmax} do %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
 &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;https://www.gstatic.com/charts/loader.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
      google.charts.load('current', {packages: ['corechart', 'bar']});&lt;br /&gt;
       //Display Options&lt;br /&gt;
      var showLabels = true;&lt;br /&gt;
      var barColors = [ // Other colors generated from the expertiza base red&lt;br /&gt;
          '#A90201',    // using paletton.com&lt;br /&gt;
          '#018701',&lt;br /&gt;
          '#016565',&lt;br /&gt;
          '#A94D01'&lt;br /&gt;
      ];&lt;br /&gt;
      function getData(){ //Loads all chart data from the page&lt;br /&gt;
        chartData = $('.chartdata_information').data('chartdata');&lt;br /&gt;
        chartText = $('.text_information').data('text');&lt;br /&gt;
        chartRange = $('.minmax_information').data('minmax');&lt;br /&gt;
 for (var i = 0; i &amp;lt; chartData.length; i++){ //Set all the criteriaSelected to true&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for (var j = 0; j &amp;lt; chartData[i].length; j++){&lt;br /&gt;
            criteria.push(true);&lt;br /&gt;
          }&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       function generateData() {	//Generates random data for testing&lt;br /&gt;
        var rounds = 3;&lt;br /&gt;
        for(var i = 0; i &amp;lt; rounds; i++) {&lt;br /&gt;
  var criteriaNum = Math.floor(Math.random() * 5 + 5);  //Random number of criteria&lt;br /&gt;
          var round = [];&lt;br /&gt;
          var criteria = [];&lt;br /&gt;
          for(var j = 0; j &amp;lt; criteriaNum; j++) {&lt;br /&gt;
  round.push(Math.floor(Math.random() * 101));  //Random score for each criterion&lt;br /&gt;
            criteria.push(true);  //Everything starts out true&lt;br /&gt;
          }&lt;br /&gt;
          chartData.push(round);&lt;br /&gt;
          criteriaSelected.push(criteria);&lt;br /&gt;
 &lt;br /&gt;
        chartOptions = {		//Render options for the chart&lt;br /&gt;
          title: 'Class Average on Criteria',&lt;br /&gt;
          titleTextStyle: {&lt;br /&gt;
  fontName: 'arial',&lt;br /&gt;
            fontSize: 18,&lt;br /&gt;
            italic: false,&lt;br /&gt;
            bold: true&lt;br /&gt;
         chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));&lt;br /&gt;
        var checkBox = document.getElementById(&amp;quot;labelCheck&amp;quot;);&lt;br /&gt;
        checkBox.checked = true;&lt;br /&gt;
        checkBox.style.display = &amp;quot;inline&amp;quot;;&lt;br /&gt;
        updateChart(currentRound);&lt;br /&gt;
        loadRounds(); }&lt;br /&gt;
 function updateChart(roundNum) {	//Updates the chart with a new round number and renders&lt;br /&gt;
        currentRound = roundNum;&lt;br /&gt;
        renderChart();&lt;br /&gt;
        loadCriteria();&lt;br /&gt;
      function renderChart() {	//Renders the chart if changes have been made&lt;br /&gt;
          var data = loadData();&lt;br /&gt;
 chartOptions.vAxis.viewWindow.max = 5;&lt;br /&gt;
          chartOptions.vAxis.viewWindow.min = 0;&lt;br /&gt;
          if (chartRange[currentRound]) { //Set axis ranges if they exist&lt;br /&gt;
              if (chartRange[currentRound][1])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.max = chartRange[currentRound][1];&lt;br /&gt;
 if (chartRange[currentRound][0])&lt;br /&gt;
                  chartOptions.vAxis.viewWindow.min = chartRange[currentRound][0];&lt;br /&gt;
 }&lt;br /&gt;
          chart.draw(data, chartOptions);&lt;br /&gt;
      }&lt;br /&gt;
 &lt;br /&gt;
           chartOptions.hAxis.ticks = [];&lt;br /&gt;
          var rowCount = 1;&lt;br /&gt;
 for(var i = 0; i &amp;lt; chartData[currentRound].length; i++) { //Add a chart row for each criterion if not null&lt;br /&gt;
              if (criteriaSelected[currentRound][i] &amp;amp;&amp;amp; chartData[currentRound][i]) {&lt;br /&gt;
  data.addRow([rowCount, chartData[currentRound][i], barColors[0], (showLabels) ? chartData[currentRound][i].toFixed(1).toString() : &amp;quot;&amp;quot;]);&lt;br /&gt;
                  chartOptions.hAxis.ticks.push({v: rowCount++, f: (i+1).toString()});&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
 &lt;br /&gt;
          var data = new google.visualization.DataTable();&lt;br /&gt;
          data.addColumn('number', 'Criterion');&lt;br /&gt;
          var i;&lt;br /&gt;
 for(i = 0; i &amp;lt; roundNum; i++) { //Add all columns for the data&lt;br /&gt;
              data.addColumn('number', 'Round ' + (i+1).toString());&lt;br /&gt;
              data.addColumn({type: 'string', role: 'style'});	//column for specifying the bar color&lt;br /&gt;
              data.addColumn({type: 'string', role: 'annotation'});&lt;br /&gt;
 &lt;br /&gt;
              var newRow = [];&lt;br /&gt;
              var elementsAdded = false;&lt;br /&gt;
              newRow.push(rowCount);&lt;br /&gt;
 for(var j = 0; j &amp;lt; roundNum; j++) { //If the round has the criterion, add it&lt;br /&gt;
                  if (chartData[j][i]) {&lt;br /&gt;
                      newRow.push(chartData[j][i]);&lt;br /&gt;
                      elementsAdded = true;&lt;br /&gt;
                  } else {&lt;br /&gt;
                      newRow.push(null);&lt;br /&gt;
                  }&lt;br /&gt;
  newRow.push(barColors[j % barColors.length]); //Add column color&lt;br /&gt;
                  if (chartData[j] &amp;amp;&amp;amp; chartData[j][i] &amp;amp;&amp;amp; showLabels)&lt;br /&gt;
  newRow.push(chartData[j][i].toFixed(1).toString()); //Add column annotations&lt;br /&gt;
                  else&lt;br /&gt;
                      newRow.push(&amp;quot;&amp;quot;);&lt;br /&gt;
              }&lt;br /&gt;
       function loadCriteria() {	//Creates the criteria check boxes&lt;br /&gt;
          var form = document.getElementById(&amp;quot;chartCriteria&amp;quot;);&lt;br /&gt;
 while (form.firstChild) //Clear out the old check boxes&lt;br /&gt;
              form.removeChild(form.firstChild);&lt;br /&gt;
 if (currentRound == -1) //Don't show criteria for 'all rounds'&lt;br /&gt;
              return;&lt;br /&gt;
          chartData[currentRound].forEach(function(dat, i) {&lt;br /&gt;
              var checkbox = document.createElement('input');&lt;br /&gt;
              checkbox.type = &amp;quot;checkbox&amp;quot;;&lt;br /&gt;
              checkbox.id = &amp;quot;checkboxoption&amp;quot; + i;&lt;br /&gt;
 checkbox.onclick = function() { //Register callback to toggle the criterion&lt;br /&gt;
                  checkboxUpdate(i);&lt;br /&gt;
              }&lt;br /&gt;
              var label = document.createElement('label')&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;form id=&amp;quot;chartOptions&amp;quot; name=&amp;quot;chartOptions&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;select id=&amp;quot;chartRounds&amp;quot; name=&amp;quot;rounds&amp;quot; &lt;br /&gt;
 onChange=&amp;quot;updateChart(document.chartOptions.chartRounds.options[document.chartOptions.chartRounds.options.selectedIndex].value)&amp;quot; style = &amp;quot;display: none&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;/select&amp;gt;&lt;br /&gt;
 &amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; id = &amp;quot;labelCheck&amp;quot; checked=&amp;quot;checked&amp;quot; style=&amp;quot;display: none&amp;quot; onclick=&amp;quot;showLabels = !showLabels; renderChart();&amp;quot;&amp;gt;Show &lt;br /&gt;
 Labels&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;/form&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;chartCriteria&amp;quot; name=&amp;quot;chartCriteria&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== app/controllers/grades_controller.rb ===&lt;br /&gt;
&lt;br /&gt;
 def action_allowed?&lt;br /&gt;
     case params[:action]&lt;br /&gt;
     when 'view_my_scores'&lt;br /&gt;
       ['Instructor',&lt;br /&gt;
        'Teaching Assistant',&lt;br /&gt;
        'Administrator',&lt;br /&gt;
        'Super-Administrator',&lt;br /&gt;
       'Student'].include? current_role_name and&lt;br /&gt;
        are_needed_authorizations_present?(params[:id], &amp;quot;reader&amp;quot;, &amp;quot;reviewer&amp;quot;) and&lt;br /&gt;
        check_self_review_status&lt;br /&gt;
 when 'view_team'&lt;br /&gt;
      if ['Student'].include? current_role_name # students can only see the head map for their own team&lt;br /&gt;
        participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
        session[:user].id == participant.user_id&lt;br /&gt;
      else&lt;br /&gt;
 true&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      ['Instructor',&lt;br /&gt;
       'Teaching Assistant',&lt;br /&gt;
       'Administrator',&lt;br /&gt;
       'Super-Administrator'].include? current_role_name&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
   # collects the question text for display on the chart&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_text&lt;br /&gt;
     @text = []&lt;br /&gt;
     (1..@assignment.num_review_rounds).to_a.each do |round|&lt;br /&gt;
       question = @questions[('review' + round.to_s).to_sym]&lt;br /&gt;
       @text[round - 1] = []&lt;br /&gt;
       next if question.nil?&lt;br /&gt;
       (0..(question.length - 1)).to_a.each do |q|&lt;br /&gt;
         @text[round - 1][q] = question[q].txt&lt;br /&gt;
       end&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   # find the maximum and minimum scores for each questionnaire round&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_minmax(questionnaires)&lt;br /&gt;
     @minmax = []&lt;br /&gt;
     questionnaires.each do |questionnaire|&lt;br /&gt;
      next if questionnaire.symbol != :review&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      next if round.nil?&lt;br /&gt;
  @minmax[round - 1] = []&lt;br /&gt;
      @minmax[round - 1][0] = if !questionnaire.min_question_score.nil? and questionnaire.min_question_score &amp;lt; 0&lt;br /&gt;
                                questionnaire.min_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                0&lt;br /&gt;
                              end&lt;br /&gt;
      @minmax[round - 1][1] = if !questionnaire.max_question_score.nil?&lt;br /&gt;
                                questionnaire.max_question_score&lt;br /&gt;
                              else&lt;br /&gt;
                                5&lt;br /&gt;
                              end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 # this method collects and averages all the review scores across teams&lt;br /&gt;
   # Added as part of E1859&lt;br /&gt;
   def assign_chart_data&lt;br /&gt;
     @rounds = @assignment.num_review_rounds&lt;br /&gt;
     @chartdata = []&lt;br /&gt;
     (1..@rounds).to_a.each do |round|&lt;br /&gt;
       @teams = AssignmentTeam.where(parent_id: @assignment.id)&lt;br /&gt;
       @teamids = []&lt;br /&gt;
       @result = []&lt;br /&gt;
       @responseids = []&lt;br /&gt;
       @scoreviews = []&lt;br /&gt;
       (0..(@teams.length - 1)).to_a.each do |t|&lt;br /&gt;
         @teamids[t] = @teams[t].id&lt;br /&gt;
         @result[t] = ResponseMap.find_by_sql [&amp;quot;SELECT id FROM response_maps&lt;br /&gt;
           WHERE type = 'ReviewResponseMap' AND reviewee_id = ?&amp;quot;, @teamids[t]]&lt;br /&gt;
         @responseids[t] = []&lt;br /&gt;
         @scoreviews[t] = []&lt;br /&gt;
         (0..(@result[t].length - 1)).to_a.each do |r|&lt;br /&gt;
           @responseids[t][r] = Response.find_by_sql [&amp;quot;SELECT id FROM responses&lt;br /&gt;
             WHERE round = ? AND map_id = ?&amp;quot;, round, @result[t][r]]&lt;br /&gt;
          @scoreviews[t][r] = Answer.where(response_id: @responseids[t][r][0]) unless @responseids[t][r].empty?&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      @chartdata[round - 1] = []&lt;br /&gt;
      # because the nth first elements could be nil&lt;br /&gt;
      # iterate until a non-nil value is found or move to next round&lt;br /&gt;
      t = 0&lt;br /&gt;
      r = 0&lt;br /&gt;
 t += 1 while @scoreviews[t].nil?&lt;br /&gt;
      while t &amp;lt; @scoreviews.length and @scoreviews[t][r].nil?&lt;br /&gt;
        if r &amp;lt; @scoreviews[t].length - 1&lt;br /&gt;
          r += 1&lt;br /&gt;
        else&lt;br /&gt;
 def assign_chart_data&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      next if t &amp;gt;= @scoreviews.length&lt;br /&gt;
 (0..(@scoreviews[t][r].length - 1)).to_a.each do |q|&lt;br /&gt;
        sum = 0&lt;br /&gt;
        counter = 0&lt;br /&gt;
 def retrieve_questions(questionnaires)&lt;br /&gt;
    questionnaires.each do |questionnaire|&lt;br /&gt;
      round = AssignmentQuestionnaire.where(assignment_id: @assignment.id, questionnaire_id: questionnaire.id).first.used_in_round&lt;br /&gt;
      questionnaire_symbol = if !round.nil?&lt;br /&gt;
                         (questionnaire.symbol.to_s + round.to_s).to_sym&lt;br /&gt;
                             else&lt;br /&gt;
                               questionnaire.symbol&lt;br /&gt;
                             end&lt;br /&gt;
      @questions[questionnaire_symbol] = questionnaire.questions&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
 def update&lt;br /&gt;
    if format(&amp;quot;%.2f&amp;quot;, total_score) != params[:participant][:grade]&lt;br /&gt;
      participant.update_attribute(:grade, params[:participant][:grade])&lt;br /&gt;
      message = if participant.grade.nil?&lt;br /&gt;
           &amp;quot;The computed score will be used for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                  &amp;quot;A score of &amp;quot; + params[:participant][:grade] + &amp;quot;% has been saved for &amp;quot; + participant.user.name + &amp;quot;.&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
    end&lt;br /&gt;
    flash[:note] = message&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
&lt;br /&gt;
=== app/views/grades/_team_charts.html.erb ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;%= render :partial =&amp;gt; 'criteria_charts' %&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;a href=&amp;quot;#&amp;quot; name='team-chartLink' onClick=&amp;quot;toggleElement('team-chart', 'stats');return false;&amp;quot;&amp;gt;Hide stats&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;TR style =&amp;quot;background-color: white;&amp;quot; class=&amp;quot;team&amp;quot; id=&amp;quot;team-chart&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;div class=&amp;quot;circle&amp;quot; id=&amp;quot;average-score&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
      Class Average&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH COLSPAN=&amp;quot;8&amp;quot;&amp;gt;&lt;br /&gt;
    	&amp;lt;img src=&amp;quot;&amp;lt;%= @average_chart  %&amp;gt;&amp;quot; &amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    	Class Distribution&lt;br /&gt;
    	&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;TH WIDTH=&amp;quot;9&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
  &amp;lt;/TR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var myCircle = Circles.create({&lt;br /&gt;
      id:           'average-score',&lt;br /&gt;
      radius:       50,&lt;br /&gt;
      value:        &amp;lt;%= @avg_of_avg.to_i %&amp;gt;,&lt;br /&gt;
      maxValue:     100,&lt;br /&gt;
      width:        15,&lt;br /&gt;
      text:         '&amp;lt;%=@avg_of_avg.to_i%&amp;gt;',&lt;br /&gt;
      colors:       ['#FFEB99', '#FFCC00'],&lt;br /&gt;
      duration:       700,&lt;br /&gt;
      textClass:      'circles-final'&lt;br /&gt;
    });&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;style&amp;gt;&lt;br /&gt;
   .circles-final{&lt;br /&gt;
      font-size: 16px !important;&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test Results ==&lt;br /&gt;
The team ran both automated tests, using the RSpec framework, and manual tests of the user interface (UI), using the app. The automated tests helped to ensure that the basic functionality of the app still worked, while the UI tests ensured that the visualizations were correct.&lt;br /&gt;
&lt;br /&gt;
=== RSpec Test Results ===&lt;br /&gt;
In order to ensure that our changes did not affect basic functionality of the app, we made sure that all tests that passed before our changes also passed after our changes. Add statistics on the tests before our changes and matching statistics after our changes.&lt;br /&gt;
&lt;br /&gt;
=== UI Tests ===&lt;br /&gt;
To validate all functionality of the chart when adding new features or fixing old ones, the following criteria were tested manually for expected functionality:&lt;br /&gt;
&lt;br /&gt;
# Chart is displaying correctly&lt;br /&gt;
## Bars are showing up where expected&lt;br /&gt;
## Bar annotations are showing the expected value&lt;br /&gt;
## Criteria labels are for the correct bar and displaying correct values&lt;br /&gt;
## Hover text is displaying the correct values&lt;br /&gt;
## Null values are not present on the chart&lt;br /&gt;
## Correct colors are used for the multi-round view&lt;br /&gt;
# Show Labels checkbox works as expected&lt;br /&gt;
# Round Criteria is displaying correctly&lt;br /&gt;
## Round dropdown menu shows all rounds for the assignment&lt;br /&gt;
## Selecting a round changes the criteria checkboxes&lt;br /&gt;
## All checkboxes are displayed with appropriate text&lt;br /&gt;
## Checkboxes correctly remove or add criterion bars to the chart&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123185</id>
		<title>E1929 Visualizations for Instructors</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1929_Visualizations_for_Instructors&amp;diff=123185"/>
		<updated>2019-04-04T13:57:27Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: Created page with &amp;quot;Place Holder for our write-up&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Place Holder for our write-up&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122875</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122875"/>
		<updated>2019-04-01T21:19:48Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* New RSpec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we ran the corresponding test via the terminal window. For example, to test the simi_check_webservice model:&lt;br /&gt;
   rspec spec/models/simi_check_webservie_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the simi_check_webservice model, app/models/simi_check_webervice.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/simi_check_webservice_spec.rb&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    .........&lt;br /&gt;
    &lt;br /&gt;
    Finished in 1.63 seconds (files took 28.35 seconds to load)&lt;br /&gt;
    10 examples, 0 failures, 10 pending&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/expertiza/coverage. 1192 / 17393 LOC (6.85%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
We ran this command against master branch as a baseline, which produced the following results:&lt;br /&gt;
&lt;br /&gt;
    817 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
These tests represented 1510 lines of code and 58.54% code coverage for our models. Among our models, these numbers included 10 models that had 100% code coverage.&lt;br /&gt;
&lt;br /&gt;
However, while working with the existing RSpec tests, we noticed that some models have relatively low coverage (&amp;gt; 40%). Therefore, we could not rely strictly on existing RSpec tests and guarantee correctness of our code changes by running them. We decided to write additional Rspec tests that directly test all our code changes and add them into existing spec files by modifying existing tests and boost the test coverage on files that we modified. For example, we fixed multiple Code Climate issues in the [https://github.com/gshugh/expertiza/commit/b9aac55b6eb331c1db295b7e7dd45fbbdba19abc app/models/team.rb] file. Specifically, complications of such issues as &amp;quot;Use a guard clause instead of wrapping the code inside a conditional expression&amp;quot;, &amp;quot;Use ''find_by'' instead of ''where.first''&amp;quot;, and others were resolved in ''import'', ''export'', and ''handle_duplicate'' method calls. Most of the changes are listed below:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_1.png]]&lt;br /&gt;
[[File: app_models_teams_2.png]]&lt;br /&gt;
&lt;br /&gt;
Any of the above changes may break existing functionality of the code without proper testing. Moreover, we noticed that existing ''spec/models/team_spec.rb'' Rspec file does not thoroughly tests these method calls and had very a little to none of such tests. Hence, in order to verify and test all our changes, we wrote additional Rspec tests and added them into ''spec/models/team_spec.rb'' that specifically tests our code changes. ''Note'' that in the following test cases, we cover all possible scenarios, including edge-case scenarios. Check out [https://github.com/gshugh/expertiza/commit/96cec7fa82c1c55e31e0196d3a025111a4fe134a spec/models/team_spec.rb] for full list of Rspec tests. The following is a list of Rspec we developed to test all our changes in the ''app/models/team.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: rspec_models_team_spec_1.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_2.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_3.png]]&lt;br /&gt;
&lt;br /&gt;
''Note'' that this is only one small example we show here of additional Rspec tests we developed. Full list of newly developed and added Rspec tests can be found in our Git Pull Request. Also note that by adding new spec test cases, we increased test code coverage on all of the models. The test coverage for the ''app/models/team.rb'' model was increased up to 88.51% as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_team_spec_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
Moreover, while working with the existing Rspec tests, besides low coverage on some of the tests, we also noticed that some models are tested indirectly via other Rspec tests. Meaning there is no dedicated spec test file for some of the models that we fixed. Since we were not aware of what spec files are responsible for testing some models that have no dedicated spec test file, we did not know what are the exact set of test cases existing Rspec testing framework runs on these file (e.g. edge-case scenarios and etc). Similarly, as with existing Rspec tests we found out that existing specs would not suffice for the changes that we made. Therefore, we created '''new''' dedicated Rspec test files and wrote test cases that test our changes directly.&lt;br /&gt;
&lt;br /&gt;
For example, we fixed multiple Code Climate issues in the ''app/models/teams_user.rb'' file. At the moment, there is no corresponding Rspec file for that model in the system. Therefore, we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to test directly our code changes and boost the code coverage on that model. The following is the change that we did in the ''app/models/teams_user.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
The following is newly created corresponding ''spec/models/teams_test_spec.rb'' test file included in our Git Pull Request having all general-purpose tests in it as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_1.png]]&lt;br /&gt;
[[File: spec_models_teams_user_2.png]]&lt;br /&gt;
[[File: spec_models_teams_user_3.png]]&lt;br /&gt;
 &lt;br /&gt;
''Note'' that by creating new corresponding spec test for the ''app/models/teams_user.rb'' model, we achieved 100% test coverage on that model, whereas before it was around 60.53%.&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
Again this is only one example we show here of the files that we created. More additional spec files were created to test our code changes. For example, we made extensive changes by fixing &amp;quot;Tagging a string as html safe may be a security risk&amp;quot; Code Climate issue. Most of those models did not have corresponding Rspec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment. The test coverage on those models was also increased.&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the RSpec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
This represented 1440 lines of code and 68.19% of code coverage for the models of interest. The number of lines of code decreased by 4.64% (from 1510 to 1440), an increase in code coverage of 16.48% (from 58.54% to 68.19%) and an increase in test examples of 8.45% (from 817 to 886). Included in the new test numbers was a 70% increase in the number of models that had 100% coverage (from 10 to 17). The increase in the percentage of code coverage was due to a combination of the decrease in the number of lines and the increase in the number of test examples.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])! There are no more Code Climate issues found!&lt;br /&gt;
&lt;br /&gt;
Although, in our project we were not asked to write additional Rspec tests, we dedicated some of our time to do so. The goal of writing additional spec test cases was to validate our code changes, make sure our changes did not cause any problems in the app, and boost the test coverage on the models we worked on. We achieved all our goals and tested all our changes with the help of Rspec tests that we wrote. We also ensured that our additional spec tests boost the code coverage.&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage on all of the existing files by writing more Rspec tests and considering more possible scenarios (i.e, edge-case scenarios).&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122874</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122874"/>
		<updated>2019-04-01T21:17:10Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Existing Rspec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we ran the corresponding test via the terminal window. For example, to test the simi_check_webservice model:&lt;br /&gt;
   rspec spec/models/simi_check_webservie_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the simi_check_webservice model, app/models/simi_check_webervice.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/simi_check_webservice_spec.rb&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    .........&lt;br /&gt;
    &lt;br /&gt;
    Finished in 1.63 seconds (files took 28.35 seconds to load)&lt;br /&gt;
    10 examples, 0 failures, 10 pending&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/expertiza/coverage. 1192 / 17393 LOC (6.85%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
We ran this command against master branch as a baseline, which produced the following results:&lt;br /&gt;
&lt;br /&gt;
    817 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
These tests represented 1510 lines of code and 58.54% code coverage for our models. Among our models, these numbers included 10 models that had 100% code coverage.&lt;br /&gt;
&lt;br /&gt;
However, while working with the existing RSpec tests, we noticed that some models have relatively low coverage (&amp;gt; 40%). Therefore, we could not rely strictly on existing RSpec tests and guarantee correctness of our code changes by running them. We decided to write additional Rspec tests that directly test all our code changes and add them into existing spec files by modifying existing tests and boost the test coverage on files that we modified. For example, we fixed multiple Code Climate issues in the [https://github.com/gshugh/expertiza/commit/b9aac55b6eb331c1db295b7e7dd45fbbdba19abc app/models/team.rb] file. Specifically, complications of such issues as &amp;quot;Use a guard clause instead of wrapping the code inside a conditional expression&amp;quot;, &amp;quot;Use ''find_by'' instead of ''where.first''&amp;quot;, and others were resolved in ''import'', ''export'', and ''handle_duplicate'' method calls. Most of the changes are listed below:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_1.png]]&lt;br /&gt;
[[File: app_models_teams_2.png]]&lt;br /&gt;
&lt;br /&gt;
Any of the above changes may break existing functionality of the code without proper testing. Moreover, we noticed that existing ''spec/models/team_spec.rb'' Rspec file does not thoroughly tests these method calls and had very a little to none of such tests. Hence, in order to verify and test all our changes, we wrote additional Rspec tests and added them into ''spec/models/team_spec.rb'' that specifically tests our code changes. ''Note'' that in the following test cases, we cover all possible scenarios, including edge-case scenarios. Check out [https://github.com/gshugh/expertiza/commit/96cec7fa82c1c55e31e0196d3a025111a4fe134a spec/models/team_spec.rb] for full list of Rspec tests. The following is a list of Rspec we developed to test all our changes in the ''app/models/team.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: rspec_models_team_spec_1.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_2.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_3.png]]&lt;br /&gt;
&lt;br /&gt;
''Note'' that this is only one small example we show here of additional Rspec tests we developed. Full list of newly developed and added Rspec tests can be found in our Git Pull Request. Also note that by adding new spec test cases, we increased test code coverage on all of the models. The test coverage for the ''app/models/team.rb'' model was increased up to 88.51% as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_team_spec_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
Moreover, while working with the existing Rspec tests, besides low coverage on some of the tests, we also noticed that some models are tested indirectly via other Rspec tests. Meaning there is no dedicated spec test file for some of the models that we fixed. Since we were not aware of what spec files are responsible for testing some models that have no dedicated spec test file, we did not know what are the exact set of test cases existing Rspec testing framework runs on these file (e.g. edge-case scenarios and etc). Similarly, as with existing Rspec tests we found out that existing specs would not suffice for the changes that we made. Therefore, we created '''new''' dedicated Rspec test files and wrote test cases that test our changes directly.&lt;br /&gt;
&lt;br /&gt;
For example, we fixed multiple Code Climate issues in the ''app/models/teams_user.rb'' file. At the moment, there is no corresponding Rspec file for that model in the system. Therefore, we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to test directly our code changes and boost the code coverage on that model. The following is the change that we did in the ''app/models/teams_user.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
The following is newly created corresponding ''spec/models/teams_test_spec.rb'' test file included in our Git Pull Request having all general-purpose tests in it as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_1.png]]&lt;br /&gt;
[[File: spec_models_teams_user_2.png]]&lt;br /&gt;
[[File: spec_models_teams_user_3.png]]&lt;br /&gt;
 &lt;br /&gt;
''Note'' that by creating new corresponding spec test for the ''app/models/teams_user.rb'' model, we achieved 100% test coverage on that model, whereas before it was around 60.53%.&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
Again this is only one example we show here of the files that we created. More additional spec files were created to test our code changes. For example, we made extensive changes by fixing &amp;quot;Tagging a string as html safe may be a security risk&amp;quot; Code Climate issue. Most of those models did not have corresponding Rspec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment. The test coverage on those models was also increased.&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the RSpec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
This represented 1440 lines of code and 68.19% of code coverage for the models of interest. The number of lines of code decreased by 4.64% (from 1510 to 1440), an increase in code coverage of 16.48% (from 58.54% to 68.19%) and an increase in test examples of 8.45% (from 817 to 886). The increase in the percentage of code coverage was due to a combination of the decrease in the number of lines and the increase in the number of test examples.&lt;br /&gt;
&lt;br /&gt;
We also compared the test coverage before and after implementation of our project and there was increase of 1% on models with names starting with ''Se'' through ''Z''. To compare the results on the files that were fixed we ran the following command before and after our project implementation:&lt;br /&gt;
&lt;br /&gt;
  rspec spec/models/[se-z]*.rb&lt;br /&gt;
&lt;br /&gt;
The following are results before our project implementation:&lt;br /&gt;
&lt;br /&gt;
[[File: se_z_test_coverage_before.png]]&lt;br /&gt;
&lt;br /&gt;
And the following are results after the project implementation:&lt;br /&gt;
&lt;br /&gt;
[[File: se_z_test_coverage_after.png]]&lt;br /&gt;
&lt;br /&gt;
Although 1% does not seem to be big improvements. However, this is 1% of the total code coverage and for such massive project 1% test coverage increase is significant!&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])! There are no more Code Climate issues found!&lt;br /&gt;
&lt;br /&gt;
Although, in our project we were not asked to write additional Rspec tests, we dedicated some of our time to do so. The goal of writing additional spec test cases was to validate our code changes, make sure our changes did not cause any problems in the app, and boost the test coverage on the models we worked on. We achieved all our goals and tested all our changes with the help of Rspec tests that we wrote. We also ensured that our additional spec tests boost the code coverage.&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage on all of the existing files by writing more Rspec tests and considering more possible scenarios (i.e, edge-case scenarios).&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122861</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122861"/>
		<updated>2019-04-01T20:55:27Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* New RSpec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we ran the corresponding test via the terminal window. For example, to test the simi_check_webservice model:&lt;br /&gt;
   rspec spec/models/simi_check_webservie_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the simi_check_webservice model, app/models/simi_check_webervice.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/simi_check_webservice_spec.rb&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    .........&lt;br /&gt;
    &lt;br /&gt;
    Finished in 1.63 seconds (files took 28.35 seconds to load)&lt;br /&gt;
    10 examples, 0 failures, 10 pending&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/expertiza/coverage. 1192 / 17393 LOC (6.85%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
We ran this command against master branch as a baseline, which produced the following results:&lt;br /&gt;
&lt;br /&gt;
    817 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
These tests represented 1510 lines of code and 58.54% code coverage for our models.&lt;br /&gt;
&lt;br /&gt;
However, while working with the existing RSpec tests, we noticed that some models have relatively low coverage (&amp;gt; 40%). Therefore, we could not rely strictly on existing RSpec tests and guarantee correctness of our code changes by running them. We decided to write additional Rspec tests that directly test all our code changes and add them into existing spec files by modifying existing tests and boost the test coverage on files that we modified. For example, we fixed multiple Code Climate issues in the [https://github.com/gshugh/expertiza/commit/b9aac55b6eb331c1db295b7e7dd45fbbdba19abc app/models/team.rb] file. Specifically, complications of such issues as &amp;quot;Use a guard clause instead of wrapping the code inside a conditional expression&amp;quot;, &amp;quot;Use ''find_by'' instead of ''where.first''&amp;quot;, and others were resolved in ''import'', ''export'', and ''handle_duplicate'' method calls. Most of the changes are listed below:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_1.png]]&lt;br /&gt;
[[File: app_models_teams_2.png]]&lt;br /&gt;
&lt;br /&gt;
Any of the above changes may break existing functionality of the code without proper testing. Moreover, we noticed that existing ''spec/models/team_spec.rb'' Rspec file does not thoroughly tests these method calls and had very a little to none of such tests. Hence, in order to verify and test all our changes, we wrote additional Rspec tests and added them into ''spec/models/team_spec.rb'' that specifically tests our code changes. ''Note'' that in the following test cases, we cover all possible scenarios, including edge-case scenarios. Check out [https://github.com/gshugh/expertiza/commit/96cec7fa82c1c55e31e0196d3a025111a4fe134a spec/models/team_spec.rb] for full list of Rspec tests. The following is a list of Rspec we developed to test all our changes in the ''app/models/team.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: rspec_models_team_spec_1.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_2.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_3.png]]&lt;br /&gt;
&lt;br /&gt;
''Note'' that this is only one small example we show here of additional Rspec tests we developed. Full list of newly developed and added Rspec tests can be found in our Git Pull Request. Also note that by adding new spec test cases, we increased test code coverage on all of the models. The test coverage for the ''app/models/team.rb'' model was increased up to 88.51% as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_team_spec_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
Moreover, while working with the existing Rspec tests, besides low coverage on some of the tests, we also noticed that some models are tested indirectly via other Rspec tests. Meaning there is no dedicated spec test file for some of the models that we fixed. Since we were not aware of what spec files are responsible for testing some models that have no dedicated spec test file, we did not know what are the exact set of test cases existing Rspec testing framework runs on these file (e.g. edge-case scenarios and etc). Similarly, as with existing Rspec tests we found out that existing specs would not suffice for the changes that we made. Therefore, we created '''new''' dedicated Rspec test files and wrote test cases that test our changes directly.&lt;br /&gt;
&lt;br /&gt;
For example, we fixed multiple Code Climate issues in the ''app/models/teams_user.rb'' file. At the moment, there is no corresponding Rspec file for that model in the system. Therefore, we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to test directly our code changes and boost the code coverage on that model. The following is the change that we did in the ''app/models/teams_user.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
The following is newly created corresponding ''spec/models/teams_test_spec.rb'' test file included in our Git Pull Request having all general-purpose tests in it as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_1.png]]&lt;br /&gt;
[[File: spec_models_teams_user_2.png]]&lt;br /&gt;
[[File: spec_models_teams_user_3.png]]&lt;br /&gt;
 &lt;br /&gt;
''Note'' that by creating new corresponding spec test for the ''app/models/teams_user.rb'' model, we achieved 100% test coverage on that model, whereas before it was around 60.53%.&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
Again this is only one example we show here of the files that we created. More additional spec files were created to test our code changes. For example, we made extensive changes by fixing &amp;quot;Tagging a string as html safe may be a security risk&amp;quot; Code Climate issue. Most of those models did not have corresponding Rspec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment. The test coverage on those models was also increased.&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the RSpec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
This represented 1440 lines of code and 68.19% of code coverage for the models of interest. The number of lines of code decreased by 4.64% (from 1510 to 1440), an increase in code coverage of 16.48% (from 58.54% to 68.19%) and an increase in test examples of 8.45% (from 817 to 886). The increase in the percentage of code coverage was due to a combination of the decrease in the number of lines and the increase in the number of test examples.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])! There are no more Code Climate issues found!&lt;br /&gt;
&lt;br /&gt;
Although, in our project we were not asked to write additional Rspec tests, we dedicated some of our time to do so. The goal of writing additional spec test cases was to validate our code changes, make sure our changes did not cause any problems in the app, and boost the test coverage on the models we worked on. We achieved all our goals and tested all our changes with the help of Rspec tests that we wrote. We also ensured that our additional spec tests boost the code coverage.&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage on all of the existing files by writing more Rspec tests and considering more possible scenarios (i.e, edge-case scenarios).&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122859</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122859"/>
		<updated>2019-04-01T20:44:31Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Existing Rspec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we ran the corresponding test via the terminal window. For example, to test the simi_check_webservice model:&lt;br /&gt;
   rspec spec/models/simi_check_webservie_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the simi_check_webservice model, app/models/simi_check_webervice.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/simi_check_webservice_spec.rb&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    .........&lt;br /&gt;
    &lt;br /&gt;
    Finished in 1.63 seconds (files took 28.35 seconds to load)&lt;br /&gt;
    10 examples, 0 failures, 10 pending&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/expertiza/coverage. 1192 / 17393 LOC (6.85%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
We ran this command against master branch as a baseline, which produced the following results:&lt;br /&gt;
&lt;br /&gt;
    817 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
These tests represented 1510 lines of code and 58.54% code coverage for our models.&lt;br /&gt;
&lt;br /&gt;
However, while working with the existing RSpec tests, we noticed that some models have relatively low coverage (&amp;gt; 40%). Therefore, we could not rely strictly on existing RSpec tests and guarantee correctness of our code changes by running them. We decided to write additional Rspec tests that directly test all our code changes and add them into existing spec files by modifying existing tests and boost the test coverage on files that we modified. For example, we fixed multiple Code Climate issues in the [https://github.com/gshugh/expertiza/commit/b9aac55b6eb331c1db295b7e7dd45fbbdba19abc app/models/team.rb] file. Specifically, complications of such issues as &amp;quot;Use a guard clause instead of wrapping the code inside a conditional expression&amp;quot;, &amp;quot;Use ''find_by'' instead of ''where.first''&amp;quot;, and others were resolved in ''import'', ''export'', and ''handle_duplicate'' method calls. Most of the changes are listed below:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_1.png]]&lt;br /&gt;
[[File: app_models_teams_2.png]]&lt;br /&gt;
&lt;br /&gt;
Any of the above changes may break existing functionality of the code without proper testing. Moreover, we noticed that existing ''spec/models/team_spec.rb'' Rspec file does not thoroughly tests these method calls and had very a little to none of such tests. Hence, in order to verify and test all our changes, we wrote additional Rspec tests and added them into ''spec/models/team_spec.rb'' that specifically tests our code changes. ''Note'' that in the following test cases, we cover all possible scenarios, including edge-case scenarios. Check out [https://github.com/gshugh/expertiza/commit/96cec7fa82c1c55e31e0196d3a025111a4fe134a spec/models/team_spec.rb] for full list of Rspec tests. The following is a list of Rspec we developed to test all our changes in the ''app/models/team.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: rspec_models_team_spec_1.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_2.png]]&lt;br /&gt;
[[File: rspec_models_team_spec_3.png]]&lt;br /&gt;
&lt;br /&gt;
''Note'' that this is only one small example we show here of additional Rspec tests we developed. Full list of newly developed and added Rspec tests can be found in our Git Pull Request. Also note that by adding new spec test cases, we increased test code coverage on all of the models. The test coverage for the ''app/models/team.rb'' model was increased up to 88.51% as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_team_spec_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
Moreover, while working with the existing Rspec tests, besides low coverage on some of the tests, we also noticed that some models are tested indirectly via other Rspec tests. Meaning there is no dedicated spec test file for some of the models that we fixed. Since we were not aware of what spec files are responsible for testing some models that have no dedicated spec test file, we did not know what are the exact set of test cases existing Rspec testing framework runs on these file (e.g. edge-case scenarios and etc). Similarly, as with existing Rspec tests we found out that existing specs would not suffice for the changes that we made. Therefore, we created '''new''' dedicated Rspec test files and wrote test cases that test our changes directly.&lt;br /&gt;
&lt;br /&gt;
For example, we fixed multiple Code Climate issues in the ''app/models/teams_user.rb'' file. At the moment, there is no corresponding Rspec file for that model in the system. Therefore, we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to test directly our code changes and boost the code coverage on that model. The following is the change that we did in the ''app/models/teams_user.rb'' file:&lt;br /&gt;
&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
The following is newly created corresponding ''spec/models/teams_test_spec.rb'' test file included in our Git Pull Request having all general-purpose tests in it as follows:&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_1.png]]&lt;br /&gt;
[[File: spec_models_teams_user_2.png]]&lt;br /&gt;
[[File: spec_models_teams_user_3.png]]&lt;br /&gt;
 &lt;br /&gt;
''Note'' that by creating new corresponding spec test for the ''app/models/teams_user.rb'' model, we achieved 100% test coverage on that model, whereas before it was around 60.53%.&lt;br /&gt;
&lt;br /&gt;
[[File: spec_models_teams_user_test_coverage.png]]&lt;br /&gt;
&lt;br /&gt;
Again this is only one example we show here of the files that we created. More additional spec files were created to test our code changes. For example, we made extensive changes by fixing &amp;quot;Tagging a string as html safe may be a security risk&amp;quot; Code Climate issue. Most of those models did not have corresponding Rspec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment. The test coverage on those models was also increased.&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the Rspec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
The increase in the number of examples reflects the addition RSpec model tests that we wrote.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
Although, in our project we were not asked to write additional Rspec tests, we dedicated some of our time to do so. The goal of writing additional spec test cases was to validate our code changes, make sure our changes did not cause any problems in the app, and boost the test coverage on the models. We achieved all our goals and tested all our changes with the help of Rspec tests that we wrote. &lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage on all of the existing files by writing more Rspec tests and considering more possible scenarios (i.e, edge-case scenarios).&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122753</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122753"/>
		<updated>2019-04-01T00:30:19Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Existing Rspec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we ran the corresponding test via the terminal window. For example, to test the simi_check_webservice model:&lt;br /&gt;
   rspec spec/models/simi_check_webservie_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the simi_check_webservice model, app/models/simi_check_webervice.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/simi_check_webservice_spec.rb&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    .........&lt;br /&gt;
    &lt;br /&gt;
    Finished in 1.63 seconds (files took 28.35 seconds to load)&lt;br /&gt;
    10 examples, 0 failures, 10 pending&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/expertiza/coverage. 1192 / 17393 LOC (6.85%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
This command was run against the master branch as a baseline and our beta branch.&lt;br /&gt;
The master branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    871 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
While looking through the exisitng RSpec test, we noticed that some models are tested indirectly via other RSpec test. Since we did not know how intensively our changes are getting tested with the existing RSpec testing framework (e.g. edge-case scenarios and etc), and whether existing tests are enough, we wrote both '''new''' RSpec test cases and '''new''' RSpec test files.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we added new RSpect tests to test our code and to increase code coverage on certain files. For those, we ran the corresponding test via the terminal window as discussed above. For example, to test the tag_prompt model:&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
&lt;br /&gt;
Other models did not have any way to directly test our changes to the code. For example, we have made multiple changes in the ''app/models/teams_user.rb'' file. There is no corresponding RSpec file in the system so we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to directly our code changes. Another example, was the extensive changes we made to remove html_safe code. Most of those models did not have corresponding RSpec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment.&lt;br /&gt;
&lt;br /&gt;
The change that we did in the ''app/models/teams_user.rb'' file as follows:&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the RSpec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
The increase in the number of examples reflects the addition RSpec model tests that we wrote.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122752</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122752"/>
		<updated>2019-04-01T00:27:31Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Existing Rspec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we ran the corresponding test via the terminal window. For example, to test the simi_check_webservice model:&lt;br /&gt;
   rspec spec/models/simi_check_webservie_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the simi_check_webservice model, app/models/simi_check_webervice.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/simi_check_webservice_spec.rb&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 1.63 seconds (files took 28.35 seconds to load)&lt;br /&gt;
    10 examples, 0 failures, 10 pending&lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/expertiza/coverage. 1192 / 17393 LOC (6.85%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
This command was run against the master branch as a baseline and our beta branch.&lt;br /&gt;
The master branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    871 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
While looking through the exisitng RSpec test, we noticed that some models are tested indirectly via other RSpec test. Since we did not know how intensively our changes are getting tested with the existing RSpec testing framework (e.g. edge-case scenarios and etc), and whether existing tests are enough, we wrote both '''new''' RSpec test cases and '''new''' RSpec test files.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we added new RSpect tests to test our code and to increase code coverage on certain files. For those, we ran the corresponding test via the terminal window as discussed above. For example, to test the tag_prompt model:&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
&lt;br /&gt;
Other models did not have any way to directly test our changes to the code. For example, we have made multiple changes in the ''app/models/teams_user.rb'' file. There is no corresponding RSpec file in the system so we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to directly our code changes. Another example, was the extensive changes we made to remove html_safe code. Most of those models did not have corresponding RSpec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment.&lt;br /&gt;
&lt;br /&gt;
The change that we did in the ''app/models/teams_user.rb'' file as follows:&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the RSpec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
The increase in the number of examples reflects the addition RSpec model tests that we wrote.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122751</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122751"/>
		<updated>2019-04-01T00:27:03Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Existing Rspec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we ran the corresponding test via the terminal window. For example, to test the simi_check_webservice model:&lt;br /&gt;
   rspec spec/models/simi_check_webservie_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the simi_check_webservice model, app/models/simi_check_webervice.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/simi_check_webservice_spec.rb&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
&lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
    .........&lt;br /&gt;
&lt;br /&gt;
    Finished in 1.63 seconds (files took 28.35 seconds to load)&lt;br /&gt;
    10 examples, 0 failures, 10 pending&lt;br /&gt;
&lt;br /&gt;
    Randomized with seed 29018&lt;br /&gt;
&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/expertiza/coverage. 1192 / 17393 LOC (6.85%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
This command was run against the master branch as a baseline and our beta branch.&lt;br /&gt;
The master branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    871 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
While looking through the exisitng RSpec test, we noticed that some models are tested indirectly via other RSpec test. Since we did not know how intensively our changes are getting tested with the existing RSpec testing framework (e.g. edge-case scenarios and etc), and whether existing tests are enough, we wrote both '''new''' RSpec test cases and '''new''' RSpec test files.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we added new RSpect tests to test our code and to increase code coverage on certain files. For those, we ran the corresponding test via the terminal window as discussed above. For example, to test the tag_prompt model:&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
&lt;br /&gt;
Other models did not have any way to directly test our changes to the code. For example, we have made multiple changes in the ''app/models/teams_user.rb'' file. There is no corresponding RSpec file in the system so we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to directly our code changes. Another example, was the extensive changes we made to remove html_safe code. Most of those models did not have corresponding RSpec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment.&lt;br /&gt;
&lt;br /&gt;
The change that we did in the ''app/models/teams_user.rb'' file as follows:&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the RSpec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
The increase in the number of examples reflects the addition RSpec model tests that we wrote.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122750</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122750"/>
		<updated>2019-04-01T00:18:04Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed four simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing RSpec tests&lt;br /&gt;
# '''Developing new RSpec tests'''&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that per project's requirement specifications we were not required to develop and write newly RSpec tests. However, ultimately we strive to achieve crucial improvements over code quality, robustness, and maintainability for the files that we have worked on. We believe we achieved our goal. We did not do this to gain extra credit or something similar. We did it because we believe in testing and convinced that nothing can improve Expertiza source code like testing.&lt;br /&gt;
 &lt;br /&gt;
There are 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Existing Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application and its functionalities, we used the RSpec Testing Framework to test all the code.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we added new RSpect tests to test our code and to increase code coverage on certain files. For those, we ran the corresponding test via the terminal window. For example, to test the tag_prompt model:&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
&lt;br /&gt;
This executes the RSpec test for the tag_prompt model, app/models/tag_prompt.rb. As you can see, there is a particular format that is used when naming the RSpec file:&lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results are displayed:&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
This command was run against the master branch as a baseline and our beta branch.&lt;br /&gt;
The master branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    871 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
=== New RSpec Testing ===&lt;br /&gt;
&lt;br /&gt;
While looking through the exisitng RSpec test, we noticed that some models are tested indirectly via other RSpec test. Since we did not know how intensively our changes are getting tested with the existing RSpec testing framework (e.g. edge-case scenarios and etc), and whether existing tests are enough, we wrote both '''new''' RSpec test cases and '''new''' RSpec test files.&lt;br /&gt;
&lt;br /&gt;
Some of the models already had existing RSpecs tests created prior we started on work on the project. For those models, we added new RSpect tests to test our code and to increase code coverage on certain files. For those, we ran the corresponding test via the terminal window as discussed above. For example, to test the tag_prompt model:&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
&lt;br /&gt;
Other models did not have any way to directly test our changes to the code. For example, we have made multiple changes in the ''app/models/teams_user.rb'' file. There is no corresponding RSpec file in the system so we created a new [https://github.com/gshugh/expertiza/blob/beta/spec/models/teams_user_spec.rb spec/models/teams_user_spec.rb] file to directly our code changes. Another example, was the extensive changes we made to remove html_safe code. Most of those models did not have corresponding RSpec files, so we added those RSpec files to allow developers to have some confidence in the code before deployment.&lt;br /&gt;
&lt;br /&gt;
The change that we did in the ''app/models/teams_user.rb'' file as follows:&lt;br /&gt;
[[File: app_models_teams_user_changes.png]]&lt;br /&gt;
&lt;br /&gt;
After all of these changes to the RSpec files, our beta branch produced the following results:&lt;br /&gt;
&lt;br /&gt;
    886 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
The increase in the number of examples reflects the addition RSpec model tests that we wrote.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122616</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122616"/>
		<updated>2019-03-28T18:44:19Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Rspec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify that the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
This command was run against the master branch as a baseline and our beta branch.&lt;br /&gt;
In both cases, the command produced the following results:&lt;br /&gt;
&lt;br /&gt;
    871 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122615</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122615"/>
		<updated>2019-03-28T18:43:42Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
This command was run against the master branch as a baseline and our beta branch.&lt;br /&gt;
In both cases, the command produced the following results:&lt;br /&gt;
&lt;br /&gt;
    871 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped to reveal all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122614</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122614"/>
		<updated>2019-03-28T18:42:51Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Rspec Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec tests, we also ensured that all previous RSpec tests passed. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec spec/controllers spec/models&lt;br /&gt;
&lt;br /&gt;
This command was run against the master branch as a baseline and our beta branch.&lt;br /&gt;
In both cases, the command produced the following results:&lt;br /&gt;
&lt;br /&gt;
    871 examples, 0 failure, 16 pending&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122600</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122600"/>
		<updated>2019-03-27T23:55:39Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Remaining Issues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
# simicheck_webservice.rb (1)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122570</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122570"/>
		<updated>2019-03-27T14:42:09Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Remaining Issues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
# sign_up_topic (2)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122569</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122569"/>
		<updated>2019-03-27T14:41:03Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Remaining Issues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
There is also an issue with methods that were commented out in the original code. While the team removed code that we changed, we also made a conscious decision to leave existing commented out methods in the code and let the original maintainer decide if the comment should be removed. The following files had existing commented out methods:&lt;br /&gt;
  # sign_up_topic (2)&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122568</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122568"/>
		<updated>2019-03-27T14:25:39Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Additional Improvements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122567</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122567"/>
		<updated>2019-03-27T14:22:40Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement OSS Project &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot; for the CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, Spring semester of the 2019.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS Project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned to [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920 - Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] OSS Project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where is needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
We created a [https://github.com/expertiza/expertiza/pull/1368 Pull Request] as soon as we had at least one fix on our [https://github.com/gshugh/expertiza/tree/beta forked beta branch].&lt;br /&gt;
&lt;br /&gt;
GitHub pull request is an integral part of solving Code Climate issues and delivering fixes into the Expertiza beta branch. We verified all our Code Climate fixes on the local working repositories, which we registered with Code Climate tool. Every new git commit/push was triggering new Code Climate job and we could verify if our changes fixed the issues. A typical workflow was as follows:&lt;br /&gt;
* Code Climate issues were resolved and tested locally&lt;br /&gt;
* Changes were pushed to local repositories registered with Code Climate&lt;br /&gt;
* New git commit/push was triggering new Code Climate verification job&lt;br /&gt;
* Verified that resolved issues were not reported on the latest Code Climate job&lt;br /&gt;
All our changes are visible and can be tracked in the single pull requests we created as soon as we had one fix.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# Pages that previously used html_safe&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122441</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122441"/>
		<updated>2019-03-26T01:59:47Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement E1920 OSS Project, &amp;quot;Fix Code Climate issues in models with names beginning with 'Se' thru 'Z'&amp;quot; in the Spring 2019 semester, CSC/ECE 517.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned with [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920. Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] Expertiza project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where is needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
&lt;br /&gt;
GitHub pull requests were an integral part of solving Code Climate issues. We found that in order for Code Climate to re-analyze new code, it had to be via pull requests. A typical workflow was as follows:&lt;br /&gt;
  - Code Climate issues were tested in RubyMine and pushed to testing repositories&lt;br /&gt;
  - A pull request was created against the beta repository&lt;br /&gt;
  - The pull request triggered an analysis by Code Climate&lt;br /&gt;
  - A refresh of the code page on GitHub allowed us to see which Code Climate issues were fixed and which ones were still open.&lt;br /&gt;
  - After all relevant Code Climate issues were fixed, the changes were pushed to the beta branch of the GitHub repository, which also closed the pull request.&lt;br /&gt;
  - The next file was opened in RubyMine and we started at the beginning.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on four types of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
# pages that previously used html_safe&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122440</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122440"/>
		<updated>2019-03-26T01:55:55Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Pull Request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement E1920 OSS Project, &amp;quot;Fix Code Climate issues in models with names beginning with 'Se' thru 'Z'&amp;quot; in the Spring 2019 semester, CSC/ECE 517.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned with [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920. Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] Expertiza project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where is needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
&lt;br /&gt;
GitHub pull requests were an integral part of solving Code Climate issues. We found that in order for Code Climate to re-analyze new code, it had to be via pull requests. A typical workflow was as follows:&lt;br /&gt;
  - Code Climate issues were tested in RubyMine and pushed to testing repositories&lt;br /&gt;
  - A pull request was created against the beta repository&lt;br /&gt;
  - The pull request triggered an analysis by Code Climate&lt;br /&gt;
  - A refresh of the code page on GitHub allowed us to see which Code Climate issues were fixed and which ones were still open.&lt;br /&gt;
  - After all relevant Code Climate issues were fixed, the changes were pushed to the beta branch of the GitHub repository, which also closed the pull request.&lt;br /&gt;
  - The next file was opened in RubyMine and we started at the beginning.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on three type of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122435</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122435"/>
		<updated>2019-03-26T01:48:04Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Most Common Issues Reported by Code Climate */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement E1920 OSS Project, &amp;quot;Fix Code Climate issues in models with names beginning with 'Se' thru 'Z'&amp;quot; in the Spring 2019 semester, CSC/ECE 517.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned with [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920. Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] Expertiza project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false)&lt;br /&gt;
We did find that there was some HTML code that was not properly rendered using the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text in HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to allow them to properly render. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where is needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
&lt;br /&gt;
Let's add some info about pull request&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on three type of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122433</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122433"/>
		<updated>2019-03-26T01:45:13Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: Add html_safe fixes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement E1920 OSS Project, &amp;quot;Fix Code Climate issues in models with names beginning with 'Se' thru 'Z'&amp;quot; in the Spring 2019 semester, CSC/ECE 517.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This Wiki page is created per CSC/ECE 517: &amp;quot;Object-Oriented Design and Development&amp;quot;, OSS project 3 requirements (Spring, 2019).&lt;br /&gt;
&lt;br /&gt;
Our [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Team_Contacts_and_Contribution team] was assigned with [https://docs.google.com/document/d/17tkcuA7AWgGEzDGpjEJ7ktPzbSr-D89MJZd-cXzSCuE/edit#heading=h.jes8j9o3codt &amp;quot;E1920. Fix Code Climate issues in models with names beginning with ''Se'' thru ''Z''&amp;quot;] Expertiza project. In this page we describe what work has been completed by our team to improve overall quality, readability, maintainability and efficiency of the Expertiza source code. What approaches we used to resolve issues reported by Code Climate, what are the remaining issues in the Expertiza code, our suggestions for further improvements and our testing strategy used to ensure integrity of the code. Each section below provides clear and descriptive review on the subject we cover.&lt;br /&gt;
&lt;br /&gt;
We start with introduction to Expertiza application and Code Climate tool. How Code Climate is used to improve Expertiza source code.&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify shortcomings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of software. The Code Climate generated results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate utilizes various engines to analyze the code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can be ran from either a 3-rd party remote server of via the local application using CLI. The Expertiza project uses the 3-rd party remote server to analyze the code. In order to use Code Climate via remote server, desired repository must be registered with Code Climate. Following [https://docs.codeclimate.com/docs this] process allows to test the code for quality issues after each git commit/push to a registered repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness, efficiency, and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files. In this section we specify what files we have changed to improve overall software of the Expertiza project. We also list and describe the issues that we were asked to ignore during implementation of our project.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
In this section we talk about implementation of our project. We start with the most common issues reported by Code Climate and what approach we used to resolve them. We provide some code samples taken from the files and show their improvements. These changes/improvements are not trivial and require understanding of the code. Therefore, we provide implementation details of such issues along with detailed explanations.&lt;br /&gt;
&lt;br /&gt;
Furthermore, we list all of the issues reported by Code Climate that we fixed. These changes/improvements are trivial and require no explanation. Therefore, any implementation details are excluded for these type of issues.&lt;br /&gt;
&lt;br /&gt;
Next, we cover section with additional improvements that we have done along with fixes for Code Climate issues. These improvements do not directly relate to Code Climate issues; however, they improve overall quality of the code, its readability, maintenance and efficiency.&lt;br /&gt;
&lt;br /&gt;
We also list and talk about remaining issues reported by Code Climate that were intentionally ignored and left in the project. We provide further suggestions based on our experience to the Expertiza software developers.&lt;br /&gt;
&lt;br /&gt;
Finally, we provide out pull request that our team created as we started to work on this project.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue warns the user that strings tagged with html_safe can leave your site vulnerable to XSS attacks. To overcome this issue, we chose to use content_tag and tag helpers to create HTML tags. By using this practice we are able to create HTML strings that are actually HTML safe and we minimize the possibility of XSS attacks. A common use is:&lt;br /&gt;
  # Bad - uses html_safe&lt;br /&gt;
  html = '&amp;lt;b style=&amp;quot;color: #986633;&amp;quot;&amp;gt;' + self.txt + '&amp;lt;/b&amp;gt;'.html_safe&lt;br /&gt;
&lt;br /&gt;
  # Good - use content_tag&lt;br /&gt;
  html = content_tag(:b, self.txt, {style: &amp;quot;color: #986633&amp;quot;}, false&lt;br /&gt;
We did find that there were some HTML code that could not fit into the content_tag paradigm. This HTML code involved user supplied answers. These answers were created using a rich text editor called TinyMCE. TinyMCE wraps parts of the text with HTML tags and our mentor warned us against trying to decode these strings. For these strings we used the raw() function to include them in the HTML string. For example,&lt;br /&gt;
  concat self.txt + raw(answer.comments)&lt;br /&gt;
This use of raw() is in two files, text_field.rb and text_area.rb. If a better solution is found, please let the authors know.&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where is needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
&lt;br /&gt;
Let's add some info about pull request&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To test integrity of the code and ensure that our changes/improvements did not introduce new issues/errors, we followed three simple test steps:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing/fixing existing Rspec tests&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
''Note'' that we did not write new Rspec tests since we were not explicitly asked to do so in the project requirements.&lt;br /&gt;
 &lt;br /&gt;
There we 2 types of frameworks that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI analyzes the code once the changes are Pushed to the GitHub server for desired repository. Travis CI needs to be setup independently for desired repository.&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on three type of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Code Climate is a powerful tool that finds flaws in the source code of the Expertiza project. We would like to acknowledge that all issues reported by Code Climate on the files beginning with ''Se'' thru ''Z'' under ''app/models'' directory were fixed (except [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells])!&lt;br /&gt;
&lt;br /&gt;
We encourage software developers working on the Expertiza project to maintain clean, readable, well-commented and efficient code. We suggest to achieve at least 85% of test coverage by writing more Rspec tests.&lt;br /&gt;
&lt;br /&gt;
We would like to thank our mentor (Zachariah Mathews) and teaching staff for all the assistance and help they provided to us during the project implementation.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122239</id>
		<title>E1920 Fix Code Climate Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues&amp;diff=122239"/>
		<updated>2019-03-25T22:15:55Z</updated>

		<summary type="html">&lt;p&gt;Gshugh: /* Most Common Issues Reported by Code Climate */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki page describes the changes are made in the Expertiza source code to implement E1920 OSS Project, &amp;quot;Fix Code Climate issues in models with names beginning with 'Se' thru 'Z'&amp;quot; in the Spring 2019 semester, CSC/ECE 517.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This is intro section. We can talk about what is our project and how we got started.&lt;br /&gt;
&lt;br /&gt;
=== Expertiza ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.ncsu.edu/ Expertiza] is a peer to peer application whereby students gain knowledge through submitting their work into the system and review the work of others. This is system diverges from the customary systems where a instructor or body of teaching staff would grade the papers/assignments and provide feedback to the students. This process misses out on a learning opportunity for students performing reviews. Allowing students to see the work of others allows them to see more code examples and from different aspects. This exercise during the review process forces the student to think through lecture material and apply during the process. The Expertiza application can also be used as an iterative process from class to class. The examples of the current semester can be used by students of subsequent semesters to identify short comings and suggest further improvements.&lt;br /&gt;
&lt;br /&gt;
=== Code Climate ===&lt;br /&gt;
&lt;br /&gt;
Code Climate is an analysis software used to improve the quality and security of your code. The Code Climate results for the Expertiza project can be found [https://codeclimate.com/github/expertiza/expertiza/code here].&lt;br /&gt;
&lt;br /&gt;
Code Climate will use various engines to analyze your code to look for issues that may concern potential security issues, (.i.e. marking code to html_safe), or add to maintainability issues (.i.e number of lines in method exceeding 25 lines). Some of the engines include: RuboCop, Brakeman, Bundler-Audit, [https://docs.codeclimate.com/docs/list-of-engines etc.]&lt;br /&gt;
&lt;br /&gt;
Code Climate can ran from either a 3rd party remote server of via the local application using CLI. The Expertiza project uses the 3rd party remote server to analyze the code. In order to use CodeClimate via remote server, you have to register your repository. Following [https://docs.codeclimate.com/docs this] process will allow you to check your code for quality issues after Pushing your code to the monitored repository.&lt;br /&gt;
&lt;br /&gt;
== Project Description ==&lt;br /&gt;
&lt;br /&gt;
Some of the Expertiza source code violates many of the [https://rubyonrails.org/ Ruby on Rails] best practices and must be rectified to improve code readability, robustness and maintainability of the Expertiza application.&lt;br /&gt;
&lt;br /&gt;
Our team was assigned to fix ''all'' code smells detected by [https://codeclimate.com/github/expertiza/expertiza/code Code Climate] in the given set of Expertiza source code files.&lt;br /&gt;
&lt;br /&gt;
=== Files Involved ===&lt;br /&gt;
&lt;br /&gt;
All files in the [https://github.com/expertiza/expertiza/tree/master/app/models app/models] directory with names beginning with '''Se''' (e.g. [https://github.com/expertiza/expertiza/blob/master/app/models/section_header.rb section_header.rb]) through '''Z''', except [https://github.com/expertiza/expertiza/blob/master/app/controllers/users_controller.rb users_controller.rb] file were targeted by our team to be Code Climate issue free files. Therefore, our team was assigned exactly with 50 (fifty) files to fix in total. Some of the files had no issues reported by the Code Climate to begin with, and hence were not modified. However, changes/improvements performed on other files had an affect globally on the files outside of the app/models scope and also had to be modified to adapt changes we implemented. For example, renaming method ''is_leaf'' as follows:&lt;br /&gt;
  def leaf?&lt;br /&gt;
in the [https://github.com/expertiza/expertiza/blob/master/app/models/team_user_node.rb team_user_node.rb] file require to change all callers to this method in different files accordingly. Such changes had to be done in the following files (for this particular example):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; models/assignment_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; models/questionnaire_node.rb&lt;br /&gt;
&amp;lt;li&amp;gt; views/tree_display/_row_header.html.erb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These files are outside of the requirements specifications, but we had to modify them in order to maintain correct behavior of the App. There were few such cases when we had to modify multiple files to fix one or more Code Climate issue(s). The list of all of files changed can be found in the Pull Request discussed in this article.&lt;br /&gt;
&lt;br /&gt;
=== Ignored Code Climate Smells ===&lt;br /&gt;
&lt;br /&gt;
There are some Code Climate issues that were ignored and not resolved intentionally.&lt;br /&gt;
&lt;br /&gt;
The following issues are exempt based the given requirements specifications and were not fixed:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Assignment Branch Condition size for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Perceived complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Cyclomatic complexity for [method name] is too high.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has a Cognitive Complexity of ''XX'' (exceeds 5 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; File [file name] has ''XXX''  lines of code (exceeds 250 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Class [class name] has ''XX'' methods (exceeds 20 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Method [method name] has ''XX'' lines of code (exceeds 25 allowed). Consider refactoring.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also two Code Climate issues that our team decided to ignore after consulting our mentor and discussing their impact on the existing code and Expertiza project. It was determined that the following Code Climate issues reported as False Positive and may not need to be resolved:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Mass assignment is not restricted using attr_accessible.&lt;br /&gt;
&amp;lt;li&amp;gt; Potentially dangerous attribute available for mass assignment.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, there was a duplicate code issue that was ignored due to a future project. The following files have a duplicate method, self.export_fields(options):&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; user.rb&lt;br /&gt;
&amp;lt;li&amp;gt; participant.rb&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further clarification with regard to ignored Code Climate issues please contact our mentor.&lt;br /&gt;
&lt;br /&gt;
== Project Implementation ==&lt;br /&gt;
&lt;br /&gt;
Talk about how we fixed the most common issues reported by Code Climate.&lt;br /&gt;
&lt;br /&gt;
=== Most Common Issues Reported by Code Climate ===&lt;br /&gt;
&lt;br /&gt;
As we worked on the Code Climate issues for the Expertiza project, we noticed a set of common code smells and issues made by software developers. Since these issues can easily be avoided and most importantly, avoiding them improves code quality, we decided to ''warn'' all Expertiza developers about them by providing the list of these issues, their descriptions, how they can be avoided, and how the code quality can be improved.&lt;br /&gt;
&lt;br /&gt;
* Do not use ''Time.now'' or ''Time.parse'' without zone.&lt;br /&gt;
This is very common issue reported by Code Climate. Since time is relative and may have different values (UTC, EST, and etc), it is a good practice to specify the time zone, whenever the ''Time'' class used.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''Time.parse'' and ''Time.zone.parse'' behave differently for invalid or unknown time. While  returns an error for invalid or unknown times,  returns nil for those types.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.parse'' - returns an error for invalid or unknown time. Generally, can be handled by ''rescue''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Time.zone.parse'' - returns ''nil'' for invalid or unknown time. It must be handled differently.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if invalid or unknown time is given (with ''if/else'' block, ''return'', or ''or'' statements, and etc.) Do not assume that time will always be valid instance. For example, (code sample is used from ''app/models/student_task.rb'' file):&lt;br /&gt;
  # Bad - use Time without zone and rescue if time is invalid or unknown &lt;br /&gt;
  stage_deadline: (Time.parse(participant.stage_deadline) rescue Time.now + 1.year)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use Time with zone and using or statement to handle nil case&lt;br /&gt;
  stage_deadline: (Time.zone.parse(participant.stage_deadline) || (Time.zone.now + 1.year))&lt;br /&gt;
Above example is good practice how ''Time'' class should be used.&lt;br /&gt;
* Method ''x'' has ''n'' arguments (exceeds 4 allowed). Consider refactoring:&lt;br /&gt;
Any method that takes more than 4 arguments must be refactored with accordance to good RoR coding standards. There are multiple ways to refactor signature of such methods and there is no single standard way of resolving this issue. Each method must be considered separately and requires unique approach to refactor, utilizing hash, array and other Ruby's built-in libraries and tools. Below we provide one sample of how fixed such issue utilizing Ruby's built-in hash (code sample is used from ''app/models/vm_question_response_row.rb'' file):&lt;br /&gt;
  # Bad - initialize method has 5 arguments&lt;br /&gt;
  def initialize(question_text, question_id, weight, question_max_score, seq)&lt;br /&gt;
    @question_text = question_text&lt;br /&gt;
    @weight = weight&lt;br /&gt;
    @question_id = question_id&lt;br /&gt;
    @question_seq = seq&lt;br /&gt;
    @question_max_score = question_max_score&lt;br /&gt;
  &lt;br /&gt;
  # Good - initialize method has 1 argument, hash&lt;br /&gt;
  def initialize(question_data)&lt;br /&gt;
    @question_text = question_data[:text]&lt;br /&gt;
    @question_id = question_data[:id]&lt;br /&gt;
    @weight = question_data[:weight]&lt;br /&gt;
    @question_max_score = question_data[:max_score]&lt;br /&gt;
    @question_seq = question_data[:seq]&lt;br /&gt;
''Note'' that since method signature is changed, it of the callers must be changed accordingly to adapt new method signature. For example, the following is illustration of such change to adapt above refactored method signature (code sample is used from ''app/models/vm_question_response.rb'' file):&lt;br /&gt;
  # Bad - passing in 5 arguments to the constructor&lt;br /&gt;
  row = VmQuestionResponseRow.new(question.txt, question.id, question.weight, question_max_score, question.seq)&lt;br /&gt;
  &lt;br /&gt;
  # Good - passing in 1 argument to the constructor, hash&lt;br /&gt;
  row = VmQuestionResponseRow.new(text: question.txt, id: question.id, weight: question.weight, max_score: question_max_score, seq: question.seq)&lt;br /&gt;
* Prefer ''each'' over ''for'':&lt;br /&gt;
We noticed there is a lot of iteration in the code using ''for'' loop instead of ''each''. Generally, you want to avoid any ''for'' loops and use ''each'', ''each_index'', ''each_with_index'', ''upto'' and etc. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for user_signup_topic in user_signup&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of each&lt;br /&gt;
  user_signup.each do |user_signup_topic|&lt;br /&gt;
    return false if user_signup_topic.is_waitlisted == false&lt;br /&gt;
Similarly, if you need to iterate the given block, passing in integer as an index, utilize ''each_index'', ''each_with_index'', ''upto'' instead of ''for''. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' file):&lt;br /&gt;
  # Bad - use of for loop&lt;br /&gt;
  for round in 1..@review_rounds&lt;br /&gt;
    process_review_round(assignment_id, due_date, round, topic)&lt;br /&gt;
  &lt;br /&gt;
  # Good - use of upto&lt;br /&gt;
  1.upto(@review_rounds) do |r|&lt;br /&gt;
    process_review_round(assignment_id, due_date, r, topic)&lt;br /&gt;
* Specify an '':inverse_of option'':&lt;br /&gt;
Whenever there are two models defined with many|one-to-one relationship (''has_many''|''has_one'' and ''belongs_to'' association) out of scope of each other or with certain options used (e.g. ''foreign_key:'' and etc.), Active Record is unable to determine the inverse association of them. This would cause redundant look up operation performed on the database for the same object. It is not really an issue that could cause significant problems, but for such massive application like Experiza, it could affect performance and cause delay in response. Therefore, the '':inverse_of'' option must be specified manually to use the associated object in memory instead of loading it from database twice. For example, (code sample is used from ''app/models/teams_user.rb'' and ''app/models/team_user_node.rb'' files respectively):&lt;br /&gt;
  class TeamsUser &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_one :team_user_node, foreign_key: 'node_object_id', dependent: :destroy, inverse_of: 'node_object'&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  class TeamUserNode &amp;lt; Node&lt;br /&gt;
    belongs_to :node_object, class_name: 'TeamsUser', inverse_of: :team_user_node&lt;br /&gt;
  end&lt;br /&gt;
* Specify a '':dependent'' option:&lt;br /&gt;
The [https://guides.rubyonrails.org/association_basics.html#the-has-many-association has_many] association should always be specified with one of the [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options :dependent] options, which specifies the behavior of the associated objects whenever their owner is destroyed. This is common practice and should be utilized adequately for the Expertiza app to work correctly. No specifying '':dependent'' option could lead to run time errors, unpredictable behavior of the app, and creating orphan objects that will never be referenced again. Specify a '':dependent'' option whenever utilizing ''has_many'' association. For example, (code sample is used from ''app/models/site_controller.rb'' file):&lt;br /&gt;
  # Bad - not specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions&lt;br /&gt;
  &lt;br /&gt;
  # Good - specifying a :dependent option&lt;br /&gt;
  class SiteController &amp;lt; ActiveRecord::Base&lt;br /&gt;
    has_many :controller_actions, dependent: :destroy&lt;br /&gt;
* Tagging a string as html safe may be a security risk. This Code Climate issue&lt;br /&gt;
For example,&lt;br /&gt;
  html.html_safe # George can you please talk about it how you fixed it&lt;br /&gt;
* Use a guard clause instead of wrapping the code inside a conditional expression.&lt;br /&gt;
This is very common issue reported by Code Climate that can be easily avoided by properly utilizing `if` statements applying some logic. In general, avoid using bulk of ''if/else'' statements whenever possible. For example, (code sample is used from ''app/models/sign_up_topic.rb'' file):&lt;br /&gt;
  # Bad - too many conditional expressions that also contain nested ones&lt;br /&gt;
  if !no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
    if topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
      return true&lt;br /&gt;
    else&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Good - use guard close&lt;br /&gt;
  return true if no_of_students_who_selected_the_topic.nil?&lt;br /&gt;
  topic.max_choosers &amp;gt; no_of_students_who_selected_the_topic.size&lt;br /&gt;
Above is typical example when 9 lines of code (LoC) can be reduced to 2 LoC and overall code quality improved. &lt;br /&gt;
* Use ''find_by'' instead of ''where.first'':&lt;br /&gt;
Always use ''find_by'' with an attempt to find the first record matching the specified conditions.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that ''find_by'' and ''where.first'' behave differently if no record was found based on specified conditions.&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.find_by'' - if there is a record match, returns the object. If there is no record match, returns ''nil''&lt;br /&gt;
&amp;lt;li&amp;gt; ''Model.where.first'' - if there is a record match, returns first ActiveRecord::Relation matched. If there is no record match, returns an ''empty'' ActiveRecord::Relation&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Therefore, always handle ''nil'' appropriately if there is no record match (with ''if/else'' block, ''return'' statement and etc.) Do not assume that the record will always be found (since ''empty'' relation skips iteration and ''nil'' throws an error if attempt to iterate). For example,&lt;br /&gt;
  user = User.find_by(name: row_hash[index.to_sym].to_s)&lt;br /&gt;
  raise ImportError, &amp;quot;The user, &amp;quot; + row_hash[index.to_sym].to_s.strip + &amp;quot;, was not found.&amp;quot; if user.nil?&lt;br /&gt;
Similar to this issue Code Climate reported &amp;quot;Use ''find_by'' instead of dynamic ''find_by_name''&amp;quot; issue. It is resolved in the same manner as the above issue by changing ''find_by_name'' to ''find_by'' query and properly handling returned edge-cases (e.g. ''nil''). &lt;br /&gt;
* Use ''snake_case'' for method names and for variable names:&lt;br /&gt;
There are a lot of instances where developers use ''camelCase'' instead of ''snake_case'' in the Expertiza project naming methods and variables. Since Expertiza project is based on RoR, it is  preferred to use ''snake_case'' for all method and variable names. For example, (code sample is used from ''app/models/sign_up_sheet.rb'' and ''app/models/sign_up_topic.rb'' files receptively):&lt;br /&gt;
  # Bad method name - camelCase&lt;br /&gt;
  def self.slotAvailable?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  def self.slot_available?(topic_id)&lt;br /&gt;
  &lt;br /&gt;
  # Bad variable name - camelCase&lt;br /&gt;
  dropDate = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
  &lt;br /&gt;
  # Good method name - snake_case&lt;br /&gt;
  drop_date = AssignmentDueDate.where(parent_id: assignment.id, deadline_type_id: '6').first&lt;br /&gt;
&lt;br /&gt;
=== Resolved Code Climate Issues ===&lt;br /&gt;
&lt;br /&gt;
Along with [http://wiki.expertiza.ncsu.edu/index.php/E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] we also fixed and verified numerous other code smells. The following is the list of all issues we have resolved. We do not provide solutions for them since most of them were trivial code changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Argument ''x'' was shadowed by a local variable before it was used.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid more than 3 levels of block nesting.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid too many return statements within the method.&lt;br /&gt;
&amp;lt;li&amp;gt; Avoid using ''update_attribute'' because it skips validations.&lt;br /&gt;
&amp;lt;li&amp;gt; Combine ''_type&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;'' and &amp;quot; into a single string literal, rather than using implicit string concatenation.&lt;br /&gt;
&amp;lt;li&amp;gt; Consider simplifying this complex logical expression.&lt;br /&gt;
&amp;lt;li&amp;gt; Convert ''if'' nested inside ''else'' to ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not introduce global variables.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not place comments on the same line as the ''end'' keyword.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix reader method names with ''get_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not prefix writer method names with ''set_''.&lt;br /&gt;
&amp;lt;li&amp;gt; Do not use ''DateTime.parse.strftime'' without zone. Use one of ''Time.zone.parse.strftime'', ''DateTime.current'', ''DateTime.parse.strftime.in_time_zone'', ''DateTime.parse.strftime.utc'', ''DateTime.parse.strftime.getlocal'', ''DateTime.parse.strftime.iso8601'', ''DateTime.parse.strftime.jisx0301'', ''DateTime.parse.strftime.rfc3339'', ''DateTime.parse.strftime.to_i'', ''DateTime.parse.strftime.to_f'' instead.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body beginning.&lt;br /&gt;
&amp;lt;li&amp;gt; Extra empty line detected at method body end.&lt;br /&gt;
&amp;lt;li&amp;gt; ''end'' at ''xxx'', ''xx'' is not aligned with ''unless'' (or ''def'') at ''xxx'', ''xx''.&lt;br /&gt;
&amp;lt;li&amp;gt; Identical blocks of code found in ''n'' locations. Consider refactoring. &lt;br /&gt;
&amp;lt;li&amp;gt; Line is too long.&lt;br /&gt;
&amp;lt;li&amp;gt; Method ''x'' is defined at both ''app/models/y.rb'' and ''app/models/z.rb''&lt;br /&gt;
&amp;lt;li&amp;gt; Optional arguments should appear at the end of the argument list.&lt;br /&gt;
&amp;lt;li&amp;gt; Place the condition on the same line as ''elsif''.&lt;br /&gt;
&amp;lt;li&amp;gt; Prefer Date or Time over DateTime.&lt;br /&gt;
&amp;lt;li&amp;gt; Redundant use of ''Object#to_s'' in interpolation.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''has_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Rename ''is_x'' to ''x?''.&lt;br /&gt;
&amp;lt;li&amp;gt; Replace class var ''@@variable_name'' with a class instance var.&lt;br /&gt;
&amp;lt;li&amp;gt; Similar blocks of code found in ''n'' locations. Consider refactoring.&lt;br /&gt;
&amp;lt;li&amp;gt; Unnecessary spacing detected.&lt;br /&gt;
&amp;lt;li&amp;gt; Unused method argument - ''x''. If it's necessary, use ''_'' or ''_x'' as an argument name to indicate that it won't be used.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''find_by'' instead of ''where.first''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''x.zero?'' instead of ''x == 0''.&lt;br /&gt;
&amp;lt;li&amp;gt; Use ''=='' if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.&lt;br /&gt;
&amp;lt;li&amp;gt; Useless assignment to variable - ''x''.&lt;br /&gt;
&amp;lt;li&amp;gt; Variable ''x'' used in void context.&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional Improvements ===&lt;br /&gt;
&lt;br /&gt;
While our primary task was to fix code smells reported by Code Climate, we also attempted to improve overall quality of code along the way. We introduced several minor changes that we believe improve the code, and encourage all software engineers working on the Expertiza source code to maintain clean and efficient software. All additional improvements are listed and described below.&lt;br /&gt;
&lt;br /&gt;
* Meaningful names for class and instance variables.&lt;br /&gt;
There were several files where names for class or instance variables did not meet good naming conventions. For example, in the ''app/models/vm_question_response_row.rb'' file, instance variable &lt;br /&gt;
  no_of_columns&lt;br /&gt;
indicating number of columns that refer to count of reviews, was re-named with&lt;br /&gt;
  count_columns&lt;br /&gt;
Above is only an example of how we attempted to improve readability of the code.&lt;br /&gt;
* More comments where is needed.&lt;br /&gt;
In general there is sufficient amount of comments to fully understand the code and follow the flow. However, some of the functionalities are not as trivial and additional comments help a lot faster understand what the code does.&lt;br /&gt;
We added such comments in all the places where we fixed Climate Code issues. We also ensured to provide only sufficient comments to keep code as clean as possible and at the same time to clarify any complexity.&lt;br /&gt;
* Eliminate DRY code.&lt;br /&gt;
We tried to combine all of the duplicated code into a single functionality and eliminate any repetitive statements. Most of these issues were taken care by fixing &amp;quot;Similar blocks of code found in ''n'' locations&amp;quot; and &amp;quot;Identical blocks of code found in ''n'' locations&amp;quot; Code Climate issues. However, in some files Code Climate did not report such issues, although there were obvious repetitive statements. For example, ''add_reviews'' method in the ''app/models/vm_question_response.rb'' file had 4 places of the repetitive code and it was different only by data retrieved from various tables as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = ReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;AuthorFeedbackQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = FeedbackResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;TeammateReviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = TeammateReviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
  elsif @questionnaire_type == &amp;quot;MetareviewQuestionnaire&amp;quot;&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = MetareviewResponseMap.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code as everywhere else&lt;br /&gt;
The above duplicate code was refactored to eliminate all repetitive statements and make the code more efficient as follows:&lt;br /&gt;
  if @questionnaire_type == 'ReviewQuestionnaire'&lt;br /&gt;
    reviews = ...&lt;br /&gt;
    response_map = 'ReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'AuthorFeedbackQuestionnaire'&lt;br /&gt;
    reviews = participant.feedback&lt;br /&gt;
    response_map = 'FeedbackResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'TeammateReviewQuestionnaire'&lt;br /&gt;
    reviews = participant.teammate_reviews&lt;br /&gt;
    response_map = 'TeammateReviewResponseMap'.constantize&lt;br /&gt;
  elsif @questionnaire_type == 'MetareviewQuestionnaire'&lt;br /&gt;
    reviews = participant.metareviews&lt;br /&gt;
    response_map = 'MetareviewResponseMap'.constantize&lt;br /&gt;
  end&lt;br /&gt;
  # All repetitive code was extracted and now is common&lt;br /&gt;
  unless reviews.nil?&lt;br /&gt;
    reviews.each do |review|&lt;br /&gt;
      review_mapping = response_map.find_by(id: review.map_id)&lt;br /&gt;
      # Repetitive code&lt;br /&gt;
Again this is only single sample where improvements was made.&lt;br /&gt;
&lt;br /&gt;
=== Remaining Issues ===&lt;br /&gt;
&lt;br /&gt;
Unfortunately, Expertiza has some remaining issues reported by Code Climate in the files under ''app/models'' directory (names beginning with '''Se''' through '''Z''') that we were asked to ignore in this project. These issues described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Ignored_Code_Climate_Smells Ignored Code Climate Smells] section above and why there were ignored. Although these code smells do not impose any problems into existing code and application, we strongly believe that all of remaining issues must be fixed.&lt;br /&gt;
&lt;br /&gt;
We did not find any further issues besides what we already reported and fixed it.&lt;br /&gt;
&lt;br /&gt;
=== Further Suggestions ===&lt;br /&gt;
&lt;br /&gt;
We suggest and encourage to fix all of the remaining issues that were intentionally ignored per the projects requirements in all of the files under ''app/models'' directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We also suggest to maintain clean, efficient, well-commented, and well-tested code in the Expertiza project. Prior delivering any changes to the ''master'' or ''beta'' branches, we recommend to test your software in the following manner:&lt;br /&gt;
# Code inspection&lt;br /&gt;
# Passing existing Rspec tests&lt;br /&gt;
# Adding new Rspec test that cover changes&lt;br /&gt;
# Running through a live demo in the Expertiza instance through the UI&lt;br /&gt;
Furthermore, we noticed that currently Expertiza project has ~53% test coverage, which is relatively small test coverage for such a massive project. Remember, &amp;quot;Debugging - sucks, and Testing - rocks!&amp;quot;. We encourage Expertiza software developers to reach at least (minimum) 85% test coverage. That must cover all vital functionalities of the application and reduce any possibilities of introducing new issues into the system.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request ===&lt;br /&gt;
&lt;br /&gt;
Let's add some info about pull request&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
There we 2 types of frame works that we used to verify our code modifications/creation within the models: RSpec and Travis CI.&lt;br /&gt;
&lt;br /&gt;
RSpec was used to locally test the changes we had implemented without having to Push the change to the GitHub, this is discussed more in-depth in the section below.&lt;br /&gt;
&lt;br /&gt;
Travis CI is a more comprehensive testing used by the Expetiza team to verify code changes from multiple sources, (.i.e forks from students). Travis CI will analyze the code once you Push your changes to the GitHub server for your given repository. Travis CI will need to be setup independently for your repository&lt;br /&gt;
&lt;br /&gt;
Talk about Testing we performed&lt;br /&gt;
&lt;br /&gt;
=== Rspec Testing ===&lt;br /&gt;
&lt;br /&gt;
To verify the code changes we made did not break the existing application, we used the RSpec Testing Framework. Several of the models already had existing RSpecs Tests already created. For those, we just simply ran the corresponding test via the terminal window. Example&lt;br /&gt;
   rspec spec/models/tag_prompt_spec.rb&lt;br /&gt;
   &lt;br /&gt;
   *rspec path/to/spec/file.rb*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would execute the RSpec test for the tag_prompt.rb file located in the app/models folder. As you can see, there is a particular format that is used when naming the RSpec file: &lt;br /&gt;
    model_name_spec.rb&lt;br /&gt;
&lt;br /&gt;
Once the execution of the RSpec model testing is completed, results will be display&lt;br /&gt;
    $ rspec spec/models/tag_prompt_spec.rb                                                                                                                                                     [10:45:15]&lt;br /&gt;
    [Coveralls] Set up the SimpleCov formatter.&lt;br /&gt;
    [Coveralls] Using SimpleCov's 'rails' settings.&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    .........&lt;br /&gt;
    Finished in 3.35 seconds (files took 23.23 seconds to load)&lt;br /&gt;
    9 examples, 0 failures&lt;br /&gt;
    Randomized with seed 19443&lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 1254 / 17313 LOC (7.24%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition to running the individual RSpec Test, we also executed broader in scope testing. To achieve this, we executed the following command in the terminal window:&lt;br /&gt;
    $ bundle exec rspec --seed 5114  &lt;br /&gt;
&lt;br /&gt;
This produces the following results:&lt;br /&gt;
&lt;br /&gt;
    Finished in 1 minute 11.23 seconds (files took 23.19 seconds to load)&lt;br /&gt;
    131 examples, 1 failure, 1 pending&lt;br /&gt;
    &lt;br /&gt;
    Failed examples:&lt;br /&gt;
    &lt;br /&gt;
    rspec ./spec/features/assignment_creation_spec.rb:707 # assignment function check to find if the assignment can be added to a course&lt;br /&gt;
    &lt;br /&gt;
    Randomized with seed 5114&lt;br /&gt;
        &lt;br /&gt;
    Coverage report generated for RSpec to /home/expertiza_developer/RubymineProjects/expertiza_testbed/coverage. 2998 / 14031 LOC (21.37%) covered.&lt;br /&gt;
    [Coveralls] Outside the CI environment, not sending data.&lt;br /&gt;
    FAIL: 1&lt;br /&gt;
&lt;br /&gt;
As you can see from the examples above there are failures. However, we are only looking for failures caused by the code we modified/created in a given model. In this case, all code we have created/modified is not causing failures.&lt;br /&gt;
&lt;br /&gt;
=== UI Testing ===&lt;br /&gt;
&lt;br /&gt;
We concentrated our UI testing based on how changes to Code Climate issues affected the interface between callers and methods. Two main culprits were found.&lt;br /&gt;
# Change of ''Time.parse'' to ''Time.zone.parse''. While ''Time.parse'' returns an error for invalid or unknown times, ''Time.zone.parse'' returns ''nil'' for those types.&lt;br /&gt;
# Change of ''where().first'' to ''find_by()'' query. Using ''where().first'' returns empty records if record is not found, while ''find_by()'' returns ''nil'' if there was no match.&lt;br /&gt;
Note both of the above changes are well described in the [http://wiki.expertiza.ncsu.edu/index.php?title=E1920_Fix_Code_Climate_Issues#Most_Common_Issues_Reported_by_Code_Climate Most Common Issues Reported by Code Climate] section above. The section describes how such cases must be handled properly.&lt;br /&gt;
&lt;br /&gt;
The user interface testing concentrated on three type of user stories.&lt;br /&gt;
# General functionality, could users still access the basic menu items from before.&lt;br /&gt;
# Test time functionality, such as sorting based on timestamp.&lt;br /&gt;
# Test searching functionality (involving all changes of ''where().first'' to ''find_by()'').&lt;br /&gt;
UI testing helped us revealed all the problems that were introduced along with our fixes and running through UI live demos ensured that we have fully functioning and properly working Expertiza app.&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
Talk about conclusion.&lt;br /&gt;
&lt;br /&gt;
== Team Contacts and Contribution ==&lt;br /&gt;
&lt;br /&gt;
We have 3 (three) members in our team and 1 (one) mentor was assigned to us. For any project-related questions/concerns please contact us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Christopher Adkins - cladkins@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; George Hugh - gshugh@ncsu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Nikolay G. Titov - ngtitov@ncu.edu&lt;br /&gt;
&amp;lt;li&amp;gt; Zachariah Mathews (mentor) - zmathew@ncsu.edu&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you have questions or concerns related to a specific file that was improved/modified by our team, please contact an engineer who worked on the file based on the [https://docs.google.com/spreadsheets/d/1bX2XizitGGoajFT6Br_y6MQjAwBCsX5WCVlx3xg8Jp8/edit?ts=5c87a06c#gid=0 Assignment Grid] we created to keep track of our progress and contribution. Please CC in email all team members and our mentor.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* Ruby [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/InverseOf]&lt;br /&gt;
* CodeClimate [https://docs.codeclimate.com/docs]&lt;br /&gt;
* Expertiza [https://github.com/expertiza/expertiza#expertiza]&lt;br /&gt;
* E. F. Gehringer, L. M. Ehresman, S. G. Conger and P. A. Wagle, &amp;quot;Work in Progress: Reusable Learning Objects Through Peer Review: The Expertiza Approach,&amp;quot; Proceedings. Frontiers in Education. 36th Annual Conference, San Diego, CA, 2006, pp. 1-2. [http://ieeexplore.ieee.org.prox.lib.ncsu.edu/stamp/stamp.jsp?tp=&amp;amp;arnumber=4117076&amp;amp;isnumber=4116830]&lt;br /&gt;
* The ''has_many'' Association [https://guides.rubyonrails.org/association_basics.html#the-has-many-association]&lt;br /&gt;
* Module ActiveRecord::Associations::ClassMethods Options [https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Options]&lt;br /&gt;
* TimeZone Class [https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Rails/TimeZone]&lt;/div&gt;</summary>
		<author><name>Gshugh</name></author>
	</entry>
</feed>