<?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=Bharcha</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=Bharcha"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Bharcha"/>
	<updated>2026-06-05T21:52:20Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152685</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152685"/>
		<updated>2023-12-05T05:21:20Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Class UML Diagram==&lt;br /&gt;
[[File:UML-Diagram.png ‎| 900px]]&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_new.jpeg ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
#assignment.rb&lt;br /&gt;
#asssignments_controller.rb&lt;br /&gt;
#routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
#20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
#20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
#20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
#20231129050431_create_sign_up_topics.rb&lt;br /&gt;
#20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
#20231130030500_create_signed_up_teams.rb&lt;br /&gt;
#20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
#20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
#20231130033226_create_teams_users.rb&lt;br /&gt;
#20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
#20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
#20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
#20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
==Testing model methods==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: &lt;br /&gt;
*when the required number is less than or equal to the allowed number (expected to return success)&lt;br /&gt;
*when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
*when review type is invalid&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is invalid' do&lt;br /&gt;
      it 'returns an error message for an invalid review_type' do&lt;br /&gt;
        result = assignment.valid_num_review('invalid_type')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Please enter a valid review type.')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
*Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
*Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
*Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
*Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
*Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
*Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
*Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
*Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
*Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
*Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
*Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
*Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller test plan==&lt;br /&gt;
&lt;br /&gt;
==Add Participant to Assignment==&lt;br /&gt;
Endpoint: POST /api/v1/assignments/{assignment_id}/add_participant/{user_id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Add a participant to an existing assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to add a participant to a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, response contains participant details.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
 post 'Adds a participant to an assignment' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'participant added successfully' do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
        let(:user_id) { user.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['id']).to be_present&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 3 }&lt;br /&gt;
        let(:user_id) { 1 }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Remove Participant from Assignment==&lt;br /&gt;
Endpoint: DELETE /api/v1/assignments/{assignment_id}/remove_participant/{user_id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Remove a participant from an assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to remove a participant from a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, participant removed successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment or user not found.&lt;br /&gt;
'''&lt;br /&gt;
delete 'Removes a participant from an assignment' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'participant removed successfully' do&lt;br /&gt;
        let(:user_id) { user.id }&lt;br /&gt;
        let(:assignment) {create(:assignment)}&lt;br /&gt;
        let(:assignment_id) {assignment.id}&lt;br /&gt;
&lt;br /&gt;
        before do&lt;br /&gt;
          assignment.add_participant(user.id)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment or user not found' do&lt;br /&gt;
        let(:assignment_id) { 4 }&lt;br /&gt;
        let(:user_id) { 1 }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Assign Course to Assignment==&lt;br /&gt;
Endpoint: PATCH /api/v1/assignments/{assignment_id}/assign_courses_to_assignment/{course_id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Assign a course to an assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to assign a course to a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, course assigned successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
patch 'Make course_id of assignment null' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'course_id assigned successfully' do&lt;br /&gt;
        let(:course) { create(:course)}&lt;br /&gt;
        let(:course_id) { course.id }&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['course_id']).to eq(course.id)&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 3 }&lt;br /&gt;
        let(:course) { create(:course)}&lt;br /&gt;
        let(:course_id) {course.id}&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Remove Assignment from Course==&lt;br /&gt;
Endpoint: PATCH /api/v1/assignments/{assignment_id}/remove_assignment_from_course&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Remove an assignment from a course.&lt;br /&gt;
&lt;br /&gt;
Attempt to remove a non-existent assignment from a course.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment removed from course.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
patch 'Removes assignment from course' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: :assignment_id, in: :path, type: :integer, required: true&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      response '200', 'assignment removed from course' do&lt;br /&gt;
        let(:course) { create(:course) }&lt;br /&gt;
        let(:assignment) { create(:assignment,  course: course)}&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
        let(:course_id) { course.id }&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['course_id']).to be_nil&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 4 }&lt;br /&gt;
        let(:course_id) {1}&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body)&lt;br /&gt;
          expect(response_json['error']).to eq('Assignment not found')&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Copy Assignment==&lt;br /&gt;
Endpoint: POST /api/v1/assignments/{assignment_id}/copy_assignment&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Copy an existing assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to copy a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment copied successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
post 'Copy an existing assignment' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'assignment copied successfully' do&lt;br /&gt;
        let(:assignment) { create(:assignment) } # Assuming you have a Factory for Assignment&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['id']).to be_present&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 4 }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Delete Assignment==&lt;br /&gt;
Endpoint: DELETE /api/v1/assignments/{id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Delete an existing assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to delete a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment deleted successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
delete('Delete an assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['message']).to eq('Assignment deleted successfully!')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has a Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has a badge.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for a badge.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment has a badge.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has a badge') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if pair programming is enabled for an assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for pair programming.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, pair programming is enabled.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if pair programming is enabled for an assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has Topics==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has topics.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for topics.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment has topics.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has topics') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment is a team assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for being a team assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment is a team assignment.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment is a team assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has a Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/valid_num_review/{review_type}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has a valid number of reviews for a specific type.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for reviews.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, valid number of reviews for the specified type.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has a valid number of reviews for a specific type') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
        let(:review_type) { 'review' }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
        let(:review_type) { 'some_type' }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment is calibrated.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for calibration.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment is calibrated.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment is calibrated') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has Teams==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has teams.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for teams.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment has teams.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has teams') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Topic==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment is staggered and has no topic.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for staggered and no topic.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment is staggered and has no topic.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment is staggered and has no topic') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Create Node for Assignment==&lt;br /&gt;
Endpoint: POST /api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
 &lt;br /&gt;
Create a node for an assignment. &lt;br /&gt;
&lt;br /&gt;
Attempt to create a node for a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, node created successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
post('Create a node for an assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has Varying Rubrics by Round==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has varying rubrics by round.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for varying rubrics.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment has varying rubrics by round.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
parameter name: 'assignment_id', in: :path, type: :integer, description: 'Assignment ID'&lt;br /&gt;
&lt;br /&gt;
  get('Check if an assignment has varying rubrics by round') do&lt;br /&gt;
    tags 'Assignments'&lt;br /&gt;
    produces 'application/json'&lt;br /&gt;
    parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
    parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
    let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
    let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
    response(200, 'successful') do&lt;br /&gt;
      let(:questionnaire) { create(:questionnaire) }&lt;br /&gt;
      let(:assignment) { create(:assignment) }&lt;br /&gt;
      let(:assignment_id) {assignment.id}&lt;br /&gt;
      let(:assignment_questionnaire) { create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1) }&lt;br /&gt;
      &lt;br /&gt;
&lt;br /&gt;
      run_test! do |response|&lt;br /&gt;
        expect(response).to have_http_status(:ok)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    response(404, 'Assignment not found') do&lt;br /&gt;
      let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
      run_test! do |response|&lt;br /&gt;
        data = JSON.parse(response.body)&lt;br /&gt;
        expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Test Coverage==&lt;br /&gt;
We used SimpleCov to generate a coverage report for the Rspec test cases impleneted for Assignment model. The test coverage indicated 97.62% percent of code was covered through the testcases.&lt;br /&gt;
&lt;br /&gt;
[[File:Code-Coverage-Assignment-Model.png ‎| 1200px]]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Swagger Video Link:[https://youtu.be/HvHY0VzYCFs]&lt;br /&gt;
&lt;br /&gt;
Pull request:[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
Model Tests Video:[https://www.youtube.com/watch?v=TAuoHEqiRXo]&lt;br /&gt;
&lt;br /&gt;
Controller Tests Video:[https://youtu.be/sOGkLLMThQ4]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152679</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152679"/>
		<updated>2023-12-05T05:18:05Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Class UML Diagram==&lt;br /&gt;
[[File:UML-Diagram.png ‎| 900px]]&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_new.jpeg ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
#assignment.rb&lt;br /&gt;
#asssignments_controller.rb&lt;br /&gt;
#routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
#20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
#20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
#20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
#20231129050431_create_sign_up_topics.rb&lt;br /&gt;
#20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
#20231130030500_create_signed_up_teams.rb&lt;br /&gt;
#20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
#20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
#20231130033226_create_teams_users.rb&lt;br /&gt;
#20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
#20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
#20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
#20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
==Testing model methods==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: &lt;br /&gt;
*when the required number is less than or equal to the allowed number (expected to return success)&lt;br /&gt;
*when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
*when review type is invalid&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is invalid' do&lt;br /&gt;
      it 'returns an error message for an invalid review_type' do&lt;br /&gt;
        result = assignment.valid_num_review('invalid_type')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Please enter a valid review type.')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
*Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
*Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
*Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
*Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
*Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
*Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
*Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
*Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
*Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
*Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
*Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
*Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller test plan==&lt;br /&gt;
&lt;br /&gt;
==Add Participant to Assignment==&lt;br /&gt;
Endpoint: POST /api/v1/assignments/{assignment_id}/add_participant/{user_id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Add a participant to an existing assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to add a participant to a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, response contains participant details.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
 post 'Adds a participant to an assignment' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'participant added successfully' do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
        let(:user_id) { user.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['id']).to be_present&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 3 }&lt;br /&gt;
        let(:user_id) { 1 }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Remove Participant from Assignment==&lt;br /&gt;
Endpoint: DELETE /api/v1/assignments/{assignment_id}/remove_participant/{user_id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Remove a participant from an assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to remove a participant from a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, participant removed successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment or user not found.&lt;br /&gt;
'''&lt;br /&gt;
delete 'Removes a participant from an assignment' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'participant removed successfully' do&lt;br /&gt;
        let(:user_id) { user.id }&lt;br /&gt;
        let(:assignment) {create(:assignment)}&lt;br /&gt;
        let(:assignment_id) {assignment.id}&lt;br /&gt;
&lt;br /&gt;
        before do&lt;br /&gt;
          assignment.add_participant(user.id)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment or user not found' do&lt;br /&gt;
        let(:assignment_id) { 4 }&lt;br /&gt;
        let(:user_id) { 1 }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Assign Course to Assignment==&lt;br /&gt;
Endpoint: PATCH /api/v1/assignments/{assignment_id}/assign_courses_to_assignment/{course_id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Assign a course to an assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to assign a course to a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, course assigned successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
patch 'Make course_id of assignment null' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'course_id assigned successfully' do&lt;br /&gt;
        let(:course) { create(:course)}&lt;br /&gt;
        let(:course_id) { course.id }&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['course_id']).to eq(course.id)&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 3 }&lt;br /&gt;
        let(:course) { create(:course)}&lt;br /&gt;
        let(:course_id) {course.id}&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Remove Assignment from Course==&lt;br /&gt;
Endpoint: PATCH /api/v1/assignments/{assignment_id}/remove_assignment_from_course&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Remove an assignment from a course.&lt;br /&gt;
&lt;br /&gt;
Attempt to remove a non-existent assignment from a course.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment removed from course.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
patch 'Removes assignment from course' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: :assignment_id, in: :path, type: :integer, required: true&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      response '200', 'assignment removed from course' do&lt;br /&gt;
        let(:course) { create(:course) }&lt;br /&gt;
        let(:assignment) { create(:assignment,  course: course)}&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
        let(:course_id) { course.id }&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['course_id']).to be_nil&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 4 }&lt;br /&gt;
        let(:course_id) {1}&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body)&lt;br /&gt;
          expect(response_json['error']).to eq('Assignment not found')&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Copy Assignment==&lt;br /&gt;
Endpoint: POST /api/v1/assignments/{assignment_id}/copy_assignment&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Copy an existing assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to copy a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment copied successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
post 'Copy an existing assignment' do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response '200', 'assignment copied successfully' do&lt;br /&gt;
        let(:assignment) { create(:assignment) } # Assuming you have a Factory for Assignment&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          response_json = JSON.parse(response.body) # Parse the response body as JSON&lt;br /&gt;
          expect(response_json['id']).to be_present&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response '404', 'assignment not found' do&lt;br /&gt;
        let(:assignment_id) { 4 }&lt;br /&gt;
&lt;br /&gt;
        run_test! do&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Delete Assignment==&lt;br /&gt;
Endpoint: DELETE /api/v1/assignments/{id}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Delete an existing assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to delete a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment deleted successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
delete('Delete an assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['message']).to eq('Assignment deleted successfully!')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has a Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has a badge.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for a badge.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment has a badge.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has a badge') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if pair programming is enabled for an assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for pair programming.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, pair programming is enabled.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if pair programming is enabled for an assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:not_found)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has Topics==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has topics.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for topics.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment has topics.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has topics') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment is a team assignment.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for being a team assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment is a team assignment.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment is a team assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has a Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/valid_num_review/{review_type}&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has a valid number of reviews for a specific type.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for reviews.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, valid number of reviews for the specified type.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has a valid number of reviews for a specific type') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
        let(:review_type) { 'review' }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
        let(:review_type) { 'some_type' }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment is calibrated.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for calibration.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment is calibrated.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment is calibrated') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment has Teams==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment has teams.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for teams.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment has teams.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment has teams') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Topic==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
