<?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=Naydt</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=Naydt"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Naydt"/>
	<updated>2026-06-25T20:11:25Z</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_2022_-_E2281._Reimplement_Waitlists&amp;diff=147311</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147311"/>
		<updated>2022-12-12T19:17:19Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* RSPEC Test Cases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', they needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method stores the incoming team_id and topic_id into the instance of WaitlistTeam'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it ensures its valid before storing it in the database, if it is not, then it has an error''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method first searches the database for the instance of WaitlistTeam that matches the incoming team_id and topic_id'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it calls the destroyer to remove the instance from the database''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''When a team is added to a topic or removed from an assignment, this method is called'' &amp;lt;br&amp;gt;&lt;br /&gt;
''It first finds all Waitlists associated with that teams team_id for that assignment'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then one by one destroys the entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_on_waitlist'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_on_waitlist(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_is_on_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_is_on_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_waitlist?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_waitlist?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Finds the list of waitlist entries for a team'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then calls the destroyer to remove the entries''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Finds the list of waitlist entries for a topic'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then calls the destroyer to remove the entries''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Order is dependent on the created_at attribute''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''sign_up_first_waitlisted_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.sign_up_first_waitlisted_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_on_waitlist(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistController.sign_up_first_waitlisted_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistController.team_is_on_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistController.topic_has_waitlist?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147310</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147310"/>
		<updated>2022-12-12T19:14:43Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Controller Methods (app/controllers/waitlist_team_controller.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', they needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method stores the incoming team_id and topic_id into the instance of WaitlistTeam'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it ensures its valid before storing it in the database, if it is not, then it has an error''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method first searches the database for the instance of WaitlistTeam that matches the incoming team_id and topic_id'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it calls the destroyer to remove the instance from the database''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''When a team is added to a topic or removed from an assignment, this method is called'' &amp;lt;br&amp;gt;&lt;br /&gt;
''It first finds all Waitlists associated with that teams team_id for that assignment'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then one by one destroys the entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_on_waitlist'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_on_waitlist(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_is_on_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_is_on_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_waitlist?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_waitlist?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Finds the list of waitlist entries for a team'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then calls the destroyer to remove the entries''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Finds the list of waitlist entries for a topic'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then calls the destroyer to remove the entries''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Order is dependent on the created_at attribute''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''sign_up_first_waitlisted_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.sign_up_first_waitlisted_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_on_waitlist(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147291</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147291"/>
		<updated>2022-12-12T15:21:20Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Controller Methods (app/controllers/waitlist_team_controller.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', they needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method stores the incoming team_id and topic_id into the instance of WaitlistTeam'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it ensures its valid before storing it in the database, if it is not, then it has an error''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method first searches the database for the instance of WaitlistTeam that matches the incoming team_id and topic_id'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it calls the destroyer to remove the instance from the database''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''When a team is added to a topic or removed from an assignment, this method is called'' &amp;lt;br&amp;gt;&lt;br /&gt;
''It first finds all Waitlists associated with that teams team_id for that assignment'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then one by one destroys the entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Finds the list of waitlist entries for a team'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then calls the destroyer to remove the entries''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Finds the list of waitlist entries for a topic'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then calls the destroyer to remove the entries''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Order is dependent on the created_at attribute''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147290</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147290"/>
		<updated>2022-12-12T15:18:13Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Model Methods (app/models/waitlist_team.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', they needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method stores the incoming team_id and topic_id into the instance of WaitlistTeam'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it ensures its valid before storing it in the database, if it is not, then it has an error''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method first searches the database for the instance of WaitlistTeam that matches the incoming team_id and topic_id'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it calls the destroyer to remove the instance from the database''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''When a team is added to a topic or removed from an assignment, this method is called'' &amp;lt;br&amp;gt;&lt;br /&gt;
''It first finds all Waitlists associated with that teams team_id for that assignment'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then one by one destroys the entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147289</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147289"/>
		<updated>2022-12-12T15:17:54Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Model Methods (app/models/waitlist_team.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', they needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method stores the incoming team_id and topic_id into the instance of WaitlistTeam'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it ensures its valid before storing it in the database, if it is not, then it has an error''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method first searches the database for the instance of WaitlistTeam that matches the incoming team_id and topic_id'' &amp;lt;br&amp;gt;&lt;br /&gt;
''Then it calls the destroyer to remove the instance from the database''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''When a team is added to a topic or removed from an assignment, this method is called''&lt;br /&gt;
''It first finds all Waitlists associated with that teams team_id for that assignment''&lt;br /&gt;
''Then one by one destroys the entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147288</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147288"/>
		<updated>2022-12-12T15:16:08Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Model Methods (app/models/waitlist_team.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', they needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method stores the incoming team_id and topic_id into the instance of WaitlistTeam''&lt;br /&gt;
''Then it ensures its valid before storing it in the database, if it is not, then it has an error''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''This method first searches the database for the instance of WaitlistTeam that matches the incoming team_id and topic_id''&lt;br /&gt;
''Then it calls the destroyer to remove the instance from the database''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147287</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147287"/>
		<updated>2022-12-12T15:13:26Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', they needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147286</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147286"/>
		<updated>2022-12-12T15:13:06Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', the needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# '''team_id''': This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# '''topic_id''': In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# '''created_at''': This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147285</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147285"/>
		<updated>2022-12-12T15:12:49Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
When creating ''WaitlistTeams'', the needed to be stored in the database in a particular way. The ''WaitlistTeams'' instance contains three columns: &amp;lt;br&amp;gt;&lt;br /&gt;
# team_id: This stores the '''team_id''' of the team being waitlisted. This ID comes from their assignment team.&lt;br /&gt;
# topic_id: In order to keep track of teams for a certain topic, it must be link to the topic by storing it's '''topic_id'''.&lt;br /&gt;
# created_at: This is used to keep track of the order in which teams waitlist. While usually you can just look at the order in the database, this gives us an extra level of accuracy that the teams are ordered correctly.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147284</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147284"/>
		<updated>2022-12-12T15:08:32Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class CreateWaitlistTeams &amp;lt; ActiveRecord::Migration[5.1]&lt;br /&gt;
&lt;br /&gt;
  def self.up&lt;br /&gt;
    create_table 'waitlist_teams' do |t|&lt;br /&gt;
      t.column 'team_id', :integer&lt;br /&gt;
      t.column 'topic_id', :integer&lt;br /&gt;
      t.column 'created_at', :datetime&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['team_id'], name: 'fk_waitlist_teams'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
                 add constraint fk_waitlist_teams&lt;br /&gt;
                 foreign key (team_id) references teams(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', ['topic_id'], name: 'fk_waitlist_teams_sign_up_topics'&lt;br /&gt;
&lt;br /&gt;
    execute &amp;quot;alter table waitlist_teams&lt;br /&gt;
               add constraint fk_waitlist_teams_sign_up_topics&lt;br /&gt;
               foreign key (topic_id) references sign_up_topics(id)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    add_index 'waitlist_teams', [&amp;quot;team_id&amp;quot;, &amp;quot;topic_id&amp;quot;], unique: true&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.down&lt;br /&gt;
    drop_table 'waitlist_teams'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147283</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147283"/>
		<updated>2022-12-12T15:07:49Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Our Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
=== Schema Changes (db/migrate/20221129040129_create_waitlist_teams.rb) ===&lt;br /&gt;
&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147224</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147224"/>
		<updated>2022-12-06T03:35:03Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Controller Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods (app/controllers/waitlist_team_controller.rb)===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147222</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147222"/>
		<updated>2022-12-06T03:34:23Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Model Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods (app/models/waitlist_team.rb)===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147221</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147221"/>
		<updated>2022-12-06T03:34:11Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* app/models/waitlist_team.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147220</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147220"/>
		<updated>2022-12-06T03:33:53Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Model Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
==== app/models/waitlist_team.rb ====&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147214</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147214"/>
		<updated>2022-12-06T03:26:45Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Logged in as ''student10'', notice that you are waitlisted for '''Topic 1''', '''Topic 2''' and '''Topic 3'''&lt;br /&gt;
# Click the check next to '''Topic 4'''&lt;br /&gt;
# This will cancel waitlists for '''Topic 1''', '''Topic 2''' and '''Topic 3''' and assign '''Topic 4'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:Testcase_3.gif]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Testcase_3.gif&amp;diff=147213</id>
		<title>File:Testcase 3.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Testcase_3.gif&amp;diff=147213"/>
		<updated>2022-12-06T03:23:49Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Testcase 3, for E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Testcase 3, for E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147210</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147210"/>
		<updated>2022-12-06T03:10:42Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
==== Test Case 3 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Student_View_After_Deleting_Topic_3.PNG&amp;diff=147209</id>
		<title>File:Student View After Deleting Topic 3.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Student_View_After_Deleting_Topic_3.PNG&amp;diff=147209"/>
		<updated>2022-12-06T03:08:46Z</updated>

		<summary type="html">&lt;p&gt;Naydt: student10's view of topics after topic 3 has been deleted. E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;student10's view of topics after topic 3 has been deleted. E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147208</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147208"/>
		<updated>2022-12-06T03:08:03Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&amp;lt;br&amp;gt; [[File:Instructor_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&amp;lt;br&amp;gt; [[File:Student_View_After_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Instructor_View_After_Deleting_Topic_3.PNG&amp;diff=147207</id>
		<title>File:Instructor View After Deleting Topic 3.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Instructor_View_After_Deleting_Topic_3.PNG&amp;diff=147207"/>
		<updated>2022-12-06T03:07:10Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Instructor view of topics after topic 3 is deleted. E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Instructor view of topics after topic 3 is deleted. E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147205</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147205"/>
		<updated>2022-12-06T03:05:55Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3''' &amp;lt;br&amp;gt; [[File:Before_Deleting_Topic_3.PNG|600px|]]&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Before_Deleting_Topic_3.PNG&amp;diff=147204</id>
		<title>File:Before Deleting Topic 3.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Before_Deleting_Topic_3.PNG&amp;diff=147204"/>
		<updated>2022-12-06T03:05:30Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Instructor View of Topic 3, prior to deletion. E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Instructor View of Topic 3, prior to deletion. E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147203</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147203"/>
		<updated>2022-12-06T03:04:34Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# As instructor notice that ''student10'' is waitlisted for '''Topic 1''' and '''Topic 3'''&lt;br /&gt;
# When Instructor Deletes '''Topic 3'''&lt;br /&gt;
# Login as ''student10''&lt;br /&gt;
# Notice ''student10'' is only waitlisted for '''Topic 1'''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147201</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147201"/>
		<updated>2022-12-06T02:49:56Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Manual UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147200</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147200"/>
		<updated>2022-12-06T02:49:46Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Manual UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: student 11, student14, student15&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Login: instructor6&lt;br /&gt;
Password: password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147199</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147199"/>
		<updated>2022-12-06T02:48:36Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Planned Test Cases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147198</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147198"/>
		<updated>2022-12-06T02:44:50Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147197</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147197"/>
		<updated>2022-12-06T02:43:24Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG|800px]]&lt;br /&gt;
==== Test Case 2 ====&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147196</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147196"/>
		<updated>2022-12-06T02:43:00Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:No_longer_waitlisted.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:No_longer_waitlisted.PNG&amp;diff=147195</id>
		<title>File:No longer waitlisted.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:No_longer_waitlisted.PNG&amp;diff=147195"/>
		<updated>2022-12-06T02:42:39Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Show student is off waitlist when leaves waitlisted team. E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Show student is off waitlist when leaves waitlisted team. E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147194</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147194"/>
		<updated>2022-12-06T02:34:33Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&amp;lt;br&amp;gt; [[File:Leaving_Team.gif]]&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Leaving_Team.gif&amp;diff=147193</id>
		<title>File:Leaving Team.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Leaving_Team.gif&amp;diff=147193"/>
		<updated>2022-12-06T02:15:11Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Gif of Student 14 leaving team. E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gif of Student 14 leaving team. E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147192</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147192"/>
		<updated>2022-12-06T02:14:31Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|800px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147191</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147191"/>
		<updated>2022-12-06T02:14:16Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147190</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147190"/>
		<updated>2022-12-06T02:14:05Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.PNG|200px|]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147189</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147189"/>
		<updated>2022-12-06T02:13:19Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show_Waitlisted_Topics.png]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147188</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147188"/>
		<updated>2022-12-06T02:12:54Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Clicked on Ensure WaitList&lt;br /&gt;
# Showed Student Signed up for '''Topic1''' and '''Topic2''' &amp;lt;br&amp;gt;[[File:Show Waitlisted Topics.png]]&lt;br /&gt;
# Went to Team View&lt;br /&gt;
# Left Team&lt;br /&gt;
# Went Back to Signup Sheet&lt;br /&gt;
''Shows Student is no longer on any waitlists''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Show_Waitlisted_Topics.PNG&amp;diff=147187</id>
		<title>File:Show Waitlisted Topics.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Show_Waitlisted_Topics.PNG&amp;diff=147187"/>
		<updated>2022-12-06T02:12:14Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Shows the student view of topics. E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Shows the student view of topics. E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147186</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147186"/>
		<updated>2022-12-06T02:05:51Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Test Case 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
==== Test Case 1 ====&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147185</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147185"/>
		<updated>2022-12-06T02:05:29Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Manual UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Ensure Waitlists)&amp;lt;br&amp;gt; [[File:Clicking_on_Assignment.gif]]&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Test Case 1 ==&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Clicking_on_Assignment.gif&amp;diff=147184</id>
		<title>File:Clicking on Assignment.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Clicking_on_Assignment.gif&amp;diff=147184"/>
		<updated>2022-12-06T02:02:45Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Shows students view of clicking on an assignment. E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Shows students view of clicking on an assignment. E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147183</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147183"/>
		<updated>2022-12-06T02:01:51Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Manual UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147182</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147182"/>
		<updated>2022-12-06T02:01:29Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Manual UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif|400px|]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147181</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147181"/>
		<updated>2022-12-06T02:01:12Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Manual UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&amp;lt;br&amp;gt; [[File:Logging_in_as_Student.gif|200px|]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147180</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147180"/>
		<updated>2022-12-06T02:00:24Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Manual UI Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student [[File:Logging_in_as_Student.gif]]&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Logging_in_as_Student.gif&amp;diff=147179</id>
		<title>File:Logging in as Student.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Logging_in_as_Student.gif&amp;diff=147179"/>
		<updated>2022-12-06T01:58:55Z</updated>

		<summary type="html">&lt;p&gt;Naydt: Gif of logging in as student for E2281&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gif of logging in as student for E2281&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147090</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147090"/>
		<updated>2022-12-05T20:59:46Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Our goal was to create a simple waitlist functionality that would allow teams to signup for topics that are currently full and remain waitlisted until the topic is made available or they signup for a different topic. We accomplished this using by creating a ''WaitlistTeam'' class that would take a team's '''team_id''' and the '''topic_id''' for the topic they wanted and would store them on the database. Then if a topic became available, if a waitlist existed it would assign the first team on the waitlist to the topic, then cancel all outstanding waitlists that the '''team_id''' had for that particular assignment. Our code was tested meticulously in the UI to confirm that no edge cases broke the system, and even automated a few tests using the RSPEC functionality.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147089</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147089"/>
		<updated>2022-12-05T20:50:04Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* RSPEC Test Cases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/models/waitlist_team_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/waitlist_team_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
While most of the functionalities will be inherited from the queue class, a few important functionalities must still be added. The implementation, while rather simple, will still require a good bit of work in order to ensure that is will be ready to be merged. Our intent is to fully test functionalities not inherited from the queue class, in order to properly ensure that the waitlist can be reimplemented.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147088</id>
		<title>CSC/ECE 517 Fall 2022 - E2281. Reimplement Waitlists</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2022_-_E2281._Reimplement_Waitlists&amp;diff=147088"/>
		<updated>2022-12-05T20:35:55Z</updated>

		<summary type="html">&lt;p&gt;Naydt: /* RSPEC Test Cases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Topic Overview &amp;amp; Prior Work ==&lt;br /&gt;
=== Feature Overview ===&lt;br /&gt;
&lt;br /&gt;
[https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Spring_2022_-_E2240._Re-write_waitlist_functionality E2240] contains detailed information on the previous team's work with this feature.&lt;br /&gt;
&lt;br /&gt;
'''A summary of the desired functionality is presented below:'''&lt;br /&gt;
&lt;br /&gt;
Any instructor or TA can sign students up for a topic. Students are able to sign themselves up for a topic.&lt;br /&gt;
If the topic is full then the team will be put on a queue or &amp;quot;waitlist&amp;quot; for the topic. If the current team&lt;br /&gt;
holding that topic drops the topic, then the team at the top of the waitlist will be assigned the topic.&lt;br /&gt;
&lt;br /&gt;
'''Our Concerns with Current Functionality'''&lt;br /&gt;
&lt;br /&gt;
* What if a team is currently assigned a different topic and waitlisted for a topic that is now available? ''Currently assigned a topic, drop from all other waitlists''&lt;br /&gt;
* How many topics can a student be waitlisted for? ''As many as needed''&lt;br /&gt;
* How are students notified that they were assigned a new topic? ''Currently no functionality exists in expertiza''&lt;br /&gt;
&lt;br /&gt;
=== Comments on why E2240, was not merged ===&lt;br /&gt;
# The code for the waitlist is distributed all over the application, which is something could have been placed into a single controller and called through other files&lt;br /&gt;
# Although manual testing looked solid, there were not enough automated test cases to back their functionality.&lt;br /&gt;
# Too many class methods.&lt;br /&gt;
# The code does not follow ruby style design.&lt;br /&gt;
# Lack of descriptive code comments&lt;br /&gt;
&lt;br /&gt;
=== Files Modified By Previous Team ===&lt;br /&gt;
* ''signed_up_team.rb''&lt;br /&gt;
* ''waitlist.rb''&lt;br /&gt;
* ''sign_up_sheet_controller.rb''&lt;br /&gt;
* ''sign_up_sheet.rb''&lt;br /&gt;
* ''sign_up_topic.rb''&lt;br /&gt;
* ''suggestion_controller.rb''&lt;br /&gt;
* ''invitation.rb''&lt;br /&gt;
&lt;br /&gt;
=== Current Instructor View ===&lt;br /&gt;
The current instructor view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Instructors_Current_View_of_Signup_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Current Student View ===&lt;br /&gt;
The current student view is clean and readable. We see no need to alter the view.&lt;br /&gt;
[[File:Students_Current_View_of_Signup_E2281.jpg|900px|center|]]&lt;br /&gt;
&lt;br /&gt;
== Planned Work ==&lt;br /&gt;
This Project is a total reimplementation of the ''Waitlists'' functionality because the previous implementation failed to be merged for reasons stated above. As such we have a number of things to complete in order for it to be operational. Our plan to accomplish this task is to create a new class for ''Waitlists'' that inherits from Ruby's ''Queue class''. Within this class we will have a model, and controller that will house all of the functionality relating to ''Waitlists''. The further implementation explanation will be below including diagrams.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram === &lt;br /&gt;
[[File:Use_Case_Diagram_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Adding Team ===&lt;br /&gt;
''This is our desired flow for adding a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Adding_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Flow Chart for Removing Team ===&lt;br /&gt;
''This is our desired flow for removing a team to a topic''&lt;br /&gt;
[[File:Flow_Chart_Removing_a_Team_E2281.jpg|center|]]&lt;br /&gt;
&lt;br /&gt;
=== Functions to Implement ===&lt;br /&gt;
====Functionalities for Team====&lt;br /&gt;
* Adding Team to Waitlist&lt;br /&gt;
* Removing Team from Waitlist&lt;br /&gt;
* Removing Team from all Waitlists&lt;br /&gt;
* Checking if Team is on any Waitlists&lt;br /&gt;
* List all Waitlists a Team is on&lt;br /&gt;
====Functionalities for Topic====&lt;br /&gt;
* Checking if Topic has any teams on Waitlist&lt;br /&gt;
* Listing all Teams on Topics Waitlist&lt;br /&gt;
* Locate First Team on Waitlist&lt;br /&gt;
* Convert WaitListTeam into SignedUpTeam&lt;br /&gt;
&lt;br /&gt;
== Our Work ==&lt;br /&gt;
===Model Methods===&lt;br /&gt;
'''add_team_to_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to create a WaitlistTeam instance for a topic, using team's team_id''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_team_to_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    new_waitlist = WaitlistTeam.new&lt;br /&gt;
    new_waitlist.topic_id = topic_id&lt;br /&gt;
    new_waitlist.team_id = team_id&lt;br /&gt;
    if new_waitlist.valid?&lt;br /&gt;
      WaitlistTeam.create(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Team #{team_id} cannot be added to waitlist for the topic #{topic_id}&amp;quot;)&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, new_waitlist.errors.full_messages.join(&amp;quot; &amp;quot;))&lt;br /&gt;
      return false&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''remove_team_from_topic_waitlist''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.remove_team_from_topic_waitlist(team_id, topic_id, user_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.find_by(topic_id: topic_id, team_id: team_id)&lt;br /&gt;
    unless waitlisted_team_for_topic.nil?&lt;br /&gt;
      waitlisted_team_for_topic.destroy&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist for the topic #{topic_id} to be deleted.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''cancel_all_waitlists''' &amp;lt;br&amp;gt;&lt;br /&gt;
''How to remove a WaitlistTeam instance from all topics for a specific team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.cancel_all_waitlists(team_id, assignment_id)&lt;br /&gt;
    waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id, team_id)&lt;br /&gt;
    unless waitlisted_topics.nil?&lt;br /&gt;
      waitlisted_topics.each do |waitlisted_topic|&lt;br /&gt;
        entry = SignedUpTeam.find_by(topic_id: waitlisted_topic.id)&lt;br /&gt;
        next if entry.nil?&lt;br /&gt;
&lt;br /&gt;
        entry.destroy&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Controller Methods===&lt;br /&gt;
'''first_team_in_waitlist_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Determines first team on waitlist based on date/time of entry''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
    waitlisted_team_for_topic = WaitlistTeam.where(topic_id: topic_id).order(&amp;quot;created_at ASC&amp;quot;).first&lt;br /&gt;
    waitlisted_team_for_topic&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''team_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.team_has_any_waitlists?(team_id)&lt;br /&gt;
    WaitlistTeam.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''topic_has_any_waitlists?'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for waitlist entries for topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.topic_has_any_waitlists?(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlists for a team across all topics''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_team(team_id)&lt;br /&gt;
    waitlisted_topics_for_team = get_all_waitlists_for_team team_id&lt;br /&gt;
    if !waitlisted_topics_for_team.nil?&lt;br /&gt;
      waitlisted_topics_for_team.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Team #{team_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''delete_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Deletes all waitlisted teams on a specific topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.delete_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    waitlisted_teams_for_topic = get_all_waitlists_for_topic topic_id&lt;br /&gt;
    if !waitlisted_teams_for_topic.nil?&lt;br /&gt;
      waitlisted_teams_for_topic.destroy_all&lt;br /&gt;
    else&lt;br /&gt;
      ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', user_id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlist topics for a team''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_team(team_id)&lt;br /&gt;
    WaitlistTeam.joins(:topic).select('waitlist_teams.id, topic_name, team_id, topic_id, created_at').where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''get_all_waitlists_for_topic'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Returns list of all waitlisted teams for a topic''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_all_waitlists_for_topic(topic_id)&lt;br /&gt;
    WaitlistTeam.where(topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''count_all_waitlists_pre_topic_per_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches through all topics on an assignment to determine waitlist sizes''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.count_all_waitlists_per_topic_per_assignment(assignment_id)&lt;br /&gt;
    list_of_topic_waitlist_counts = []&lt;br /&gt;
    assignment_topics = Assignment.find(assignment_id).sign_up_topics&lt;br /&gt;
    assignment_topics.each do |topic|&lt;br /&gt;
      list_of_topic_waitlist_counts.append({ topic_id: topic.id, count: topic.waitlist_teams.size })&lt;br /&gt;
    end&lt;br /&gt;
    list_of_topic_waitlist_counts&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''find_waitlisted_teams_for_assignment'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Searches database for all waitlisted teams for specific assignment''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.find_waitlisted_teams_for_assignment(assignment_id, ip_address = nil)&lt;br /&gt;
    waitlisted_participants = WaitlistTeam.joins('INNER JOIN sign_up_topics ON waitlist_teams.topic_id = sign_up_topics.id')&lt;br /&gt;
                                          .select('waitlist_teams.id as id, sign_up_topics.id as topic_id, sign_up_topics.topic_name as name,&lt;br /&gt;
                                            sign_up_topics.topic_name as team_name_placeholder, sign_up_topics.topic_name as user_name_placeholder,&lt;br /&gt;
                                            waitlist_teams.team_id as team_id')&lt;br /&gt;
                                          .where('sign_up_topics.assignment_id = ?', assignment_id)&lt;br /&gt;
    SignedUpTeam.fill_participant_names waitlisted_participants, ip_address&lt;br /&gt;
    waitlisted_participants&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''check_team_waitlisted_for_topic'''&lt;br /&gt;
''Simple database check to find if waitlisted team exists''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.check_team_waitlisted_for_topic(team_id, topic_id)&lt;br /&gt;
    WaitlistTeam.exists?(team_id: team_id, topic_id: topic_id)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''signup_first_waitlist_team'''&amp;lt;br&amp;gt;&lt;br /&gt;
''Find team at top of queue and converts to SignedUpTeam''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.signup_first_waitlist_team(topic_id)&lt;br /&gt;
    sign_up_waitlist_team = nil&lt;br /&gt;
    ApplicationRecord.transaction do&lt;br /&gt;
      first_waitlist_team = first_team_in_waitlist_for_topic(topic_id)&lt;br /&gt;
      unless first_waitlist_team.blank?&lt;br /&gt;
        sign_up_waitlist_team = SignedUpTeam.new&lt;br /&gt;
        sign_up_waitlist_team.topic_id = first_waitlist_team.topic_id&lt;br /&gt;
        sign_up_waitlist_team.team_id = first_waitlist_team.team_id&lt;br /&gt;
        if sign_up_waitlist_team.valid?&lt;br /&gt;
          sign_up_waitlist_team.is_waitlisted = false&lt;br /&gt;
          sign_up_waitlist_team.save&lt;br /&gt;
          first_waitlist_team.destroy&lt;br /&gt;
          delete_all_waitlists_for_team sign_up_waitlist_team.team_id&lt;br /&gt;
        else&lt;br /&gt;
          ExpertizaLogger.info LoggerMessage.new('WaitlistTeam', session[:user].id, &amp;quot;Cannot find Topic #{topic_id} in waitlist.&amp;quot;)&lt;br /&gt;
          raise ActiveRecord::Rollback&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    sign_up_waitlist_team&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design Strategy ==&lt;br /&gt;
=== Ruby Style Guide Basics ===&lt;br /&gt;
Previous teams were not merged due to failure of following the Ruby Style Guide, so our intent is to ensure we follow all Ruby Style Guidelines. Below we have highlighted which we believe are the most important.&lt;br /&gt;
* '''Indentation''': Each indentation level should be marked using two spaces.&lt;br /&gt;
* '''Line Length''': Each line should contain a maximum of 80 characters.&lt;br /&gt;
* '''End of Line''': Each line should have no trailing whitespace and should use UNIX Style line endings (CRLF).&lt;br /&gt;
* '''Expression''': Each line should only contain one expression.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
The principle simply means &amp;quot;Don't Repeat Yourself&amp;quot;. Which aims to reduce repetition and redundancy in favor of abstraction.&lt;br /&gt;
&lt;br /&gt;
''''' Current/Past Implementation ''''' of the ''WaitLists'' has failed to follow this principle by having similar versions of the same code within all classes that need the waitlist functionality.&lt;br /&gt;
''''' Our Intent ''''' is to take the functionalities of ''WaitLists'' and contain them in a centralized ''WaitLists'' class. From there all classes that need a waitlist can just call from the ''WaitLists'' controller.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
=== Planned Test Cases ===&lt;br /&gt;
*Waitlist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Scenario: Student leaves a waitlisted team &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student leaves a team&lt;br /&gt;
   Then: Student should be removed from all waitlisted topics associated with that team&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes Student from Class &lt;br /&gt;
 Given: Logged in as an Instructor/Admin and Student is on a team by themselves&lt;br /&gt;
  When: Student is dropped from class&lt;br /&gt;
   Then: Team should be removed from all waitlists&lt;br /&gt;
&lt;br /&gt;
Scenario: Student accepts new team invitation &lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Student accepted invitation to join team on a waitlist&lt;br /&gt;
   Then: Student should join team on waitlist&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor/TA Removes a topic&lt;br /&gt;
 Given: Logged in as an Student&lt;br /&gt;
  When: Instructor/TA removes a topic containing a waitlist&lt;br /&gt;
   Then: The waitlist should be deleted&lt;br /&gt;
&lt;br /&gt;
Scenario: Team is Assigned a Topic&lt;br /&gt;
 Given: Team is enrolled in multiple waitlists&lt;br /&gt;
  When: Team is assigned topic&lt;br /&gt;
   Then: Team should be dropped from all other waitlists within that project&lt;br /&gt;
&lt;br /&gt;
Scenario: Team Attempts to Join Unavailable Topic&lt;br /&gt;
 Given: Topic is Full and Waitlist is Disabled&lt;br /&gt;
  When: A Team attempts to enroll in the topic&lt;br /&gt;
   Then: Error to raise explaining that &amp;quot;The Topic is Full and Waitlist is Disabled&amp;quot; &lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Waitlist for a Topic&lt;br /&gt;
 Given: A Topic has a waitlist filled with teams&lt;br /&gt;
  When: An Instructor attempted to view the waitlist&lt;br /&gt;
   Then: A List of the Waitlisted teams in order on queue should be returned&lt;br /&gt;
&lt;br /&gt;
Scenario: Instructor Views Topics Waitlist by a Team&lt;br /&gt;
 Given: A Team is Waitlisted for multiple topics for a project&lt;br /&gt;
  When: An Instructor attempted to view which topics&lt;br /&gt;
   Then: A List of the Waitlisted topics should be returned&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RSPEC Test Cases ===&lt;br /&gt;
'''Model Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeam' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds and removes a team from the topic waitlist' do&lt;br /&gt;
      expect(WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'cannot remove a team that does not exist from the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)).to be_truthy&lt;br /&gt;
      expect(WaitlistTeam.remove_team_from_topic_waitlist(waitlist_team1.team_id, waitlist_team2.topic_id,1)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Controller Tests'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  describe 'CRUD WaitlistTeamController' do&lt;br /&gt;
    before(:each) do&lt;br /&gt;
      allow(waitlist_team1).to receive(:topic_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team1).to receive(:team_id).and_return(1)&lt;br /&gt;
      allow(waitlist_team2).to receive(:topic_id).and_return(2)&lt;br /&gt;
      allow(waitlist_team2).to receive(:team_id).and_return(2)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'adds first waitlist team in the topic waitlist' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      signed_up_team = WaitlistTeamController.signup_first_waitlist_team(1)&lt;br /&gt;
      expect(signed_up_team).to be_instance_of(SignedUpTeam) or  expect(signed_up_team).to be_nil&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if team does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.team_has_any_waitlists?(waitlist_team1.team_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check if topic does not has any waitlists' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.topic_has_any_waitlists?(waitlist_team1.topic_id)).to be_falsey&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a team' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_team(waitlist_team1.team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'check and delete all waitlists for a topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.delete_all_waitlists_for_topic(waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    it 'verify team waitlisted for topic' do&lt;br /&gt;
      WaitlistTeam.add_team_to_topic_waitlist(waitlist_team1.team_id, waitlist_team1.topic_id,1)&lt;br /&gt;
      expect(WaitlistTeamController.check_team_waitlisted_for_topic(waitlist_team1.team_id, waitlist_team1.topic_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Manual UI Testing ===&lt;br /&gt;
''''' Testing as Student '''''&lt;br /&gt;
# Login as Student&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Click the Green Check Mark under the Actions Column to add a topic (for testing choose an available topic)&lt;br /&gt;
# Ensure when Student is added to Topic that the Available Slots decrements &lt;br /&gt;
# To ensure the Waitlist works, login as another student (Follow steps 1-5). For step 5 choose the same topic that you chose with the other student&lt;br /&gt;
# Ensure this student should now be added to the waitlist&lt;br /&gt;
# Now log back in as the original student and navigate back to the signup sheet&lt;br /&gt;
# Now drop your topic. ''This should cause the available slots to remain the same and only the waitlist to decrement, because the student on the waitlist should've been added to the topic''&lt;br /&gt;
# Now log back in a the second student an ensure you are assigned the topic&lt;br /&gt;
&lt;br /&gt;
''''' Testing as Instructor'''''&lt;br /&gt;
# Login as Instructor&lt;br /&gt;
# Click on Assignments&lt;br /&gt;
# Find an Assignment with a Signup Sheet (ex. Final project (and design doc))&lt;br /&gt;
# Click Signup Sheet&lt;br /&gt;
# Begin by adding a Student (we will call them Student A) to an open topic&lt;br /&gt;
# Then add another Student (we will call them Student B) to the same topic. ''Student B should've been added to the waitlist''&lt;br /&gt;
# Now remove Student A from the topic. ''Student B should now be assigned the topic and the waitlist should've decremented''&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
While most of the functionalities will be inherited from the queue class, a few important functionalities must still be added. The implementation, while rather simple, will still require a good bit of work in order to ensure that is will be ready to be merged. Our intent is to fully test functionalities not inherited from the queue class, in order to properly ensure that the waitlist can be reimplemented.&lt;br /&gt;
&lt;br /&gt;
== Useful Links ==&lt;br /&gt;
[https://github.com/hss69017/expertiza-E2281 Our Github Forked Repo] &amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/expertiza/expertiza/pull/2485 Our Pull Request]&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
=== Students ===&lt;br /&gt;
*Nick Aydt (''naydt'')&lt;br /&gt;
*Nagaraj Madamshetti (''nmadams'')&lt;br /&gt;
*Rohan Shiveshwarkar (''rsshives'')&lt;br /&gt;
*Gun Ju Im (''gim'')&lt;br /&gt;
=== Mentor ===&lt;br /&gt;
*Naman Shrimali (''nshrima'')&lt;/div&gt;</summary>
		<author><name>Naydt</name></author>
	</entry>
</feed>