Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2473. Reimplement sign_up_topic.rb as project_topic.rb #125

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/controllers/api/v1/assignments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ def show_assignment_details
end
end

# check if assignment has topics
# has_topics is set to true if there is SignUpTopic corresponding to the input assignment id
# Checks if an assignment has associated topics.
# If the assignment is found, it returns a boolean indicating whether topics exist for it.
# If the assignment is not found, it returns an error message.
def has_topics
assignment = Assignment.find_by(id: params[:assignment_id])
if assignment.nil?
Expand Down
84 changes: 84 additions & 0 deletions app/controllers/api/v1/project_topics_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
class Api::V1::ProjectTopicsController < ApplicationController
before_action :set_project_topic, only: %i[ show update ]

# GET /api/v1/project_topics?assignment_id=&topic_ids[]=
# Retrieve ProjectTopics by two query parameters - assignment_id (compulsory) and an array of topic_ids (optional)
def index
if params[:assignment_id].nil?
render json: { message: 'Assignment ID is required!' }, status: :unprocessable_entity
elsif params[:topic_ids].nil?
@project_topics = ProjectTopic.where(assignment_id: params[:assignment_id])
render json: @project_topics, status: :ok
else
@project_topics = ProjectTopic.where(assignment_id: params[:assignment_id], topic_identifier: params[:topic_ids])
render json: @project_topics, status: :ok
end
# render json: {message: 'All selected topics have been loaded successfully.', project_topics: @stopics}, status: 200
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
end

# POST /project_topics
# The create method allows the instructor to create a new topic
# params[:project_topic][:topic_identifier] follows a json format
# The method takes inputs and outputs the if the topic creation was successful.
def create
@project_topic = ProjectTopic.new(project_topic_params)
@assignment = Assignment.find(params[:project_topic][:assignment_id])
@project_topic.micropayment = params[:micropayment] if @assignment.microtask?
if @project_topic.save
# undo_link "The topic: \"#{@project_topic.topic_name}\" has been created successfully. "
render json: { message: "The topic: \"#{@project_topic.topic_name}\" has been created successfully. " }, status: :created
else
render json: { message: @project_topic.errors }, status: :unprocessable_entity
end
end

# PATCH/PUT /project_topics/1
# updates parameters present in project_topic_params.
def update
if @project_topic.update(project_topic_params)
render json: { message: "The topic: \"#{@project_topic.topic_name}\" has been updated successfully. " }, status: 200
else
render json: @project_topic.errors, status: :unprocessable_entity
end
end

# Show a ProjectTopic by ID
def show
render json: @project_topic, status: :ok
end

# Similar to index method, this method destroys ProjectTopics by two query parameters
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
# assignment_id is compulsory.
# topic_ids[] is optional
def destroy
# render json: {message: @project_topic}
# filters topics based on assignment id (required) and topic identifiers (optional)
if params[:assignment_id].nil?
render json: { message: 'Assignment ID is required!' }, status: :unprocessable_entity
elsif params[:topic_ids].nil?
@project_topics = ProjectTopic.where(assignment_id: params[:assignment_id])
# render json: @project_topics, status: :ok
else
@project_topics = ProjectTopic.where(assignment_id: params[:assignment_id], topic_identifier: params[:topic_ids])
# render json: @project_topics, status: :ok
end

if @project_topics.each(&:delete)
render json: { message: "The topic has been deleted successfully. " }, status: :no_content
else
render json: @project_topic.errors, status: :unprocessable_entity
end
end

private

# Use callbacks to share common setup or constraints between actions.
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
def set_project_topic
@project_topic = ProjectTopic.find(params[:id])
end

# Only allow a list of trusted parameters through.
def project_topic_params
params.require(:project_topic).permit(:topic_identifier, :category, :topic_name, :max_choosers, :assignment_id)
end
end
84 changes: 0 additions & 84 deletions app/controllers/api/v1/sign_up_topics_controller.rb

This file was deleted.

16 changes: 10 additions & 6 deletions app/controllers/api/v1/signed_up_teams_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
class Api::V1::SignedUpTeamsController < ApplicationController