&lt;br /&gt;
Check if an assignment is staggered and has no topic.&lt;br /&gt;
&lt;br /&gt;
Attempt to check a non-existent assignment for staggered and no topic.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, assignment is staggered and has no topic.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
'''&lt;br /&gt;
get('Check if an assignment is staggered and has no topic') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      produces 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Create Node for Assignment==&lt;br /&gt;
Endpoint: POST /api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
&lt;br /&gt;
Test Scenario:&lt;br /&gt;
 &lt;br /&gt;
Create a node for an assignment. &lt;br /&gt;
&lt;br /&gt;
Attempt to create a node for a non-existent assignment.&lt;br /&gt;
&lt;br /&gt;
Expected Outcome:&lt;br /&gt;
&lt;br /&gt;
HTTP status 200, node created successfully.&lt;br /&gt;
&lt;br /&gt;
HTTP status 404, assignment not found.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
post('Create a node for an assignment') do&lt;br /&gt;
      tags 'Assignments'&lt;br /&gt;
      consumes 'application/json'&lt;br /&gt;
      parameter name: 'Authorization', in: :header, type: :string&lt;br /&gt;
      parameter name: 'Content-Type', in: :header, type: :string&lt;br /&gt;
      let('Authorization') { &amp;quot;Bearer #{auth_token}&amp;quot; }&lt;br /&gt;
      let('Content-Type') { 'application/json' }&lt;br /&gt;
&lt;br /&gt;
      response(200, 'successful') do&lt;br /&gt;
        let(:assignment) { create(:assignment) }&lt;br /&gt;
        let(:assignment_id) { assignment.id }&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          expect(response).to have_http_status(:ok)&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      response(404, 'Assignment not found') do&lt;br /&gt;
        let(:assignment_id) { 999 } # Non-existent ID&lt;br /&gt;
&lt;br /&gt;
        run_test! do |response|&lt;br /&gt;
          data = JSON.parse(response.body)&lt;br /&gt;
          expect(data['error']).to eq('Assignment not found')&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
==Test Coverage==&lt;br /&gt;
We used SimpleCov to generate a coverage report for the Rspec test cases impleneted for Assignment model. The test coverage indicated 97.62% percent of code was covered through the testcases.&lt;br /&gt;
&lt;br /&gt;
[[File:Code-Coverage-Assignment-Model.png ‎| 1200px]]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Swagger Video Link:[https://youtu.be/HvHY0VzYCFs]&lt;br /&gt;
&lt;br /&gt;
Pull request:[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
Model Tests Video:[https://www.youtube.com/watch?v=TAuoHEqiRXo]&lt;br /&gt;
&lt;br /&gt;
Controller Tests Video:[https://youtu.be/sOGkLLMThQ4]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152638</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152638"/>
		<updated>2023-12-05T04:42:07Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_new.jpeg ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
#assignment.rb&lt;br /&gt;
#asssignments_controller.rb&lt;br /&gt;
#routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
#20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
#20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
#20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
#20231129050431_create_sign_up_topics.rb&lt;br /&gt;
#20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
#20231130030500_create_signed_up_teams.rb&lt;br /&gt;
#20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
#20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
#20231130033226_create_teams_users.rb&lt;br /&gt;
#20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
#20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
#20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
#20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: &lt;br /&gt;
*when the required number is less than or equal to the allowed number (expected to return success)&lt;br /&gt;
*when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
*when review type is invalid&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is invalid' do&lt;br /&gt;
      it 'returns an error message for an invalid review_type' do&lt;br /&gt;
        result = assignment.valid_num_review('invalid_type')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Please enter a valid review type.')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
*Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
*Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
*Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
*Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
*Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
*Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
*Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
*Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
*Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
*Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
*Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
*Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Test Coverage==&lt;br /&gt;
We used SimpleCov to generate a coverage report for the Rspec test cases impleneted for Assignment model. The test coverage indicated 97.62% percent of code was covered through the testcases.&lt;br /&gt;
&lt;br /&gt;
[[File:Code-Coverage-Assignment-Model.png ‎| 1200px]]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Swagger Video Link:[https://youtu.be/HvHY0VzYCFs]&lt;br /&gt;
&lt;br /&gt;
Pull request:[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
Model Tests Video:[https://www.youtube.com/watch?v=TAuoHEqiRXo]&lt;br /&gt;
&lt;br /&gt;
Controller Tests Video:[https://youtu.be/sOGkLLMThQ4]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152599</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152599"/>
		<updated>2023-12-05T04:05:16Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_new.jpeg ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
#assignment.rb&lt;br /&gt;
#asssignments_controller.rb&lt;br /&gt;
#routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
#20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
#20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
#20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
#20231129050431_create_sign_up_topics.rb&lt;br /&gt;
#20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
#20231130030500_create_signed_up_teams.rb&lt;br /&gt;
#20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
#20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
#20231130033226_create_teams_users.rb&lt;br /&gt;
#20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
#20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
#20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
#20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: &lt;br /&gt;
*when the required number is less than or equal to the allowed number (expected to return success)&lt;br /&gt;
*when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
*when review type is invalid&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is invalid' do&lt;br /&gt;
      it 'returns an error message for an invalid review_type' do&lt;br /&gt;
        result = assignment.valid_num_review('invalid_type')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Please enter a valid review type.')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
*Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
*Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
*Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
*Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
*Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
*Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
*Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
*Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
*Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
*Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
*Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
*Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
*Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
*Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Test Coverage==&lt;br /&gt;
We used SimpleCov to generate a coverage report for the Rspec test cases impleneted for Assignment model. The test coverage indicated 97.65% percent of code was covered through the testcases.&lt;br /&gt;
&lt;br /&gt;
[[File:Code-Coverage-Assignment-Model.png ‎| 1200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Swagger Video Link:&lt;br /&gt;
&lt;br /&gt;
Pull request:[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
Tests Video:&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152575</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152575"/>
		<updated>2023-12-05T03:56:48Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: /* has_badge? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_new.jpeg ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
assignment.rb&lt;br /&gt;
asssignments_controller.rb&lt;br /&gt;
routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
20231129050431_create_sign_up_topics.rb&lt;br /&gt;
20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
20231130030500_create_signed_up_teams.rb&lt;br /&gt;
20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
20231130033226_create_teams_users.rb&lt;br /&gt;
20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Test Coverage==&lt;br /&gt;
We used SimpleCov to generate a coverage report for the Rspec test cases impleneted for Assignment model. The test coverage indicated 97.65% percent of code was covered through the testcases.&lt;br /&gt;
&lt;br /&gt;
[[File:Code-Coverage-Assignment-Model.png ‎| 1200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Swagger Video Link:&lt;br /&gt;
Pull request:&lt;br /&gt;
Tests Video: &lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152573</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152573"/>
		<updated>2023-12-05T03:54:56Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_new.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
assignment.rb&lt;br /&gt;
asssignments_controller.rb&lt;br /&gt;
routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
20231129050431_create_sign_up_topics.rb&lt;br /&gt;
20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
20231130030500_create_signed_up_teams.rb&lt;br /&gt;
20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
20231130033226_create_teams_users.rb&lt;br /&gt;
20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==Test Coverage==&lt;br /&gt;
We used SimpleCov to generate a coverage report for the Rspec test cases impleneted for Assignment model. The test coverage indicated 97.65% percent of code was covered through the testcases.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Swagger Video Link:&lt;br /&gt;
Pull request:&lt;br /&gt;
Tests Video: &lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_badge_new.jpeg&amp;diff=152566</id>
		<title>File:Has badge new.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_badge_new.jpeg&amp;diff=152566"/>
		<updated>2023-12-05T03:52:22Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152562</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152562"/>
		<updated>2023-12-05T03:51:22Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: /* Check if Assignment is Staggered and Has No Assigned Topic for Current User */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET http://localhost/api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
assignment.rb&lt;br /&gt;
asssignments_controller.rb&lt;br /&gt;
routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
20231129050431_create_sign_up_topics.rb&lt;br /&gt;
20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
20231130030500_create_signed_up_teams.rb&lt;br /&gt;
20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
20231130033226_create_teams_users.rb&lt;br /&gt;
20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152561</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152561"/>
		<updated>2023-12-05T03:50:08Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{assignment_id}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET, api/v1/assignments/{assignment_id}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{assignment_id}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET http://localhost/api/v1/assignments/{assignment_id}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{assignment_id}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{assignment_id}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
assignment.rb&lt;br /&gt;
asssignments_controller.rb&lt;br /&gt;
routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
20231129050431_create_sign_up_topics.rb&lt;br /&gt;
20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
20231130030500_create_signed_up_teams.rb&lt;br /&gt;
20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
20231130033226_create_teams_users.rb&lt;br /&gt;
20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We used the given test skeletons for assignment model and implement the respective Rspec test cases. For all the new methods reimplemented in the Assignment model, there are automated test cases implemented using Rspec Framework and FactoryBot. The automated testcases implemented are as follows :&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Varying_rubrics_by_round_controller.png&amp;diff=152558</id>
		<title>File:Varying rubrics by round controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Varying_rubrics_by_round_controller.png&amp;diff=152558"/>
		<updated>2023-12-05T03:44:13Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Valid_num_review_controller.png&amp;diff=152557</id>
		<title>File:Valid num review controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Valid_num_review_controller.png&amp;diff=152557"/>
		<updated>2023-12-05T03:43:56Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Team_assignment_controller.png&amp;diff=152556</id>
		<title>File:Team assignment controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Team_assignment_controller.png&amp;diff=152556"/>
		<updated>2023-12-05T03:43:40Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Staggered_controller.png&amp;diff=152555</id>
		<title>File:Staggered controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Staggered_controller.png&amp;diff=152555"/>
		<updated>2023-12-05T03:43:22Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Pair_programming_controller.png&amp;diff=152554</id>
		<title>File:Pair programming controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Pair_programming_controller.png&amp;diff=152554"/>
		<updated>2023-12-05T03:43:07Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Is_calibrated_controller.png&amp;diff=152553</id>
		<title>File:Is calibrated controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Is_calibrated_controller.png&amp;diff=152553"/>
		<updated>2023-12-05T03:42:53Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_topics_controller.png&amp;diff=152551</id>
		<title>File:Has topics controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_topics_controller.png&amp;diff=152551"/>
		<updated>2023-12-05T03:42:35Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_teams_controller.png&amp;diff=152550</id>
		<title>File:Has teams controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_teams_controller.png&amp;diff=152550"/>
		<updated>2023-12-05T03:42:10Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_badge_controller.png&amp;diff=152549</id>
		<title>File:Has badge controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_badge_controller.png&amp;diff=152549"/>
		<updated>2023-12-05T03:41:52Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Create_node_controller.png&amp;diff=152548</id>
		<title>File:Create node controller.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Create_node_controller.png&amp;diff=152548"/>
		<updated>2023-12-05T03:41:35Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152547</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152547"/>
		<updated>2023-12-05T03:40:56Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Controller==&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Badge==&lt;br /&gt;
Endpoint: GET /api/v1/assignments/{{assignment_id}}/has_badge&lt;br /&gt;
Description: Check if the assignment has a badge.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_badge field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has a badge, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Has_badge_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Pair Programming is Enabled==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{{assignment_id}}/pair_programming_enabled&lt;br /&gt;
Description: Check if pair programming is enabled for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the enable_pair_programming field in the assignment table.&lt;br /&gt;
Response Body: true if pair programming is enabled, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Topics==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{{assignment_id}}/has_topics&lt;br /&gt;
Description: Check if the assignment has topics.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the has_topics field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has topics, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Has_topics_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is a Team Assignment==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{{assignment_id}}/team_assignment&lt;br /&gt;
Description: Check if the assignment is a team assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value which is set based on max_team_size field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is a team assignment, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Team_assignment_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Valid Number of Reviews==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{{assignment_id}}/valid_num_review/{{review_type}}&lt;br /&gt;
Description: Check if the assignment has a valid number of reviews for a specific review type.&lt;br /&gt;
Input: ID of the assignment (Path Parameter) and Type of review (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the number of allowed reviews is greater than required rewievs for the specified review type.&lt;br /&gt;
Response Body: true if valid, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Valid_num_review_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Calibrated==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{{assignment_id}}/is_calibrated&lt;br /&gt;
Description: Check if the assignment is calibrated.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value of the is_calibrated field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment is calibrated, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Is_calibrated_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Teams==&lt;br /&gt;
EndpointGET api/v1/assignments/{{assignment_id}}/has_teams&lt;br /&gt;
Description: Check if the assignment has teams.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value of the has_teams field in the assignment table.&lt;br /&gt;
Response Body: true if the assignment has teams, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Has_teams_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment is Staggered and Has No Assigned Topic for Current User==&lt;br /&gt;
Endpoint: GET http://localhost/api/v1/assignments/{{assignment_id}}/staggered_and_no_topic&lt;br /&gt;
Description: Check if the assignment is staggered and has no assigned topic for the current user.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Boolean value indicating if the assignment is staggered and has no assigned topic.&lt;br /&gt;
Response Body: true if staggered and no topic assigned, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Staggered_and_no_topic_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Create Nodes for Assignment==&lt;br /&gt;
Endpoint: POST api/v1/assignments/{{assignment_id}}/create_node&lt;br /&gt;
Description: Create node for the assignment.&lt;br /&gt;
Input: ID of the assignment (Path Parameter)&lt;br /&gt;
Output: Returns the created node.&lt;br /&gt;
Response Body: JSON representation of the created node.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Create_node_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Check if Assignment Has Varying Rubrics Across Rounds==&lt;br /&gt;
Endpoint: GET api/v1/assignments/{{assignment_id}}/varying_rubrics_by_round&lt;br /&gt;
Description: Check if the assignment has varying rubrics across rounds.&lt;br /&gt;
Input: assignment_id (Path Parameter): ID of the assignment.&lt;br /&gt;
Output: Boolean value indicating if rubrics vary across rounds in the assignment.&lt;br /&gt;
Response Body: true if rubrics vary, false otherwise.&lt;br /&gt;
Method:&lt;br /&gt;
[[File:Varying_rubrics_by_round_controller.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
assignment.rb&lt;br /&gt;
asssignments_controller.rb&lt;br /&gt;
routes.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
20231129050431_create_sign_up_topics.rb&lt;br /&gt;
20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
20231130030500_create_signed_up_teams.rb&lt;br /&gt;
20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
20231130033226_create_teams_users.rb&lt;br /&gt;
20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We plan to use the given test skeletons for assignment model and implement the respective Rspec test cases. The test cases for other methods will be included later as reimplementation might have methods which are combined versions of multiple other methods. The test scenarios for some for the methods are mentioned in the following table.&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152537</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152537"/>
		<updated>2023-12-05T03:27:44Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Here are the methods that we reimplemented in the Assignment Model:&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication in order to follow DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. We also created migrations for adding the field used_in_round to the assignment questionnaire model to ensure the fulfilment of SOLID principles.   &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. We did this to ensure that the new method it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This is done so that the new code adheres to the Single Responsibility Principle by having each method focused on a single task and hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details because we had to follow the principles of SOLID programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and ensures that SOLID principles are followed by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. To verify the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is made more concise and straightforward to make it easy to understand and follow the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed to ensure that the code adheres to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
assignment.rb&lt;br /&gt;
asssignments_controller.rb&lt;br /&gt;
The following migration files were also added : &lt;br /&gt;
20231129021640_add_enable_pair_programming_to_assignment.rb&lt;br /&gt;
20231129023417_add_assignment_to_teams.rb&lt;br /&gt;
20231129024913_add_has_teams_to_assignments.rb&lt;br /&gt;
20231129050431_create_sign_up_topics.rb&lt;br /&gt;
20231129051018_add_has_topics_to_assignment.rb&lt;br /&gt;
20231130030500_create_signed_up_teams.rb&lt;br /&gt;
20231130030611_add_foreign_key_to_signed_up_teams_for_sign_up_topic.rb&lt;br /&gt;
20231130030646_add_foreign_key_to_signed_up_teams_for_team.rb&lt;br /&gt;
20231130033226_create_teams_users.rb&lt;br /&gt;
20231130033325_add_foreign_key_to_teams_users_for_user.rb&lt;br /&gt;
20231130033332_add_foreign_key_to_teams_users_for_team.rb&lt;br /&gt;
20231201012040_add_used_in_round_to_assignment_questionnaire.rb&lt;br /&gt;
20231201024204_create_nodes.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We plan to use the given test skeletons for assignment model and implement the respective Rspec test cases. The test cases for other methods will be included later as reimplementation might have methods which are combined versions of multiple other methods. The test scenarios for some for the methods are mentioned in the following table.&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152527</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152527"/>
		<updated>2023-12-05T03:12:17Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Methods Reimplemented&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication thus following DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
[[File:Valid_num_review.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. &lt;br /&gt;
We also created migrations for adding the field used_in_round to the assignment questionnaire model.  &lt;br /&gt;
&lt;br /&gt;
[[File:Varying_rubrics_by_round.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
&lt;br /&gt;
[[File:Has_badge.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. Hence it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Is_calibrated.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This adheres to the Single Responsibility Principle by having each method focused on a single task. Hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Num_reviews_greater.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview. There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details. Hence following the principles of object oriented programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and promotes SOLID principles by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. For verifying the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
[[File:Staggered_and_no_topic.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is concise and straightforward, making it easy to understand hence following the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Team_assignment.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is concise and straightforward, making it easy to understand hence following the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
[[File:Teams1.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is concise and straightforward, making it easy to understand hence following the SOLID principles. &lt;br /&gt;
&lt;br /&gt;
[[File:Topics.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed, adhering to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
[[File:Create_node.png ‎| 700px]]&lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
The following migration files were added : &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We plan to use the given test skeletons for assignment model and implement the respective Rspec test cases. The test cases for other methods will be included later as reimplementation might have methods which are combined versions of multiple other methods. The test scenarios for some for the methods are mentioned in the following table.&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Varying_rubrics_by_round.png&amp;diff=152509</id>
		<title>File:Varying rubrics by round.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Varying_rubrics_by_round.png&amp;diff=152509"/>
		<updated>2023-12-05T02:57:09Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Valid_reviews_allowed.png&amp;diff=152508</id>
		<title>File:Valid reviews allowed.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Valid_reviews_allowed.png&amp;diff=152508"/>
		<updated>2023-12-05T02:57:01Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Valid_num_review.png&amp;diff=152506</id>
		<title>File:Valid num review.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Valid_num_review.png&amp;diff=152506"/>
		<updated>2023-12-05T02:56:47Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Topics.png&amp;diff=152505</id>
		<title>File:Topics.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Topics.png&amp;diff=152505"/>
		<updated>2023-12-05T02:56:39Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Teams1.png&amp;diff=152503</id>
		<title>File:Teams1.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Teams1.png&amp;diff=152503"/>
		<updated>2023-12-05T02:56:26Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Team_assignment.png&amp;diff=152502</id>
		<title>File:Team assignment.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Team_assignment.png&amp;diff=152502"/>
		<updated>2023-12-05T02:56:02Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Staggered_and_no_topic.png&amp;diff=152501</id>
		<title>File:Staggered and no topic.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Staggered_and_no_topic.png&amp;diff=152501"/>
		<updated>2023-12-05T02:55:51Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Pair_programming.png&amp;diff=152500</id>
		<title>File:Pair programming.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Pair_programming.png&amp;diff=152500"/>
		<updated>2023-12-05T02:55:39Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Num_reviews_greater.png&amp;diff=152499</id>
		<title>File:Num reviews greater.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Num_reviews_greater.png&amp;diff=152499"/>
		<updated>2023-12-05T02:55:29Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: Bharcha uploaded a new version of File:Num reviews greater.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Num_reviews_greater.png&amp;diff=152498</id>
		<title>File:Num reviews greater.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Num_reviews_greater.png&amp;diff=152498"/>
		<updated>2023-12-05T02:55:12Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: Bharcha uploaded a new version of File:Num reviews greater.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Num_reviews_greater.png&amp;diff=152497</id>
		<title>File:Num reviews greater.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Num_reviews_greater.png&amp;diff=152497"/>
		<updated>2023-12-05T02:54:57Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Is_calibrated.png&amp;diff=152495</id>
		<title>File:Is calibrated.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Is_calibrated.png&amp;diff=152495"/>
		<updated>2023-12-05T02:54:48Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_badge.png&amp;diff=152493</id>
		<title>File:Has badge.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Has_badge.png&amp;diff=152493"/>
		<updated>2023-12-05T02:54:38Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Create_node.png&amp;diff=152492</id>
		<title>File:Create node.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Create_node.png&amp;diff=152492"/>
		<updated>2023-12-05T02:54:27Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152487</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=152487"/>
		<updated>2023-12-05T02:52:17Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Methods Reimplemented&lt;br /&gt;
&lt;br /&gt;
==valid_num_review==&lt;br /&gt;
The method checks if the number of reviews or metareviews required exceeds the allowed limit. This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method,  we have taken a new parameter - review_type which is the type of review and called the method only for the corresponding review type.&lt;br /&gt;
We also removed the incorrect assignment of num_reviews_allowed to num_reviews which actually represents number of reviews done by a student for an assignment. This did not make any sense and hence was removed.&lt;br /&gt;
The num_reviews_greater? method is called with different parameters based on the review_type, avoiding code duplication thus following DRY principles.&lt;br /&gt;
The reimplementation separates the concerns more explicitly. It checks for the validity of either regular reviews or metareviews based on the value of review_type.&lt;br /&gt;
&lt;br /&gt;
==varying_rubrics_by_round?== &lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It used to do it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method checks if we have more than one rubric of a given type for an assignment. &lt;br /&gt;
We also created migrations for adding the field used_in_round to the assignment questionnaire model.  &lt;br /&gt;
&lt;br /&gt;
==has_badge?==&lt;br /&gt;
This method returns the value of the has_badge instance variable and this was initially known as badge?. The code is easy to read and understand. It explicitly checks if has_badge is nil and returns false in that case, otherwise returning the value of has_badge. This contributes to code that is easy to reason about. The method encapsulates the logic for checking whether an object has a badge or not. This is a good practice as it hides the implementation details from the outside world and provides a clear and readable interface. &lt;br /&gt;
Files Modified&lt;br /&gt;
&lt;br /&gt;
==is_calibrated?==&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and was initially known as calibrated?. This is a concise, more appropriately named method and it encapsulates the logic for checking if an object is calibrated. Hence it is more dry and follows SOLID principles. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==current_stage(topic_id = nil)== &lt;br /&gt;
This method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==current_stage_name(topic_id = nil)== This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==stage_deadline(topic_id = nil)== &lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic object oriented and SOLID principles. &lt;br /&gt;
&lt;br /&gt;
==num_reviews_greater?(reviews_required, reviews_allowed)== &lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we checked if reviews_allowed is valid or not in a separate function. We used a separate function (valid_reviews_allowed?) allows for potential reusability of the validation logic in other parts of the codebase. The code snippet separates the concern of checking if reviews_allowed is valid into a dedicated method (valid_reviews_allowed?). This adheres to the Single Responsibility Principle by having each method focused on a single task. Hence this aligns with the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==quiz_allowed(topic_id = nil)== &lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. However, this method had to be removed from the reimplementation as it was better suited to be a part of due date model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==response_map_to_metareview(metareviewer)== &lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  However, this method had to be removed from the reimplementation as it was better suited to be a part of MetareviewResponseMap model where it can be combined with the reviewer_metareviews_map method that is basically a step of this method in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==review_questionnaire_id(round_number = nil, topic_id = nil)== &lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round. In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved. However, this method had to be removed from the reimplementation as it was better suited to be a part of the Questionnaire model in order to follow basic SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==reviewer_metareviews_map(response_map_set)== &lt;br /&gt;
This is a step in finding the response_map_to_metareview.  There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation and moved to the MetareviewResponseMap Model.&lt;br /&gt;
&lt;br /&gt;
==pair_programming_enabled?== &lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable. This method is concise and straightforward. It directly calls the enable_pair_programming method, avoiding unnecessary duplication of code. There's no redundant logic or unnecessary complexity. It provides a clean interface for querying the state without exposing the internal details. Hence following the principles of object oriented programming. We added the enabled_pair_programming field to the Assignment model through migrations.&lt;br /&gt;
&lt;br /&gt;
==staggered_and_no_topic?(topic_id)==&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic then it returns true otherwise it returns false. This method is concise and straightforward and promotes SOLID principles by avoiding unnecessary duplication of logical constructs and also adheres to Single responsibility principle. For verifying the functionality of this method we created teams_users model and created foreign key associations between teams_users and users and teams_users and team. We also created a signed_up_teams model and the corresponding foreign key associations with sign_up_topics and teams model.&lt;br /&gt;
&lt;br /&gt;
==team_assignment?==&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 1. It was initially checking is the max_team_size &amp;gt;0. It focuses on a single responsibility and follows the right naming convention. It is concise and straightforward, making it easy to understand hence following the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==teams?==&lt;br /&gt;
This method is used to check whether any team is associated with this assignment. For this, we added a has_teams field to the assignment model and a foreign key association between assignment and teams model with the help of migrations. It is concise and straightforward, making it easy to understand hence following the SOLID principles.&lt;br /&gt;
&lt;br /&gt;
==topics?==&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. It delegates the responsibility of determining the presence of topics to sign_up_topics. For this, we created a sign_up_topics model and has_topics field for assignment model. It is concise and straightforward, making it easy to understand hence following the SOLID principles. &lt;br /&gt;
&lt;br /&gt;
==create_node== &lt;br /&gt;
This method creates an AssignmentNode for this assignment. The method thas a single responsibility: creating an AssignmentNode and associating it with a parent (CourseNode). We added a nodes model and the subclasses CourseNode and Assignment Node. This aligns with the Single responsibility principle.It is readable and clear and the use of a conditional statement enhances readability by ensuring that the assignment node is associated with a parent only when a valid parent is found. It is well-designed, adhering to DRY principles by reusing logic and following SOLID principles, particularly the Single Responsibility Principle and encapsulation. &lt;br /&gt;
&lt;br /&gt;
==Files Modified/Added==&lt;br /&gt;
The following migration files were added : &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We plan to use the given test skeletons for assignment model and implement the respective Rspec test cases. The test cases for other methods will be included later as reimplementation might have methods which are combined versions of multiple other methods. The test scenarios for some for the methods are mentioned in the following table.&lt;br /&gt;
&lt;br /&gt;
==test_valid_num_review==&lt;br /&gt;
&lt;br /&gt;
The testcases are designed to validate the relationship between the required and allowed numbers of reviews or metareviews, depending on the specified review_type. The tests cover scenarios where review_type is either &amp;quot;review&amp;quot; or &amp;quot;metareview&amp;quot; and evaluate the method's behavior in two cases: when the required number is less than or equal to the allowed number (expected to return success), and when the required number is greater than the allowed number (expected to return an error message). &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#valid_num_review' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when review_type is &amp;quot;review&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_reviews_required is less than or equal to num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 2&lt;br /&gt;
        assignment.num_reviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_reviews_required is greater than num_reviews_allowed' do&lt;br /&gt;
        assignment.num_reviews_required = 5&lt;br /&gt;
        assignment.num_reviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('review')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of reviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when review_type is &amp;quot;metareview&amp;quot;' do&lt;br /&gt;
      it 'returns success: true if num_metareviews_required is less than or equal to num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 2&lt;br /&gt;
        assignment.num_metareviews_allowed = 5&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be true&lt;br /&gt;
        expect(result[:message]).to be_nil&lt;br /&gt;
      end&lt;br /&gt;
      it 'returns an error message if num_metareviews_required is greater than num_metareviews_allowed' do&lt;br /&gt;
        assignment.num_metareviews_required = 5&lt;br /&gt;
        assignment.num_metareviews_allowed = 2&lt;br /&gt;
        result = assignment.valid_num_review('metareview')&lt;br /&gt;
        expect(result[:success]).to be false&lt;br /&gt;
        expect(result[:message]).to eq('Number of metareviews required cannot be greater than number of reviews allowed')&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_is_calibrated?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when is_calibrated is true':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to true. The expectation is that calling is_calibrated? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
2. Context: 'when is_calibrated is false':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets is_calibrated to false. The expectation is that calling is_calibrated? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#is_calibrated?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when is_calibrated is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.is_calibrated = true&lt;br /&gt;
        expect(assignment.is_calibrated?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when is_calibrated is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.is_calibrated = false&lt;br /&gt;
        expect(assignment.is_calibrated?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_has_badge?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when has_badge is true':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to true. The expectation is that calling has_badge? on the assignment returns true.&lt;br /&gt;
2. Context: 'when has_badge is false':&lt;br /&gt;
The test creates an Assignment object. It sets has_badge to false. The expectation is that calling has_badge? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#has_badge?' do&lt;br /&gt;
    let(:assignment) { Assignment.new }&lt;br /&gt;
    context 'when has_badge is true' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.has_badge = true&lt;br /&gt;
        expect(assignment.has_badge?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when has_badge is false' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.has_badge = false&lt;br /&gt;
        expect(assignment.has_badge?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_pair_programming_enabled?==&lt;br /&gt;
The test is organized into two contexts:&lt;br /&gt;
1. Context: &amp;quot;when pair programming is enabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to enable pair programming (assignment.enable_pair_programming = true) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return true.&lt;br /&gt;
2. Context: &amp;quot;when pair programming is disabled&amp;quot;:&lt;br /&gt;
The test sets up an Assignment object using the create(:assignment) factory. It uses a before block to disable pair programming (assignment.enable_pair_programming = false) before each test in this context. The test asserts that when pair_programming_enabled? is called on the assignment, it should return false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;pair_programming_enabled?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when pair programming is enabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Enable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming = true&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when pair programming is disabled&amp;quot; do&lt;br /&gt;
      before do&lt;br /&gt;
        # Disable pair programming before each test in this context&lt;br /&gt;
        assignment.enable_pair_programming=false&lt;br /&gt;
        # You may need a method to disable pair programming if it's not the inverse of enable_pair_programming&lt;br /&gt;
      end&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        expect(assignment.pair_programming_enabled?).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_staggered_and_no_topic?(topic_id)==&lt;br /&gt;
The test covers various scenarios based on the combination of staggered deadlines and the presence of a topic_id. Here's a summary:&lt;br /&gt;
1. Context: &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where staggered deadlines are enabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return true.&lt;br /&gt;
2. Context: &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with a scenario where a topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
3. Context: &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot;:&lt;br /&gt;
The test sets up a scenario where staggered deadlines are disabled and no topic_id is provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
4. Context: &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot;:&lt;br /&gt;
Similar to the previous context, but with staggered deadlines disabled and a topic_id provided. The test expects the staggered_and_no_topic? method to return false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;staggered_and_no_topic?&amp;quot; do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns true&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(true)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is enabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(true)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is not provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(subject).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(nil)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when staggered deadline is disabled and topic_id is provided&amp;quot; do&lt;br /&gt;
      it &amp;quot;returns false&amp;quot; do&lt;br /&gt;
        allow(assignment).to receive(:staggered_deadline?).and_return(false)&lt;br /&gt;
        expect(assignment.staggered_and_no_topic?(&amp;quot;some_topic_id&amp;quot;)).to eq(false)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_teams?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It creates a team associated with the assignment using FactoryBot (create(:team, assignment: assignment)). The expectation is that calling teams? on the assignment returns true.&lt;br /&gt;
2. Context: 'when no teams are associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. The expectation is that calling teams? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
describe '#teams?' do&lt;br /&gt;
    let(:assignment) {create(:assignment)}&lt;br /&gt;
    context 'when teams are associated with the assignment' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Create a team associated with the assignment using FactoryBot&lt;br /&gt;
        team = create(:team, assignment: assignment)&lt;br /&gt;
        expect(assignment.teams?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no teams are associated with the assignment' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        expect(assignment.teams?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_topics?==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: 'when no topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets up a scenario where no topic is associated with the given assignment. The expectation is that calling topics? on the assignment returns false.&lt;br /&gt;
2. Context: 'when any topic is associated with the assignment':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.  It creates a sign_up_topic associated with the assignment using FactoryBot (create(:sign_up_topic, assignment: assignment)).. The expectation is that calling topics? on the assignment returns true.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#topics?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when sign_up_topics is empty' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming sign_up_topics is an empty collection&lt;br /&gt;
        expect(assignment.topics?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when sign_up_topics is not empty' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming sign_up_topics is a non-empty collection&lt;br /&gt;
        sign_up_topic = create(:sign_up_topic, assignment: assignment)&lt;br /&gt;
        expect(assignment.topics?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_create_node==&lt;br /&gt;
The test covers two scenarios:&lt;br /&gt;
1. Context: &amp;quot;when the parent node exists&amp;quot;:&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory.It stubs CourseNode.find_by to return a mock parent node. It sets up expectations for the creation of an AssignmentNode, including setting the parent_id and saving the new node. The test calls the create_node method.&lt;br /&gt;
2. Context: &amp;quot;when the parent node does not exist&amp;quot;: &lt;br /&gt;
Similar to the previous context, but it stubs CourseNode.find_by to return nil (indicating no parent node). It sets up expectations for the creation of an AssignmentNode, excluding the setting of parent_id (since there is no parent), and saving the new node. The test calls the create_node method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe &amp;quot;#create_node&amp;quot; do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context &amp;quot;when the parent node exists&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, sets parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return a mock parent node&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(double(&amp;quot;CourseNode&amp;quot;, id: 10))&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context &amp;quot;when the parent node does not exist&amp;quot; do&lt;br /&gt;
      it &amp;quot;creates a new assignment node with the given id, does not set parent_id, and saves the new node&amp;quot; do&lt;br /&gt;
        # Stub CourseNode.find_by to return nil (no parent node)&lt;br /&gt;
        allow(CourseNode).to receive(:find_by).and_return(nil)&lt;br /&gt;
        # Expectations for AssignmentNode creation&lt;br /&gt;
        expect(AssignmentNode).to receive(:create).with(node_object_id: assignment.id).and_call_original&lt;br /&gt;
        # Expectations for any_instance of AssignmentNode&lt;br /&gt;
        assignment_node_instance = instance_double(AssignmentNode)&lt;br /&gt;
        expect(assignment_node_instance).not_to receive(:parent_id=)&lt;br /&gt;
        allow(assignment_node_instance).to receive(:save)&lt;br /&gt;
        expect(AssignmentNode).to receive(:new).and_return(assignment_node_instance)&lt;br /&gt;
        # Call the method under test&lt;br /&gt;
        assignment.create_node&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
==test_varying_rubrics_by_round?==&lt;br /&gt;
The test is divided into two contexts:&lt;br /&gt;
1. Context 'when rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment and a Questionnaire. It then creates an AssignmentQuestionnaire associating the assignment with the questionnaire and specifying that it's used in round 1. The test expects the varying_rubrics_by_round? method to return true, indicating that rubrics with specified rounds are present for the assignment.&lt;br /&gt;
2. Context 'when no rubrics with specified rounds are present':&lt;br /&gt;
The test creates an Assignment. It expects the varying_rubrics_by_round? method to return false when no rubrics with specified rounds are associated with the assignment.&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe '#varying_rubrics_by_round?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    let(:questionnaire) {create(:questionnaire)}&lt;br /&gt;
    context 'when rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        # Assuming rubrics with specified rounds exist for the assignment&lt;br /&gt;
        create(:assignment_questionnaire, assignment: assignment, questionnaire: questionnaire, used_in_round: 1)&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when no rubrics with specified rounds are present' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        # Assuming no rubrics with specified rounds exist for the assignment&lt;br /&gt;
        expect(assignment.varying_rubrics_by_round?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==test_ team_assignment?==&lt;br /&gt;
The test covers three scenarios:&lt;br /&gt;
1. Context: 'when max_team_size is greater than 0':&lt;br /&gt;
The test creates an Assignment object using the create(:assignment) factory. It sets the max_team_size attribute to a value greater than 0. The test expects that calling team_assignment? on the assignment returns true.&lt;br /&gt;
2. Context: 'when max_team_size is equal to 0':&lt;br /&gt;
Similar to the previous context, but it sets max_team_size to 0. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
3. Context: 'when max_team_size is less than 0':&lt;br /&gt;
Similar to the previous contexts, but it sets max_team_size to a negative value. The test expects that calling team_assignment? on the assignment returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
  describe 'team_assignment?' do&lt;br /&gt;
    let(:assignment) { create(:assignment) }&lt;br /&gt;
    context 'when max_team_size is greater than 0' do&lt;br /&gt;
      it 'returns true' do&lt;br /&gt;
        assignment.max_team_size = 5&lt;br /&gt;
        expect(assignment.team_assignment?).to be true&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is equal to 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = 0&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when max_team_size is less than 0' do&lt;br /&gt;
      it 'returns false' do&lt;br /&gt;
        assignment.max_team_size = -3&lt;br /&gt;
        expect(assignment.team_assignment?).to be false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151626</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151626"/>
		<updated>2023-11-16T02:42:34Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
This project is a reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation Plan==&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that will be re-implemented and implemented as it is:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method, type of review will be a parameter.&lt;br /&gt;
* &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It does it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method will check if we have more than one rubric of a given type for an assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the has_badge instance variable and this should be renamed to has_badge?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and should be renamed is_calibrated?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage&amp;lt;/strong&amp;gt;&lt;br /&gt;
his method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing, though a bit informal.  However, since this method is quite similar to two other methods - current_stage_name and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage_name&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic.  However, since this method is quite similar to two other methods - current_stage and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;stage_deadline&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, since this method is quite similar to two other methods - current_stage_name and current_stage, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;num_reviews_greater?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we will check if reviews_allowed is valid or not in a separate function.&lt;br /&gt;
* &amp;lt;strong&amp;gt;quiz_allowed&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. This method will be reimplemented without making a direct call to the check_condition.&lt;br /&gt;
* &amp;lt;strong&amp;gt;response_map_to_metareview&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  This can be made as a class method of MetareviewResponseMap and combined with the reviewer_metareviews_map method that is basically a step of this method.&lt;br /&gt;
* &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round(...). In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved.  &lt;br /&gt;
* &amp;lt;strong&amp;gt;reviewer_metareviews_map&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a step in finding the response_map_to_metareview.  There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Note : &amp;lt;/strong&amp;gt;The following methods do not require specific changes and will be implemented accordingly.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment. &lt;br /&gt;
* &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable.  &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic. &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 0 (should be &amp;gt; 1). &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;teams?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any teams exist for this assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;topics?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any topics exist for this assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment.&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/config/routes.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/models/assignment_spec.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/factories/factories.rb&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We plan to use the given test skeletons for assignment model and implement the respective Rspec test cases. The test cases for other methods will be included later as reimplementation might have methods which are combined versions of multiple other methods. The test scenarios for some for the methods are mentioned in the following table.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 1.1 || Scenario 1: Max_team_size is greater than 0. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 1.2 || Scenario 2: Max_team_size is equal to 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 1.3 || Scenario 3: Max_team_size is less than 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2 || &amp;lt;strong&amp;gt;topics&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 2.1 || Scenario 1: Sign_up_topics is empty. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2.2 || Scenario 2: Sign_up_topics is not empty. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3 || &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 3.1 || Scenario 1: The object is calibrated. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3.2 || Scenario 2: The object is not calibrated. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 4 || &amp;lt;strong&amp;gt;teams&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4.1 || Scenario 1: Teams are present. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 4.2 || Scenario 2: Teams are not present. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 5 || &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 5.1 || Scenario 1: Number of reviews required is greater than the number of reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 5.2 || Scenario 2: Number of meta-reviews required is greater than the number of meta-reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 6 || &amp;lt;strong&amp;gt;dynamic_reviewer_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 6.1 || Scenario 1: Review assignment strategy is RS_AUTO_SELECTED. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 6.2 || Scenario 2: Review assignment strategy is not RS_AUTO_SELECTED. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7 || &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 7.1 || Scenario 1: Has_badge is nil. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7.2 || Scenario 2: Has_badge is true. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 7.3 || Scenario 3: Has_badge is false. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 8 || &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 8.1 || Scenario 1: Parent node exists. Expected: New node created with parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 8.2 || Scenario 2: Parent node does not exist. Expected: New node created with no parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 9.1 || Scenario 1: Rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.2 || Scenario 2: Multiple rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.3 || Scenario 3: No rubrics of a given type exist in round 2. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &amp;lt;strong&amp;gt;num_review_rounds&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 10.1 || Scenario 1: No due dates. Expected: 0&lt;br /&gt;
|-&lt;br /&gt;
| 10.2 || Scenario 2: Single due date with round 1. Expected: 1&lt;br /&gt;
|-&lt;br /&gt;
| 10.3 || Scenario 3: Multiple due dates with different rounds. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 10.4 || Scenario 4: Multiple due dates with the same round number. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 11 || &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 11.1 || Scenario 1: No round_number and topic_id provided. Expected: id of the current round's review questionnaire.&lt;br /&gt;
|-&lt;br /&gt;
| 11.2 || Scenario 2: No round_number and topic_id provided, no next due date. Expected: nil&lt;br /&gt;
|-&lt;br /&gt;
| 12 || &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 12.1 || Scenario 1: Pair programming is enabled. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 12.2 || Scenario 2: Pair programming is disabled. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 13 || &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 13.1 || Scenario 1: Staggered deadline is enabled, topic_id not provided. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 13.2 || Scenario 2: Staggered deadline is enabled, topic_id provided. Expected: false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151624</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151624"/>
		<updated>2023-11-16T02:42:19Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
A reimplementation for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation Plan==&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that will be re-implemented and implemented as it is:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method, type of review will be a parameter.&lt;br /&gt;
* &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It does it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method will check if we have more than one rubric of a given type for an assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the has_badge instance variable and this should be renamed to has_badge?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and should be renamed is_calibrated?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage&amp;lt;/strong&amp;gt;&lt;br /&gt;
his method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing, though a bit informal.  However, since this method is quite similar to two other methods - current_stage_name and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage_name&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic.  However, since this method is quite similar to two other methods - current_stage and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;stage_deadline&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, since this method is quite similar to two other methods - current_stage_name and current_stage, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;num_reviews_greater?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we will check if reviews_allowed is valid or not in a separate function.&lt;br /&gt;
* &amp;lt;strong&amp;gt;quiz_allowed&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. This method will be reimplemented without making a direct call to the check_condition.&lt;br /&gt;
* &amp;lt;strong&amp;gt;response_map_to_metareview&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  This can be made as a class method of MetareviewResponseMap and combined with the reviewer_metareviews_map method that is basically a step of this method.&lt;br /&gt;
* &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round(...). In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved.  &lt;br /&gt;
* &amp;lt;strong&amp;gt;reviewer_metareviews_map&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a step in finding the response_map_to_metareview.  There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Note : &amp;lt;/strong&amp;gt;The following methods do not require specific changes and will be implemented accordingly.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment. &lt;br /&gt;
* &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable.  &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic. &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 0 (should be &amp;gt; 1). &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;teams?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any teams exist for this assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;topics?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any topics exist for this assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment.&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/config/routes.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/models/assignment_spec.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/factories/factories.rb&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We plan to use the given test skeletons for assignment model and implement the respective Rspec test cases. The test cases for other methods will be included later as reimplementation might have methods which are combined versions of multiple other methods. The test scenarios for some for the methods are mentioned in the following table.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 1.1 || Scenario 1: Max_team_size is greater than 0. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 1.2 || Scenario 2: Max_team_size is equal to 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 1.3 || Scenario 3: Max_team_size is less than 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2 || &amp;lt;strong&amp;gt;topics&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 2.1 || Scenario 1: Sign_up_topics is empty. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2.2 || Scenario 2: Sign_up_topics is not empty. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3 || &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 3.1 || Scenario 1: The object is calibrated. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3.2 || Scenario 2: The object is not calibrated. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 4 || &amp;lt;strong&amp;gt;teams&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4.1 || Scenario 1: Teams are present. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 4.2 || Scenario 2: Teams are not present. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 5 || &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 5.1 || Scenario 1: Number of reviews required is greater than the number of reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 5.2 || Scenario 2: Number of meta-reviews required is greater than the number of meta-reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 6 || &amp;lt;strong&amp;gt;dynamic_reviewer_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 6.1 || Scenario 1: Review assignment strategy is RS_AUTO_SELECTED. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 6.2 || Scenario 2: Review assignment strategy is not RS_AUTO_SELECTED. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7 || &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 7.1 || Scenario 1: Has_badge is nil. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7.2 || Scenario 2: Has_badge is true. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 7.3 || Scenario 3: Has_badge is false. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 8 || &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 8.1 || Scenario 1: Parent node exists. Expected: New node created with parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 8.2 || Scenario 2: Parent node does not exist. Expected: New node created with no parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 9.1 || Scenario 1: Rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.2 || Scenario 2: Multiple rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.3 || Scenario 3: No rubrics of a given type exist in round 2. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &amp;lt;strong&amp;gt;num_review_rounds&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 10.1 || Scenario 1: No due dates. Expected: 0&lt;br /&gt;
|-&lt;br /&gt;
| 10.2 || Scenario 2: Single due date with round 1. Expected: 1&lt;br /&gt;
|-&lt;br /&gt;
| 10.3 || Scenario 3: Multiple due dates with different rounds. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 10.4 || Scenario 4: Multiple due dates with the same round number. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 11 || &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 11.1 || Scenario 1: No round_number and topic_id provided. Expected: id of the current round's review questionnaire.&lt;br /&gt;
|-&lt;br /&gt;
| 11.2 || Scenario 2: No round_number and topic_id provided, no next due date. Expected: nil&lt;br /&gt;
|-&lt;br /&gt;
| 12 || &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 12.1 || Scenario 1: Pair programming is enabled. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 12.2 || Scenario 2: Pair programming is disabled. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 13 || &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 13.1 || Scenario 1: Staggered deadline is enabled, topic_id not provided. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 13.2 || Scenario 2: Staggered deadline is enabled, topic_id provided. Expected: false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151621</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151621"/>
		<updated>2023-11-16T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
==Introduction==&lt;br /&gt;
A reimplementation is required for the assignment model and assignment controller in the Expertiza backend. &lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
The following tasks were required for the reimplementation :&lt;br /&gt;
#&amp;lt;b&amp;gt;Enhancing Code Clarity:&amp;lt;/b&amp;gt; This involves renaming methods with ambiguous names, optimizing loops and adding comments for unclear lines of code.&lt;br /&gt;
#&amp;lt;b&amp;gt;Removing unused methods&amp;lt;/b&amp;gt; Removing unused methods will reduce complexity.&lt;br /&gt;
#&amp;lt;b&amp;gt;Reimplement Assignment model and controller:&amp;lt;/b&amp;gt; Reimplement the methods from Assignment model that are complex and can be implemented in a better way to reduce complexity and by not violating the DRY principles.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for assignment models:&amp;lt;/b&amp;gt; Tests have to be written for Assignment Model.&lt;br /&gt;
#&amp;lt;b&amp;gt;Writing tests for the assignment controller:&amp;lt;/b&amp;gt; RSwag tests should be written for Assignment Controller&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
While reimplementation of Assignment model and controller, the following design rules have to be ensured:&lt;br /&gt;
* Validate proper functioning of all existing and anticipated methods, making any required enhancements or adjustments.&lt;br /&gt;
* Establish loose coupling and tight cohesion for the model and controller to enhance code organization and maintainability.&lt;br /&gt;
* Refactor redundant code in the previous implementation's controller and model methods using DRY principle, eliminating functionality duplications already present in the expertiza system.&lt;br /&gt;
* Confirm the continued effectiveness of existing test cases following the aforementioned modifications and generate additional test cases as per the need.&lt;br /&gt;
&lt;br /&gt;
==Implementation Plan==&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that will be re-implemented and implemented as it is:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method, type of review will be a parameter.&lt;br /&gt;
* &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It does it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method will check if we have more than one rubric of a given type for an assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the has_badge instance variable and this should be renamed to has_badge?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and should be renamed is_calibrated?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage&amp;lt;/strong&amp;gt;&lt;br /&gt;
his method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing, though a bit informal.  However, since this method is quite similar to two other methods - current_stage_name and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage_name&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic.  However, since this method is quite similar to two other methods - current_stage and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;stage_deadline&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, since this method is quite similar to two other methods - current_stage_name and current_stage, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;num_reviews_greater?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we will check if reviews_allowed is valid or not in a separate function.&lt;br /&gt;
* &amp;lt;strong&amp;gt;quiz_allowed&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. This method will be reimplemented without making a direct call to the check_condition.&lt;br /&gt;
* &amp;lt;strong&amp;gt;response_map_to_metareview&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  This can be made as a class method of MetareviewResponseMap and combined with the reviewer_metareviews_map method that is basically a step of this method.&lt;br /&gt;
* &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round(...). In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved.  &lt;br /&gt;
* &amp;lt;strong&amp;gt;reviewer_metareviews_map&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a step in finding the response_map_to_metareview.  There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Note : &amp;lt;/strong&amp;gt;The following methods do not require specific changes and will be implemented accordingly.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment. &lt;br /&gt;
* &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable.  &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic. &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 0 (should be &amp;gt; 1). &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;teams?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any teams exist for this assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;topics?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any topics exist for this assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment.&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/config/routes.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/models/assignment_spec.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/factories/factories.rb&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We plan to use the given test skeletons for assignment model and implement the respective Rspec test cases. The test cases for other methods will be included later as reimplementation might have methods which are combined versions of multiple other methods. The test scenarios for some for the methods are mentioned in the following table.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 1.1 || Scenario 1: Max_team_size is greater than 0. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 1.2 || Scenario 2: Max_team_size is equal to 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 1.3 || Scenario 3: Max_team_size is less than 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2 || &amp;lt;strong&amp;gt;topics&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 2.1 || Scenario 1: Sign_up_topics is empty. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2.2 || Scenario 2: Sign_up_topics is not empty. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3 || &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 3.1 || Scenario 1: The object is calibrated. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3.2 || Scenario 2: The object is not calibrated. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 4 || &amp;lt;strong&amp;gt;teams&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4.1 || Scenario 1: Teams are present. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 4.2 || Scenario 2: Teams are not present. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 5 || &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 5.1 || Scenario 1: Number of reviews required is greater than the number of reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 5.2 || Scenario 2: Number of meta-reviews required is greater than the number of meta-reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 6 || &amp;lt;strong&amp;gt;dynamic_reviewer_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 6.1 || Scenario 1: Review assignment strategy is RS_AUTO_SELECTED. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 6.2 || Scenario 2: Review assignment strategy is not RS_AUTO_SELECTED. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7 || &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 7.1 || Scenario 1: Has_badge is nil. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7.2 || Scenario 2: Has_badge is true. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 7.3 || Scenario 3: Has_badge is false. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 8 || &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 8.1 || Scenario 1: Parent node exists. Expected: New node created with parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 8.2 || Scenario 2: Parent node does not exist. Expected: New node created with no parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 9.1 || Scenario 1: Rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.2 || Scenario 2: Multiple rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.3 || Scenario 3: No rubrics of a given type exist in round 2. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 10 || &amp;lt;strong&amp;gt;num_review_rounds&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 10.1 || Scenario 1: No due dates. Expected: 0&lt;br /&gt;
|-&lt;br /&gt;
| 10.2 || Scenario 2: Single due date with round 1. Expected: 1&lt;br /&gt;
|-&lt;br /&gt;
| 10.3 || Scenario 3: Multiple due dates with different rounds. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 10.4 || Scenario 4: Multiple due dates with the same round number. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 11 || &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 11.1 || Scenario 1: No round_number and topic_id provided. Expected: id of the current round's review questionnaire.&lt;br /&gt;
|-&lt;br /&gt;
| 11.2 || Scenario 2: No round_number and topic_id provided, no next due date. Expected: nil&lt;br /&gt;
|-&lt;br /&gt;
| 12 || &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 12.1 || Scenario 1: Pair programming is enabled. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 12.2 || Scenario 2: Pair programming is disabled. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 13 || &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 13.1 || Scenario 1: Staggered deadline is enabled, topic_id not provided. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 13.2 || Scenario 2: Staggered deadline is enabled, topic_id provided. Expected: false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151593</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151593"/>
		<updated>2023-11-16T02:26:17Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
A reimplementation was required for assignment model and assignment controller. The following tasks were required for the reimplementation : &lt;br /&gt;
#Creating necessary associations between assignment model and other models such as course, participants, instructor.&lt;br /&gt;
#Reimplementation for the following methods in assignment model and necessary controller actions and routes : &lt;br /&gt;
#* &amp;lt;strong&amp;gt; add_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to add a participant to an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to remove a participant from an assignment.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; assign_courses_to_assignment &amp;lt;/strong&amp;gt; : Associates the assignments with a given course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_assignment_from_course&amp;lt;/strong&amp;gt; : Dissociates an assignment from a course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; copy_assignment &amp;lt;/strong&amp;gt; : Creates a copy of an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; delete &amp;lt;/strong&amp;gt; : CRUD operation for deleting the assignment and necessary dependencies. &lt;br /&gt;
#* Writing rspec and rswag test case for assignment model and controller respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Implementation Plan==&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that will be re-implemented and implemented as it is:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method, type of review will be a parameter.&lt;br /&gt;
* &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It does it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method will check if we have more than one rubric of a given type for an assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the has_badge instance variable and this should be renamed to has_badge?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and should be renamed is_calibrated?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage&amp;lt;/strong&amp;gt;&lt;br /&gt;
his method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing, though a bit informal.  However, since this method is quite similar to two other methods - current_stage_name and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage_name&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic.  However, since this method is quite similar to two other methods - current_stage and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;stage_deadline&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, since this method is quite similar to two other methods - current_stage_name and current_stage, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;num_reviews_greater?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we will check if reviews_allowed is valid or not in a separate function.&lt;br /&gt;
* &amp;lt;strong&amp;gt;quiz_allowed&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. This method will be reimplemented without making a direct call to the check_condition.&lt;br /&gt;
* &amp;lt;strong&amp;gt;response_map_to_metareview&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  This can be made as a class method of MetareviewResponseMap and combined with the reviewer_metareviews_map method that is basically a step of this method.&lt;br /&gt;
* &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round(...). In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved.  &lt;br /&gt;
* &amp;lt;strong&amp;gt;reviewer_metareviews_map&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a step in finding the response_map_to_metareview.  There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation.&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment. This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable.  This is a reasonable accessor method, and it does not need to change.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic. This method is working fine and does not need to change.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 0 (should be &amp;gt; 1).  This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;teams?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any teams exist for this assignment. This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;topics?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment. This is working fine and does not need to change.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt; Controller - Assignment_Controller.rb &amp;lt;/strong&amp;gt;&lt;br /&gt;
For the new methods added in the assignment model, we added corresponding actions in the assignment controller with the same name and routes in config.rb as mentioned in above documentation. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/config/routes.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/models/assignment_spec.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/factories/factories.rb&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
==Test Plan==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || **team_assignment?**&lt;br /&gt;
|-&lt;br /&gt;
| 1.1 || Scenario 1: Max_team_size is greater than 0. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 1.2 || Scenario 2: Max_team_size is equal to 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 1.3 || Scenario 3: Max_team_size is less than 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2 || **topics**&lt;br /&gt;
|-&lt;br /&gt;
| 2.1 || Scenario 1: Sign_up_topics is empty. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2.2 || Scenario 2: Sign_up_topics is not empty. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3 || **calibrated?**&lt;br /&gt;
|-&lt;br /&gt;
| 3.1 || Scenario 1: The object is calibrated. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3.2 || Scenario 2: The object is not calibrated. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 4 || **teams**&lt;br /&gt;
|-&lt;br /&gt;
| 4.1 || Scenario 1: Teams are present. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 4.2 || Scenario 2: Teams are not present. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 5 || **valid_num_review**&lt;br /&gt;
|-&lt;br /&gt;
| 5.1 || Scenario 1: Number of reviews required is greater than the number of reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 5.2 || Scenario 2: Number of meta-reviews required is greater than the number of meta-reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 6 || **dynamic_reviewer_assignment?**&lt;br /&gt;
|-&lt;br /&gt;
| 6.1 || Scenario 1: Review assignment strategy is RS_AUTO_SELECTED. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 6.2 || Scenario 2: Review assignment strategy is not RS_AUTO_SELECTED. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7 || **badge?**&lt;br /&gt;
|-&lt;br /&gt;
| 7.1 || Scenario 1: Has_badge is nil. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7.2 || Scenario 2: Has_badge is true. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 7.3 || Scenario 3: Has_badge is false. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 8 || **create_node**&lt;br /&gt;
|-&lt;br /&gt;
| 8.1 || Scenario 1: Parent node exists. Expected: New node created with parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 8.2 || Scenario 2: Parent node does not exist. Expected: New node created with no parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || **varying_rubrics_by_round?**&lt;br /&gt;
|-&lt;br /&gt;
| 9.1 || Scenario 1: Rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.2 || Scenario 2: Multiple rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.3 || Scenario 3: No rubrics of a given type exist in round 2. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 10 || **num_review_rounds**&lt;br /&gt;
|-&lt;br /&gt;
| 10.1 || Scenario 1: No due dates. Expected: 0&lt;br /&gt;
|-&lt;br /&gt;
| 10.2 || Scenario 2: Single due date with round 1. Expected: 1&lt;br /&gt;
|-&lt;br /&gt;
| 10.3 || Scenario 3: Multiple due dates with different rounds. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 10.4 || Scenario 4: Multiple due dates with the same round number. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 11 || **review_questionnaire_id**&lt;br /&gt;
|-&lt;br /&gt;
| 11.1 || Scenario 1: No round_number and topic_id provided. Expected: id of the current round's review questionnaire.&lt;br /&gt;
|-&lt;br /&gt;
| 11.2 || Scenario 2: No round_number and topic_id provided, no next due date. Expected: nil&lt;br /&gt;
|-&lt;br /&gt;
| ... || (continue for other scenarios)&lt;br /&gt;
|-&lt;br /&gt;
| 12 || **pair_programming_enabled?**&lt;br /&gt;
|-&lt;br /&gt;
| 12.1 || Scenario 1: Pair programming is enabled. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 12.2 || Scenario 2: Pair programming is disabled. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 13 || **staggered_and_no_topic?**&lt;br /&gt;
|-&lt;br /&gt;
| 13.1 || Scenario 1: Staggered deadline is enabled, topic_id not provided. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 13.2 || Scenario 2: Staggered deadline is enabled, topic_id provided. Expected: false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151589</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller_(Phase_2)&amp;diff=151589"/>
		<updated>2023-11-16T02:24:54Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
A reimplementation was required for assignment model and assignment controller. The following tasks were required for the reimplementation : &lt;br /&gt;
#Creating necessary associations between assignment model and other models such as course, participants, instructor.&lt;br /&gt;
#Reimplementation for the following methods in assignment model and necessary controller actions and routes : &lt;br /&gt;
#* &amp;lt;strong&amp;gt; add_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to add a participant to an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to remove a participant from an assignment.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; assign_courses_to_assignment &amp;lt;/strong&amp;gt; : Associates the assignments with a given course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_assignment_from_course&amp;lt;/strong&amp;gt; : Dissociates an assignment from a course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; copy_assignment &amp;lt;/strong&amp;gt; : Creates a copy of an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; delete &amp;lt;/strong&amp;gt; : CRUD operation for deleting the assignment and necessary dependencies. &lt;br /&gt;
#* Writing rspec and rswag test case for assignment model and controller respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tasks==&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that will be re-implemented and implemented as it is:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;valid_num_review&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method raises an error if more reviews are required than are allowed. But it is a single method for both reviews and meta reviews. In the reimplemented method, type of review will be a parameter.&lt;br /&gt;
* &amp;lt;strong&amp;gt;varying_rubrics_by_round?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether different rubrics are being used in different rounds of review.  It does it, however, by checking whether more than one rubric is listed as being used in Round 2 (used_in_round = 2). The reimplemented method will check if we have more than one rubric of a given type for an assignment.&lt;br /&gt;
* &amp;lt;strong&amp;gt;badge?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the has_badge instance variable and this should be renamed to has_badge?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;calibrated?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the is_calibrated instance variable and should be renamed is_calibrated?.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage&amp;lt;/strong&amp;gt;&lt;br /&gt;
his method returns the current stage (Submission, Review, Finished, etc.) potentially based on which topic the logged-in user holds.  It returns a string, which is useful for printing, though a bit informal.  However, since this method is quite similar to two other methods - current_stage_name and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;current_stage_name&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a convoluted method that returns the same thing as current_stage, except in a few specialized cases, such as when the assignment has topics and the user hasn’t chosen a topic.  However, since this method is quite similar to two other methods - current_stage and stage_deadline, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;stage_deadline&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is similar to current_stage, but returns the time of the next deadline unless the assignment is finished. However, since this method is quite similar to two other methods - current_stage_name and current_stage, these three can be combined with some modifications in the reimplementation for clarity. For these, we will create a duedate model and implement the get_next_due_date method 2 subclasses- TopicDueDate and AssignmentDueDate.&lt;br /&gt;
* &amp;lt;strong&amp;gt;num_reviews_greater?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether the number of reviews required is greater than the number of reviews allowed.  Basically, it just compares two instance variables of Assignment,but handles the special cases of reviews_allowed being null or negative. In the reimplemented method, we will check if reviews_allowed is valid or not in a separate function.&lt;br /&gt;
* &amp;lt;strong&amp;gt;quiz_allowed&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the quiz_allowed_id field of the next due date, i.e., whether a participant is currently allowed to take a quiz. This method will be reimplemented without making a direct call to the check_condition.&lt;br /&gt;
* &amp;lt;strong&amp;gt;response_map_to_metareview&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the “most appropriate” ResponseMap to use as the reviewed_object in a new MetareviewResponseMap.  This can be made as a class method of MetareviewResponseMap and combined with the reviewer_metareviews_map method that is basically a step of this method.&lt;br /&gt;
* &amp;lt;strong&amp;gt;review_questionnaire_id&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method finds the questionnaire in use for reviews of work submitted for the assignment. This is a complicated method because it calculates to find the round number, instead of using number_of_current_round(...). In the reimplementation, instead of creating a new form, we can use an already existing form that is associated with the assignment. The logic behind determining a round number based on the topic can also be improved.  &lt;br /&gt;
* &amp;lt;strong&amp;gt;reviewer_metareviews_map&amp;lt;/strong&amp;gt;&lt;br /&gt;
This is a step in finding the response_map_to_metareview.  There is no need for a separate method for finding reviewer_metareviews_map. This method can be combined with response_map_to_metareview during reimplementation.&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment. This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;pair_programming_enabled?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method returns the value of the enable_pair_programming instance variable.  This is a reasonable accessor method, and it does not need to change.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;staggered_and_no_topic?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks if the assignment is a staggered-deadline assignment and the logged-in user has not chosen a topic. This method is working fine and does not need to change.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;team_assignment?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method checks whether max_team_size &amp;gt; 0 (should be &amp;gt; 1).  This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;teams?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any teams exist for this assignment. This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;topics?&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method is used to check whether any topics exist for this assignment. This is working fine and does not need to change.&lt;br /&gt;
* &amp;lt;strong&amp;gt;create_node&amp;lt;/strong&amp;gt;&lt;br /&gt;
This method creates an AssignmentNode for this assignment. This is working fine and does not need to change.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt; Controller - Assignment_Controller.rb &amp;lt;/strong&amp;gt;&lt;br /&gt;
For the new methods added in the assignment model, we added corresponding actions in the assignment controller with the same name and routes in config.rb as mentioned in above documentation. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/config/routes.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/models/assignment_spec.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/factories/factories.rb&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
==Test Plan==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || **team_assignment?**&lt;br /&gt;
|-&lt;br /&gt;
| 1.1 || Scenario 1: Max_team_size is greater than 0. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 1.2 || Scenario 2: Max_team_size is equal to 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 1.3 || Scenario 3: Max_team_size is less than 0. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2 || **topics**&lt;br /&gt;
|-&lt;br /&gt;
| 2.1 || Scenario 1: Sign_up_topics is empty. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 2.2 || Scenario 2: Sign_up_topics is not empty. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3 || **calibrated?**&lt;br /&gt;
|-&lt;br /&gt;
| 3.1 || Scenario 1: The object is calibrated. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 3.2 || Scenario 2: The object is not calibrated. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 4 || **teams**&lt;br /&gt;
|-&lt;br /&gt;
| 4.1 || Scenario 1: Teams are present. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 4.2 || Scenario 2: Teams are not present. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 5 || **valid_num_review**&lt;br /&gt;
|-&lt;br /&gt;
| 5.1 || Scenario 1: Number of reviews required is greater than the number of reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 5.2 || Scenario 2: Number of meta-reviews required is greater than the number of meta-reviews allowed. Expected: Error message&lt;br /&gt;
|-&lt;br /&gt;
| 6 || **dynamic_reviewer_assignment?**&lt;br /&gt;
|-&lt;br /&gt;
| 6.1 || Scenario 1: Review assignment strategy is RS_AUTO_SELECTED. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 6.2 || Scenario 2: Review assignment strategy is not RS_AUTO_SELECTED. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7 || **badge?**&lt;br /&gt;
|-&lt;br /&gt;
| 7.1 || Scenario 1: Has_badge is nil. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 7.2 || Scenario 2: Has_badge is true. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 7.3 || Scenario 3: Has_badge is false. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 8 || **create_node**&lt;br /&gt;
|-&lt;br /&gt;
| 8.1 || Scenario 1: Parent node exists. Expected: New node created with parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 8.2 || Scenario 2: Parent node does not exist. Expected: New node created with no parent_id set.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || **varying_rubrics_by_round?**&lt;br /&gt;
|-&lt;br /&gt;
| 9.1 || Scenario 1: Rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.2 || Scenario 2: Multiple rubrics of a given type exist in round 2. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 9.3 || Scenario 3: No rubrics of a given type exist in round 2. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 10 || **num_review_rounds**&lt;br /&gt;
|-&lt;br /&gt;
| 10.1 || Scenario 1: No due dates. Expected: 0&lt;br /&gt;
|-&lt;br /&gt;
| 10.2 || Scenario 2: Single due date with round 1. Expected: 1&lt;br /&gt;
|-&lt;br /&gt;
| 10.3 || Scenario 3: Multiple due dates with different rounds. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 10.4 || Scenario 4: Multiple due dates with the same round number. Expected: Highest round number&lt;br /&gt;
|-&lt;br /&gt;
| 11 || **review_questionnaire_id**&lt;br /&gt;
|-&lt;br /&gt;
| 11.1 || Scenario 1: No round_number and topic_id provided. Expected: id of the current round's review questionnaire.&lt;br /&gt;
|-&lt;br /&gt;
| 11.2 || Scenario 2: No round_number and topic_id provided, no next due date. Expected: nil&lt;br /&gt;
|-&lt;br /&gt;
| ... || (continue for other scenarios)&lt;br /&gt;
|-&lt;br /&gt;
| 12 || **pair_programming_enabled?**&lt;br /&gt;
|-&lt;br /&gt;
| 12.1 || Scenario 1: Pair programming is enabled. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 12.2 || Scenario 2: Pair programming is disabled. Expected: false&lt;br /&gt;
|-&lt;br /&gt;
| 13 || **staggered_and_no_topic?**&lt;br /&gt;
|-&lt;br /&gt;
| 13.1 || Scenario 1: Staggered deadline is enabled, topic_id not provided. Expected: true&lt;br /&gt;
|-&lt;br /&gt;
| 13.2 || Scenario 2: Staggered deadline is enabled, topic_id provided. Expected: false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=151250</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=151250"/>
		<updated>2023-11-07T03:54:25Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
A reimplementation was required for assignment model and assignment controller. The following tasks were required for the reimplementation : &lt;br /&gt;
#Creating necessary associations between assignment model and other models such as course, participants, instructor.&lt;br /&gt;
#Reimplementation for the following methods in assignment model and necessary controller actions and routes : &lt;br /&gt;
#* &amp;lt;strong&amp;gt; add_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to add a participant to an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to remove a participant from an assignment.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; assign_courses_to_assignment &amp;lt;/strong&amp;gt; : Associates the assignments with a given course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_assignment_from_course&amp;lt;/strong&amp;gt; : Dissociates an assignment from a course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; copy_assignment &amp;lt;/strong&amp;gt; : Creates a copy of an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; delete &amp;lt;/strong&amp;gt; : CRUD operation for deleting the assignment and necessary dependencies. &lt;br /&gt;
#* Writing rspec and rswag test case for assignment model and controller respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tasks Completed==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Migrations&amp;lt;/strong&amp;gt; - &lt;br /&gt;
Before starting with the implementation, we created necessary migrations for fixing up the schema. The fields course_id and instructor_id were added to the Assignment Model as attributes instead of being added as foreign key references. Hence necessary migrations were created for removing these fields and adding them as references to the Assignment model.&lt;br /&gt;
&lt;br /&gt;
The following migration files were added : &lt;br /&gt;
20231104070639_remove_instructor_id_from_assignments.rb&lt;br /&gt;
20231104071922_add_instructor_to_assignments.rb&lt;br /&gt;
20231105193016_remove_course_id_from_assignments.rb&lt;br /&gt;
20231105193219_add_course_to_assignments.rb&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Models &amp;lt;/strong&amp;gt; - &lt;br /&gt;
&lt;br /&gt;
Assignment_Participant&lt;br /&gt;
A new model -  Assignment_Participant was added as it was missing from the current implementation. This model was required for implementing the add_participant method. &lt;br /&gt;
&lt;br /&gt;
Assignment.rb - &lt;br /&gt;
#We followed the single responsibility principle where all the methods relevant to assignment instances were implemented in the Assignment model. &lt;br /&gt;
#The method ‘set_handle’ required as a sub-method for add_participant method was moved to assignment_participant.rb as it is used for setting the handle for a participant instance. &lt;br /&gt;
#A separate method for deleting the assignment was also not needed in the new implementation as it is already being fulfilled by the CRUD operation in the assignment controller.&lt;br /&gt;
#The implementation for assign_course_to_assignment seemed incorrect as it was only setting @course variable with the course having course_id. We added the correct method to the new implementation where course_id was assigned to the assignment.&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that were re-implemented:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;add_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: POST&lt;br /&gt;
** Endpoint:  api/v1/{assignment_id}/add_participant/{user_id}&lt;br /&gt;
** Input: assignment_id, user_id&lt;br /&gt;
** Output: Response code and JSON of assignment participant &lt;br /&gt;
** Description: It allows super admins, admins, instructors, and teaching assistants to add a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;remove_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: DELETE&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/remove_participant/{user_id}&lt;br /&gt;
** Input: assignment_id, user_id&lt;br /&gt;
** Output: Response code&lt;br /&gt;
** Description: It allows super admins, admins, instructors, and teaching assistants to remove a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;remove_assignment_from_course&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: PATCH&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/remove_assignment_from_course&lt;br /&gt;
** Input: assignment_id&lt;br /&gt;
** Output: Response code and JSON of updated assignment&lt;br /&gt;
** Description: It makes the course_id of the given assignment null (removes the assignment from its course).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;assign_courses_to_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: PATCH&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/assign_courses_to_assignment/{course_id}&lt;br /&gt;
** Input: assignment_id, course_id&lt;br /&gt;
** Output: Response code and JSON of updated assignment&lt;br /&gt;
** Description: It assigns the given course_id to the given assignment. &lt;br /&gt;
 &lt;br /&gt;
* &amp;lt;strong&amp;gt;destroy(delete_assignment)&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: DELETE&lt;br /&gt;
** Endpoint:api/v1/assignment/{assignment_id}&lt;br /&gt;
** Input: assignment_id&lt;br /&gt;
** Output: Response code&lt;br /&gt;
** Description: It deletes the specified assignment.  &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;copy_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: POST&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/copy_assignment&lt;br /&gt;
** Input: assignment_id&lt;br /&gt;
** Output: Response code and JSON of copied assignment.&lt;br /&gt;
** Description: It copies the assignment and stores the copy with the name “Copy of” + the original assignment name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt; Controller - Assignment_Controller.rb &amp;lt;/strong&amp;gt;&lt;br /&gt;
For the new methods added in the assignment model, we added corresponding actions in the assignment controller with the same name and routes in config.rb as mentioned in above documentation. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/config/routes.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/models/assignment_spec.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/spec/factories/factories.rb&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
==Test Plan==&lt;br /&gt;
This testing plan outlines 10 test cases to validate the functionality of the Assignment Model.&lt;br /&gt;
* Adding a Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create a user and assignment, call add_participant, check for an increase in Assignment Participants count, and verify correct association&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a user is added as a participant.&lt;br /&gt;
&lt;br /&gt;
* Error When Adding Non-Existing Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment, call add_participant with a non-existing user ID, expect a RuntimeError, and check the AssignmentParticipants count remains unchanged.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised and no participant is added when the user does not exist.&lt;br /&gt;
&lt;br /&gt;
* Error When Adding Duplicate Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create a user and assignment, add the user as a participant, try to add the same user again, expect a RuntimeError, and check no duplicate participant is added.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised and no duplicate participant is added.&lt;br /&gt;
&lt;br /&gt;
* Removing a Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and user, add the user as a participant, call remove_participant, check for a decrease in AssignmentParticipants count, and ensure the participant is removed.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a participant is successfully removed.&lt;br /&gt;
&lt;br /&gt;
* Trying to Remove a Non-Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and user, attempt to remove a non-participant, and ensure the AssignmentParticipants count remains unchanged.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if no participant is removed when trying to remove a non-participant.&lt;br /&gt;
&lt;br /&gt;
* Successful Assignment of Course&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, call .assign_courses_to_assignment, and check if the assignment's course_id is set correctly.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if the course is successfully assigned to the assignment.&lt;br /&gt;
&lt;br /&gt;
* Error on Reassignment&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, set the assignment's course_id to the course's ID, try to assign the same course again, and expect an error with a specific message.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised when trying to reassign the same course.&lt;br /&gt;
&lt;br /&gt;
* Removing Assignment from Course&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and course, assign the course to the assignment, call remove_assignment_from_course, and verify the course_id is set to nil and the modified assignment is returned.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if the course is successfully removed, and the modified assignment is returned.&lt;br /&gt;
&lt;br /&gt;
* Error on removing course when course_id is nil&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, try removing a course from an assignment when course_id is already nil.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised when trying to remove a course when course_id is nil.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Copying an Assignment&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment, call copy_assignment, and verify the copied assignment has a new name and retains other properties.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a copy of the assignment with a new name is successfully created.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; Here is a video of successfully running the test cases:&lt;br /&gt;
[https://drive.google.com/file/d/1jfDoyaiux8XXxq3ibklnZrOMKZwf2SVS/view?usp=sharing]&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=151141</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=151141"/>
		<updated>2023-11-06T04:03:58Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
A reimplementation was required for assignment model and assignment controller. The following tasks were required for the reimplementation : &lt;br /&gt;
#Creating necessary associations between assignment model and other models such as course, participants, instructor.&lt;br /&gt;
#Reimplementation for the following methods in assignment model and necessary controller actions and routes : &lt;br /&gt;
#* &amp;lt;strong&amp;gt; add_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to add a participant to an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to remove a participant from an assignment.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; assign_courses_to_assignment &amp;lt;/strong&amp;gt; : Associates the assignments with a given course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_assignment_from_course&amp;lt;/strong&amp;gt; : Dissociates an assignment from a course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; copy_assignment &amp;lt;/strong&amp;gt; : Creates a copy of an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; delete &amp;lt;/strong&amp;gt; : CRUD operation for deleting the assignment and necessary dependencies. &lt;br /&gt;
#* Writing rspec and rswag test case for assignment model and controller respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tasks Completed==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Migrations&amp;lt;/strong&amp;gt; - &lt;br /&gt;
Before starting with the implementation, we created necessary migrations for fixing up the schema. The fields course_id and instructor_id were added to the Assignment Model as attributes instead of being added as foreign key references. Hence necessary migrations were created for removing these fields and adding them as references to the Assignment model.&lt;br /&gt;
&lt;br /&gt;
The following migration files were added : &lt;br /&gt;
20231104070639_remove_instructor_id_from_assignments.rb&lt;br /&gt;
20231104071922_add_instructor_to_assignments.rb&lt;br /&gt;
20231105193016_remove_course_id_from_assignments.rb&lt;br /&gt;
20231105193219_add_course_to_assignments.rb&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Models &amp;lt;/strong&amp;gt; - &lt;br /&gt;
&lt;br /&gt;
Assignment_Participant&lt;br /&gt;
A new model -  Assignment_Participant was added as it was missing from the current implementation. This model was required for implementing the add_participant method. &lt;br /&gt;
&lt;br /&gt;
Assignment.rb - &lt;br /&gt;
#We followed the single responsibility principle where all the methods relevant to assignment instances were implemented in the Assignment model. &lt;br /&gt;
#The method ‘set_handle’ required as a sub-method for add_participant method was moved to assignment_participant.rb as it is used for setting the handle for a participant instance. &lt;br /&gt;
#A separate method for deleting the assignment was also not needed in the new implementation as it is already being fulfilled by the CRUD operation in the assignment controller.&lt;br /&gt;
#The implementation for assign_course_to_assignment seemed incorrect as it was only setting @course variable with the course having course_id. We added the correct method to the new implementation where course_id was assigned to the assignment.&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that were re-implemented:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;add_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: POST&lt;br /&gt;
** Endpoint:  api/v1/{assignment_id}/add_participant/{user_id}&lt;br /&gt;
** Input: assignment_id, user_id&lt;br /&gt;
** Output: Response code and JSON of assignment participant &lt;br /&gt;
** Description: It allows super admins, admins, instructors, and teaching assistants to add a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;remove_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: DELETE&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/remove_participant/{user_id}&lt;br /&gt;
** Input: assignment_id, user_id&lt;br /&gt;
** Output: Response code&lt;br /&gt;
** Description: It allows super admins, admins, instructors, and teaching assistants to remove a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;remove_assignment_from_course&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: PATCH&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/remove_assignment_from_course&lt;br /&gt;
** Input: assignment_id&lt;br /&gt;
** Output: Response code and JSON of updated assignment&lt;br /&gt;
** Description: It makes the course_id of the given assignment null (removes the assignment from its course).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;assign_courses_to_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: PATCH&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/assign_courses_to_assignment/{course_id}&lt;br /&gt;
** Input: assignment_id, course_id&lt;br /&gt;
** Output: Response code and JSON of updated assignment&lt;br /&gt;
** Description: It assigns the given course_id to the given assignment. &lt;br /&gt;
 &lt;br /&gt;
* &amp;lt;strong&amp;gt;destroy(delete_assignment)&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: DELETE&lt;br /&gt;
** Endpoint:api/v1/assignment/{assignment_id}&lt;br /&gt;
** Input: assignment_id&lt;br /&gt;
** Output: Response code&lt;br /&gt;
** Description: It deletes the specified assignment.  &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;strong&amp;gt;copy_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
** HTTP Method: POST&lt;br /&gt;
** Endpoint: api/v1/{assignment_id}/copy_assignment&lt;br /&gt;
** Input: assignment_id&lt;br /&gt;
** Output: Response code and JSON of copied assignment.&lt;br /&gt;
** Description: It copies the assignment and stores the copy with the name “Copy of” + the original assignment name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt; Controller - Assignment_Controller.rb &amp;lt;/strong&amp;gt;&lt;br /&gt;
For the new methods added in the assignment model, we added corresponding actions in the assignment controller with the same name and routes in config.rb as mentioned in above documentation. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
==Test Plan==&lt;br /&gt;
This testing plan outlines 10 test cases to validate the functionality of the Assignment Model.&lt;br /&gt;
* Adding a Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create a user and assignment, call add_participant, check for an increase in Assignment Participants count, and verify correct association&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a user is added as a participant.&lt;br /&gt;
&lt;br /&gt;
* Error When Adding Non-Existing Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment, call add_participant with a non-existing user ID, expect a RuntimeError, and check the AssignmentParticipants count remains unchanged.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised and no participant is added when the user does not exist.&lt;br /&gt;
&lt;br /&gt;
* Error When Adding Duplicate Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create a user and assignment, add the user as a participant, try to add the same user again, expect a RuntimeError, and check no duplicate participant is added.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised and no duplicate participant is added.&lt;br /&gt;
&lt;br /&gt;
* Removing a Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and user, add the user as a participant, call remove_participant, check for a decrease in AssignmentParticipants count, and ensure the participant is removed.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a participant is successfully removed.&lt;br /&gt;
&lt;br /&gt;
* Trying to Remove a Non-Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and user, attempt to remove a non-participant, and ensure the AssignmentParticipants count remains unchanged.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if no participant is removed when trying to remove a non-participant.&lt;br /&gt;
&lt;br /&gt;
* Successful Assignment of Course&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, call .assign_courses_to_assignment, and check if the assignment's course_id is set correctly.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if the course is successfully assigned to the assignment.&lt;br /&gt;
&lt;br /&gt;
* Error on Reassignment&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, set the assignment's course_id to the course's ID, try to assign the same course again, and expect an error with a specific message.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised when trying to reassign the same course.&lt;br /&gt;
&lt;br /&gt;
* Removing Assignment from Course&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and course, assign the course to the assignment, call remove_assignment_from_course, and verify the course_id is set to nil and the modified assignment is returned.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if the course is successfully removed, and the modified assignment is returned.&lt;br /&gt;
&lt;br /&gt;
* Error on removing course when course_id is nil&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, try removing a course from an assignment when course_id is already nil.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised when trying to remove a course when course_id is nil.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Copying an Assignment&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment, call copy_assignment, and verify the copied assignment has a new name and retains other properties.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a copy of the assignment with a new name is successfully created.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; Here is a video of successfully running the test cases:&lt;br /&gt;
[https://drive.google.com/file/d/1jfDoyaiux8XXxq3ibklnZrOMKZwf2SVS/view?usp=sharing]&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=151140</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=151140"/>
		<updated>2023-11-06T03:27:10Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
A reimplementation was required for assignment model and assignment controller. The following tasks were required for the reimplementation : &lt;br /&gt;
#Creating necessary associations between assignment model and other models such as course, participants, instructor.&lt;br /&gt;
#Reimplementation for the following methods in assignment model and necessary controller actions and routes : &lt;br /&gt;
#* &amp;lt;strong&amp;gt; add_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to add a participant to an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to remove a participant from an assignment.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; assign_courses_to_assignment &amp;lt;/strong&amp;gt; : Associates the assignments with a given course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_assignment_from_course&amp;lt;/strong&amp;gt; : Dissociates an assignment from a course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; copy_assignment &amp;lt;/strong&amp;gt; : Creates a copy of an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; delete &amp;lt;/strong&amp;gt; : CRUD operation for deleting the assignment and necessary dependencies. &lt;br /&gt;
#* Writing rspec and rswag test case for assignment model and controller respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that were re- implemented:&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;add_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#*HTTP Method: POST&lt;br /&gt;
#*Endpoint:  api/v1/{assignment_id}/add_participant/{user_id}&lt;br /&gt;
#*Input: assignment_id, user_id&lt;br /&gt;
#*Output: Response code and JSON of assignment participant &lt;br /&gt;
#*Description: It allows super admins, admins, instructors, and teaching assistants to add a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;remove_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: DELETE&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/remove_participant/{user_id}&lt;br /&gt;
#*Input: assignment_id, user_id&lt;br /&gt;
#*Output: Response code&lt;br /&gt;
#*Description: It allows super admins, admins, instructors, and teaching assistants to remove a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;remove_assignment_from_course&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: PATCH&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/remove_assignment_from_course&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code and JSON of updated assignment&lt;br /&gt;
#*Description: It makes the course_id of the given assignment null (removes the assignment from its course).&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;assign_courses_to_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: PATCH&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/assign_courses_to_assignment/{course_id}&lt;br /&gt;
#*Input: assignment_id, course_id&lt;br /&gt;
#*Output: Response code and JSON of updated assignment&lt;br /&gt;
#*Description: It assigns the given course_id to the given assignment. &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;destroy(delete_assignment)&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: DELETE&lt;br /&gt;
#*Endpoint:api/v1/assignment/{assignment_id}&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code&lt;br /&gt;
#*Description: It deletes the specified assignment.  &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;copy_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: POST&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/copy_assignment&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code and JSON of copied assignment.&lt;br /&gt;
#*Description: It copies the assignment and stores the copy with the name “Copy of” + the original assignment name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
This testing plan outlines 10 test cases to validate the functionality of the Assignment Model.&lt;br /&gt;
#Adding a Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create a user and assignment, call add_participant, check for an increase in Assignment Participants count, and verify correct association&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a user is added as a participant.&lt;br /&gt;
&lt;br /&gt;
#Error When Adding Non-Existing Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment, call add_participant with a non-existing user ID, expect a RuntimeError, and check the AssignmentParticipants count remains unchanged.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised and no participant is added when the user does not exist.&lt;br /&gt;
&lt;br /&gt;
#Error When Adding Duplicate Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create a user and assignment, add the user as a participant, try to add the same user again, expect a RuntimeError, and check no duplicate participant is added.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised and no duplicate participant is added.&lt;br /&gt;
&lt;br /&gt;
#Removing a Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and user, add the user as a participant, call remove_participant, check for a decrease in AssignmentParticipants count, and ensure the participant is removed.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a participant is successfully removed.&lt;br /&gt;
&lt;br /&gt;
#Trying to Remove a Non-Participant&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and user, attempt to remove a non-participant, and ensure the AssignmentParticipants count remains unchanged.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if no participant is removed when trying to remove a non-participant.&lt;br /&gt;
&lt;br /&gt;
#Successful Assignment of Course&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, call .assign_courses_to_assignment, and check if the assignment's course_id is set correctly.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if the course is successfully assigned to the assignment.&lt;br /&gt;
&lt;br /&gt;
#Error on Reassignment&lt;br /&gt;
&lt;br /&gt;
Steps: Create a new assignment and a course, set the assignment's course_id to the course's ID, try to assign the same course again, and expect an error with a specific message.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised when trying to reassign the same course.&lt;br /&gt;
&lt;br /&gt;
#Removing Assignment from Course&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment and course, assign the course to the assignment, call remove_assignment_from_course, and verify the course_id is set to nil and the modified assignment is returned.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if the course is successfully removed, and the modified assignment is returned.&lt;br /&gt;
&lt;br /&gt;
#Error on removing course when course_id is nil.&lt;br /&gt;
Steps: Create a new assignment and a course, try removing a course from an assignment when course_id is already nil.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if an error is raised when trying to remove a course when course_id is nil.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#Copying an Assignment&lt;br /&gt;
&lt;br /&gt;
Steps: Create an assignment, call copy_assignment, and verify the copied assignment has a new name and retains other properties.&lt;br /&gt;
&amp;lt;br&amp;gt;Outcome: Pass if a copy of the assignment with a new name is successfully created.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=150607</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=150607"/>
		<updated>2023-10-30T20:01:09Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
A reimplementation was required for assignment model and assignment controller. The following tasks were required for the reimplementation : &lt;br /&gt;
#Creating necessary associations between assignment model and other models such as course, participants, instructor.&lt;br /&gt;
#Reimplementation for the following methods in assignment model and necessary controller actions and routes : &lt;br /&gt;
#* &amp;lt;strong&amp;gt; add_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to add a participant to an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to remove a participant from an assignment.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; assign_courses_to_assignment &amp;lt;/strong&amp;gt; : Associates the assignments with a given course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_assignment_from_course&amp;lt;/strong&amp;gt; : Dissociates an assignment from a course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; copy_assignment &amp;lt;/strong&amp;gt; : Creates a copy of an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; delete &amp;lt;/strong&amp;gt; : CRUD operation for deleting the assignment and necessary dependencies. &lt;br /&gt;
#* Writing rspec and rswag test case for assignment model and controller respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that were re- implemented:&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;add_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#*HTTP Method: POST&lt;br /&gt;
#*Endpoint:  api/v1/{assignment_id}/add_participant/{user_id}&lt;br /&gt;
#*Input: assignment_id, user_id&lt;br /&gt;
#*Output: Response code and JSON of assignment participant &lt;br /&gt;
#*Description: It allows super admins, admins, instructors, and teaching assistants to add a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;remove_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: DELETE&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/remove_participant/{user_id}&lt;br /&gt;
#*Input: assignment_id, user_id&lt;br /&gt;
#*Output: Response code&lt;br /&gt;
#*Description: It allows super admins, admins, instructors, and teaching assistants to remove a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;remove_assignment_from_course&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: PATCH&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/remove_assignment_from_course&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code and JSON of updated assignment&lt;br /&gt;
#*Description: It makes the course_id of the given assignment null (removes the assignment from its course).&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;assign_courses_to_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: PATCH&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/assign_courses_to_assignment/{course_id}&lt;br /&gt;
#*Input: assignment_id, course_id&lt;br /&gt;
#*Output: Response code and JSON of updated assignment&lt;br /&gt;
#*Description: It assigns the given course_id to the given assignment. &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;destroy(delete_assignment)&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: DELETE&lt;br /&gt;
#*Endpoint:api/v1/assignment/{assignment_id}&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code&lt;br /&gt;
#*Description: It deletes the specified assignment.  &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;copy_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: POST&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/copy_assignment&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code and JSON of copied assignment.&lt;br /&gt;
#*Description: It copies the assignment and stores the copy with the name “Copy of” + the original assignment name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Copy_assignment- POSTMAN&lt;br /&gt;
[[File:Copy assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=150603</id>
		<title>CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2366._Reimplement_assignment_model_and_assignment_controller&amp;diff=150603"/>
		<updated>2023-10-30T19:54:47Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: Created page with &amp;quot;==Expertiza==  [http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects,...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project. Instructors have the ability to add new projects, assignments, etc., as well as edit existing ones. Later on, they can view student submissions and grade them. Students can also use Expertiza to organize into teams to work on different projects and assignments and submit their work. They can also review other students' submissions.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
A reimplementation was required for assignment model and assignment controller. The following tasks were required for the reimplementation : &lt;br /&gt;
#Creating necessary associations between assignment model and other models such as course, participants, instructor.&lt;br /&gt;
#Reimplementation for the following methods in assignment model and necessary controller actions and routes : &lt;br /&gt;
#* &amp;lt;strong&amp;gt; add_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to add a participant to an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_participant &amp;lt;/strong&amp;gt; : Allows a user with an appropriate role to remove a participant from an assignment.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; assign_courses_to_assignment &amp;lt;/strong&amp;gt; : Associates the assignments with a given course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; remove_assignment_from_course&amp;lt;/strong&amp;gt; : Dissociates an assignment from a course.&lt;br /&gt;
#* &amp;lt;strong&amp;gt; copy_assignment &amp;lt;/strong&amp;gt; : Creates a copy of an assignment&lt;br /&gt;
#* &amp;lt;strong&amp;gt; delete &amp;lt;/strong&amp;gt; : CRUD operation for deleting the assignment and necessary dependencies. &lt;br /&gt;
#* Writing rspec and rswag test case for assignment model and controller respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Documentation for methods that were re- implemented:&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;add_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#*HTTP Method: POST&lt;br /&gt;
#*Endpoint:  api/v1/{assignment_id}/add_participant/{user_id}&lt;br /&gt;
#*Input: assignment_id, user_id&lt;br /&gt;
#*Output: Response code and JSON of assignment participant &lt;br /&gt;
#*Description: It allows super admins, admins, instructors, and teaching assistants to add a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;remove_participant&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: DELETE&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/remove_participant/{user_id}&lt;br /&gt;
#*Input: assignment_id, user_id&lt;br /&gt;
#*Output: Response code&lt;br /&gt;
#*Description: It allows super admins, admins, instructors, and teaching assistants to remove a particular participant (student) from the given assignment.&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;remove_assignment_from_course&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: PATCH&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/remove_assignment_from_course&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code and JSON of updated assignment&lt;br /&gt;
#*Description: It makes the course_id of the given assignment null (removes the assignment from its course).&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;assign_courses_to_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: PATCH&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/assign_courses_to_assignment/{course_id}&lt;br /&gt;
#*Input: assignment_id, course_id&lt;br /&gt;
#*Output: Response code and JSON of updated assignment&lt;br /&gt;
#*Description: It assigns the given course_id to the given assignment. &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;destroy(delete_assignment)&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: DELETE&lt;br /&gt;
#*Endpoint:api/v1/assignment/{assignment_id}&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code&lt;br /&gt;
#*Description: It deletes the specified assignment.  &lt;br /&gt;
&lt;br /&gt;
#&amp;lt;strong&amp;gt;copy_assignment&amp;lt;/strong&amp;gt;&lt;br /&gt;
#*HTTP Method: POST&lt;br /&gt;
#*Endpoint: api/v1/{assignment_id}/copy_assignment&lt;br /&gt;
#*Input: assignment_id&lt;br /&gt;
#*Output: Response code and JSON of copied assignment.&lt;br /&gt;
#*Description: It copies the assignment and stores the copy with the name “Copy of” + the original assignment name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Files added / modified ==&lt;br /&gt;
&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/course.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/models/assignment_participant.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/app/controllers/api/v1/assignments_controller.rb&lt;br /&gt;
*reimplementation-back-end/blob/main/db/schema.rb&lt;br /&gt;
&lt;br /&gt;
== Manual Testing Using POSTMAN ==&lt;br /&gt;
&lt;br /&gt;
Postman was used for manually testing the added method in assignment.rb and their respective controllers actions and routes. Before testing any of these methods using Postman, a request to /login needs to be sent with user_name an password fields which sends a authentication token. This token needs to be added in Postman’s ‘Authorization’ tab as ‘Bearer token’ before any further requests can be made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*add_participant - POSTMAN&lt;br /&gt;
[[File:Add_participant_to_assignment-POSTMAN.jpeg ‎| 500px]]&lt;br /&gt;
*new participant created - rails console&lt;br /&gt;
[[File:Newparticipantcreated.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_participant - POSTMAN&lt;br /&gt;
[[File:Remove_participant-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*remove_assignment_from_course - POSTMAN&lt;br /&gt;
[[File:Remove_asssignmenta_from_course-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
*assign_courses_to_assignment - POSTMAN&lt;br /&gt;
[[File:Assign_course_to_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
*destroy(delete_assignment) - POSTMAN&lt;br /&gt;
[[File:Delete_assignment-POSTMAN.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Original Assignment - rails console&lt;br /&gt;
[[File:OriginalAssignment.jpeg | 500px]]&lt;br /&gt;
*Copied Assignment - rails console&lt;br /&gt;
[[File:CopiedAssignment.jpeg | 500px]]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
=====Mentor===== &lt;br /&gt;
*Ameya Vaichalkar&lt;br /&gt;
&lt;br /&gt;
=====Members===== &lt;br /&gt;
*Bhavya Harchandani &amp;lt;bharcha@ncsu.edu&amp;gt;&lt;br /&gt;
*Akshat Saxena&amp;lt;asaxen24@ncsu.edu&amp;gt;&lt;br /&gt;
*Mitali Sethi &amp;lt;msethi@ncsu.edu&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pull Request==&lt;br /&gt;
*[https://github.com/expertiza/reimplementation-back-end/pull/54]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*[https://docs.google.com/document/d/1dXwTNHR26eou6EJZkME8k8FhlpxCf_roMmWzclca8bA/edit?usp=sharing Project Instructions]&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Delete_assignment-POSTMAN.jpeg&amp;diff=150593</id>
		<title>File:Delete assignment-POSTMAN.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Delete_assignment-POSTMAN.jpeg&amp;diff=150593"/>
		<updated>2023-10-30T19:37:25Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Assign_course_to_assignment-POSTMAN.jpeg&amp;diff=150592</id>
		<title>File:Assign course to assignment-POSTMAN.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Assign_course_to_assignment-POSTMAN.jpeg&amp;diff=150592"/>
		<updated>2023-10-30T19:37:14Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Remove_participant-POSTMAN.jpeg&amp;diff=150591</id>
		<title>File:Remove participant-POSTMAN.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Remove_participant-POSTMAN.jpeg&amp;diff=150591"/>
		<updated>2023-10-30T19:37:02Z</updated>

		<summary type="html">&lt;p&gt;Bharcha: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bharcha</name></author>
	</entry>
</feed>