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 15 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.

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

# Implemented by signed_up_team.rb (Model) --> create_signed_up_team
# Implemented by signed_up_team.rb (Model) --> sign_up_team_for_topic
def create; end

# Update signed_up_team using parameters.
Expand All @@ -23,11 +22,12 @@ def update
end

# Sign up using parameters: team_id and topic_id
# Calls model method create_signed_up_team
# Calls model method sign_up_team_for_topic
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 = SignedUpTeam.sign_up_team_for_topic(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
# Call create_signed_up_team Model method
# Get team_id using model method get_team_id_for_user
# Call sign_up_team_for_topic 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
@signed_up_team = SignedUpTeam.create_signed_up_team(topic_id, team_id)
# create(topic_id, team_id)
assignment_id = params[:assignment_id]
team_id = SignedUpTeam.get_team_id_for_user(user_id, assignment_id)
@signed_up_team = SignedUpTeam.sign_up_team_for_topic(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
82 changes: 82 additions & 0 deletions app/models/project_topic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
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

# 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
# Check if the team has already signed up for this topic
team_signup_record = SignedUpTeam.find_by(sign_up_topic_id: self.id, team_id: team_id, is_waitlisted: false)

# If the team is already signed up, return false
if !team_signup_record.nil?
return false
end

# Create a new sign-up entry for the team
new_signup_record = SignedUpTeam.new(sign_up_topic_id: self.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?
new_signup_record.update(is_waitlisted: false, sign_up_topic_id: self.id)
result = SignedUpTeam.drop_off_topic_waitlists(team_id)
else
# If no slots are available, add the team to the waitlist
new_signup_record.update(is_waitlisted: true, sign_up_topic_id: self.id)
end

result
end

# Retrieves the team with the earliest waitlisted record for a given topic.
# The team is determined based on the creation time of the waitlisted record.
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 number of teams who have already chosen the topic and are not waitlisted
# This would give us the number of teams who have been assigned the topic
num_teams_registered = SignedUpTeam.where(sign_up_topic_id: self.id, is_waitlisted: false).size

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

This file was deleted.

Loading