# Returns signed up topics using sign_up_topic assignment id
# Retrieves sign_up_topic using topic_id as a parameter
# Returns signed up topics using project_topic assignment id
# Retrieves project_topic using topic_id as a parameter
def index
# puts params[:topic_id]
@sign_up_topic = SignUpTopic.find(params[:topic_id])
@signed_up_team = SignedUpTeam.find_team_participants(@sign_up_topic.assignment_id)
@project_topic = ProjectTopic.find(params[:topic_id])
@signed_up_team = SignedUpTeam.find_team_participants(@project_topic.assignment_id)
render json: @signed_up_team
end

Expand All @@ -28,6 +28,7 @@ def sign_up
team_id = params[:team_id]
topic_id = params[:topic_id]
@signed_up_team = SignedUpTeam.create_signed_up_team(topic_id, team_id)
@signed_up_team.save
if @signed_up_team
render json: { message: "Signed up team successful!" }, status: :created
else
Expand All @@ -37,12 +38,13 @@ def sign_up

# Method for signing up as student
# Params : topic_id
# Get team_id using model method get_team_participants
# Get team_id using model method get_team_id
# Call create_signed_up_team Model method
def sign_up_student
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
user_id = params[:user_id]
topic_id = params[:topic_id]
team_id = SignedUpTeam.get_team_participants(user_id)
assignment_id = params[:assignment_id]
team_id = SignedUpTeam.get_team_id(user_id, assignment_id)
# @teams_user = TeamsUser.where(user_id: user_id).first
# team_id = @teams_user.team_id
@signed_up_team = SignedUpTeam.create_signed_up_team(topic_id, team_id)
Expand All @@ -66,6 +68,8 @@ def destroy

private

# Strong parameters method for permitting attributes related to signed-up teams.
# Ensures only the allowed parameters are passed for creating or updating a signed-up team.
def signed_up_teams_params
params.require(:signed_up_team).permit(:topic_id, :team_id, :is_waitlisted, :preference_priority_number)
end
Expand Down
4 changes: 2 additions & 2 deletions app/models/assignment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Assignment < ApplicationRecord
has_many :questionnaires, through: :assignment_questionnaires
has_many :response_maps, foreign_key: 'reviewed_object_id', dependent: :destroy, inverse_of: :assignment
has_many :review_mappings, class_name: 'ReviewResponseMap', foreign_key: 'reviewed_object_id', dependent: :destroy, inverse_of: :assignment
has_many :sign_up_topics , class_name: 'SignUpTopic', foreign_key: 'assignment_id', dependent: :destroy
has_many :project_topics , class_name: 'ProjectTopic', foreign_key: 'assignment_id', dependent: :destroy
belongs_to :course, optional: true
belongs_to :instructor, class_name: 'User', inverse_of: :assignments

Expand Down Expand Up @@ -137,7 +137,7 @@ def staggered_and_no_topic?(topic_id)
#This method return the value of the has_topics field for the given assignment object.
# has_topics is of boolean type and is set true if there is any topic associated with the assignment.
def topics?
@has_topics ||= sign_up_topics.any?
@has_topics ||= project_topics.any?
end

#This method return if the given assignment is a team assignment.
Expand Down
2 changes: 1 addition & 1 deletion app/models/bookmark.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Bookmark < ApplicationRecord
belongs_to :user
# belongs_to :topic, class_name: "SignUpTopic"
# belongs_to :topic, class_name: "ProjectTopic"
has_many :bookmark_ratings
validates :url, presence: true
validates :title, presence: true
Expand Down
102 changes: 102 additions & 0 deletions app/models/project_topic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
class ProjectTopic < ApplicationRecord
has_many :signed_up_teams, foreign_key: 'topic_id', dependent: :destroy
has_many :teams, through: :signed_up_teams # list all teams choose this topic, no matter in waitlist or not
has_many :assignment_questionnaires, class_name: 'AssignmentQuestionnaire', foreign_key: 'topic_id', dependent: :destroy
belongs_to :assignment

# max_choosers should be a non-negative integer
validates :max_choosers, numericality: { only_integer: true, greater_than_or_equal_to: 0 }

