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 14 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
87 changes: 87 additions & 0 deletions app/controllers/api/v1/project_topics_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
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
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
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

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

# DELETE /project_topics
# Deletes one or more project topics associated with an assignment.
# If `assignment_id` or `topic_ids` are missing, appropriate validations are handled.
# Deletes the topics and returns a success message if successful or error messages otherwise.
def destroy
# Check if the assignment ID is provided
if params[:assignment_id].nil?
render json: { message: 'Assignment ID is required!' }, status: :unprocessable_entity
# Determine which topics to delete based on the provided parameters
elsif params[:topic_ids].nil?
# If no specific topic IDs are provided, fetch all topics for the assignment
@project_topics = ProjectTopic.where(assignment_id: params[:assignment_id])
else
# Fetch the specified topics for the assignment
@project_topics = ProjectTopic.where(assignment_id: params[:assignment_id], topic_identifier: params[:topic_ids])
end

# Attempt to delete the topics and return the appropriate response
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

# Callback to set the @project_topic instance variable.
# This method is executed before certain actions (via `before_action`) to load the project topic.
# If the topic is not found, it raises an ActiveRecord::RecordNotFound exception.
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.

20 changes: 10 additions & 10 deletions app/controllers/api/v1/signed_up_teams_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
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 +27,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,16 +37,14 @@ 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)
# @teams_user = TeamsUser.where(user_id: user_id).first
# team_id = @teams_user.team_id
assignment_id = params[:assignment_id]
team_id = SignedUpTeam.get_team_id(user_id, assignment_id)
@signed_up_team = SignedUpTeam.create_signed_up_team(topic_id, team_id)
# create(topic_id, team_id)
if @signed_up_team
render json: { message: "Signed up team successful!" }, status: :created
else
Expand All @@ -66,6 +64,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
95 changes: 95 additions & 0 deletions app/models/project_topic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
class ProjectTopic < ApplicationRecord
has_many :signed_up_teams, foreign_key: :sign_up_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

# 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_by(sign_up_topic_id: topic_id, team_id: team_id)
ajith05 marked this conversation as resolved.
Show resolved Hide resolved

# 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 longest_waiting_team
SignedUpTeam.where(sign_up_topic_id: self.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 = longest_waiting_team
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 signed_up_teams_for_topic
SignedUpTeam.where(sign_up_topic_id: self.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