# Checks if there are any slots currently available
# Returns true if the number of available slots is greater than 0, otherwise false
def slot_available?
current_available_slots > 0
end

def find_team_project_topics(assignment_id, team_id)
SignedUpTeam.joins('INNER JOIN project_topics ON signed_up_teams.sign_up_topic_id = project_topics.id')
.select('project_topics.id as topic_id, project_topics.topic_name as topic_name, signed_up_teams.is_waitlisted as is_waitlisted,
signed_up_teams.preference_priority_number as preference_priority_number')
.where('project_topics.assignment_id = ? and signed_up_teams.team_id = ?', assignment_id, team_id)
end

# Assigns the current topic to a team by updating the provided sign-up record.
# Marks the sign-up as not waitlisted and associates it with the current topic.
def assign_topic_to_team(new_sign_up)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
new_sign_up.update(is_waitlisted: false, sign_up_topic_id: self.id)
end

# Adds a new sign-up to the waitlist by updating the sign-up record.
# Marks the sign-up as waitlisted and associates it with the current topic.
def save_waitlist_entry(new_sign_up)
new_sign_up.update(is_waitlisted: true, sign_up_topic_id: self.id)
end

# Signs up a team for the current topic.
# Checks if the team is already signed up, and if so, ensures they are not waitlisted.
# If a slot is available, assigns the topic to the team; otherwise, adds the team to the waitlist.
def sign_up_team(team_id)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
topic_id = self.id
ajith05 marked this conversation as resolved.
Show resolved Hide resolved

# Check if the team has already signed up for this topic
existing_sign_up = SignedUpTeam.find_first_existing_sign_up(topic_id: topic_id, team_id: team_id)

# If the team is already signed up and not waitlisted, return false
if !existing_sign_up.nil? && !existing_sign_up.is_waitlisted
return false
end

# Create a new sign-up entry for the team
new_sign_up = SignedUpTeam.new(sign_up_topic_id: topic_id, team_id: team_id)

# If there are available slots, assign the topic to the team and remove the team from the waitlist
if slot_available?
assign_topic_to_team(new_sign_up)
result = SignedUpTeam.drop_off_team_waitlists(team_id)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
else
# If no slots are available, add the team to the waitlist
result = save_waitlist_entry(new_sign_up)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
end

result
end

# Retrieves the team that has been waitlisted the longest for a given topic.
# The team is selected based on the earliest created waitlist entry.
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
def self.longest_waiting_team(topic_id)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
SignedUpTeam.where(sign_up_topic_id: topic_id, is_waitlisted: true).order(:created_at).first
end

# Removes a team from the current topic.
# If the team is not waitlisted, the next waitlisted team is reassigned to the topic.
# The team is then destroyed (removed from the sign-up record).
def drop_team_from_topic(team_id)
# Find the sign-up record for the team for this topic
signed_up_team = SignedUpTeam.find_by(team_id: team_id, sign_up_topic_id: self.id)
return nil unless signed_up_team

# If the team is not waitlisted, reassign the topic to the next waitlisted team
unless signed_up_team.is_waitlisted
next_waitlisted_team = ProjectTopic.longest_waiting_team(self.id)
next_waitlisted_team&.reassign_topic(self.id)
end

# Destroy the sign-up record for the team
signed_up_team.destroy
end

# Retrieves all teams that are signed up for a given topic.
def self.signed_up_teams_for_topic(topic_id)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved
SignedUpTeam.where(sign_up_topic_id: topic_id)
end

# Calculates the number of available slots for a topic.
# It checks how many teams have already chosen the topic and subtracts that from the maximum allowed choosers.
def current_available_slots
# Find the teams who have already chosen the topic and are not waitlisted
teams_who_chose_the_topic = SignedUpTeam.where(sign_up_topic_id: self.id, is_waitlisted: false)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved

# Compute the number of available slots and return
self.max_choosers.to_i - teams_who_chose_the_topic.size
end
end
6 changes: 0 additions & 6 deletions app/models/sign_up_topic.rb

This file was deleted.

Loading