Move logic to JobsController

It was getting too heavy to keep in PartiesController
This commit is contained in:
Justin Edmund 2022-12-03 11:45:00 -08:00
parent bd33ee44fc
commit ec3b42101b
4 changed files with 232 additions and 142 deletions

View file

@ -1,6 +1,152 @@
class Api::V1::JobsController < Api::V1::ApiController
def all
@jobs = Job.all()
render :all, status: :ok
before_action :set, only: %w[update_job update_job_skills]
def all
@jobs = Job.all()
render :all, status: :ok
end
def update_job
raise NoJobProvidedError unless job_params[:job_id].present?
# Extract job and find its main skills
job = Job.find(job_params[:job_id])
main_skills = JobSkill.where(job: job.id, main: true)
# Update the party
@party.job = job
main_skills.each_with_index do |skill, index|
@party["skill#{index}_id"] = skill.id
end
# Check for incompatible Base and EMP skills
%w[skill1_id skill2_id skill3_id].each do |key|
@party[key] = nil if mismatched_skill(@party.job, JobSkill.find(@party[key]))
end
render :update, status: :ok if @party.save!
end
def update_job_skills
throw NoJobSkillProvidedError unless job_params[:skill1_id] || job_params[:skill2_id] || job_params[:skill3_id]
# Determine which incoming keys contain new skills
skill_keys = %w[skill1_id skill2_id skill3_id]
new_skill_keys = job_params.keys.select { |key| skill_keys.include?(key) }
# If there are new skills, merge them with the existing skills
unless new_skill_keys.empty?
existing_skills = {
1 => @party.skill1,
2 => @party.skill2,
3 => @party.skill3
}
new_skill_ids = new_skill_keys.map { |key| job_params[key] }
new_skill_ids.map do |id|
skill = JobSkill.find(id)
if mismatched_skill(@party.job, skill)
raise Api::V1::IncompatibleSkillError.new(job: @party.job, skill: skill)
end
end
positions = extract_positions_from_keys(new_skill_keys)
new_skills = merge_skills_with_existing_skills(existing_skills, new_skill_ids, positions)
new_skill_ids = new_skills.each_with_object({}) do |(index, skill), memo|
memo["skill#{index}_id"] = skill.id
end
@party.attributes = new_skill_ids
end
render :update, status: :ok if @party.save!
end
private
def merge_skills_with_existing_skills(
existing_skills,
new_skill_ids,
positions
)
new_skills = new_skill_ids.map { |id| JobSkill.find(id) }
new_skills.each_with_index do |skill, index|
existing_skills = place_skill_in_existing_skills(existing_skills, skill, positions[index])
end
existing_skills
end
def place_skill_in_existing_skills(existing_skills, skill, position)
old_position = existing_skills.key(existing_skills.detect { |_, value| value.id == skill.id })
if old_position
existing_skills = swap_skills_at_position(existing_skills, skill, position, old_position[0])
else
# Test if skill will exceed allowances of skill types
skill_type = skill.sub ? 'sub' : 'emp'
unless can_add_skill_of_type(existing_skills, position, skill_type)
raise Api::V1::TooManySkillsOfTypeError.new(skill_type: skill_type)
end
existing_skills[position] = skill
end
existing_skills
end
def swap_skills_at_position(skills, new_skill, position1, position2)
# Check desired position for a skill
displaced_skill = skills[position1] if skills[position1].present?
# Put skill in new position
skills[position1] = new_skill
skills[position2] = displaced_skill
skills
end
def extract_positions_from_keys(keys)
# Subtract by 1 because we won't operate on the 0th skill, so we don't pass it
keys.map { |key| key['skill'.length].to_i }
end
def can_add_skill_of_type(skills, position, type)
max_skill_of_type = 2
skills_to_check = skills.reject { |key, _| key == position }
sum = skills_to_check.values.count { |value| value.send(type) }
sum + 1 <= max_skill_of_type
end
def mismatched_skill(job, skill)
mismatched_emp = (skill.job.id != job.id) && skill.emp
mismatched_base = (job.row != 'ex2' || skill.job.base_job.id != job.base_job.id) && skill.base
if %w[4 5 ex2].include?(job.row)
true if mismatched_emp || mismatched_base
elsif mismatched_emp
true
else
false
end
end
def set
@party = Party.where('id = ?', params[:id]).first
end
def job_params
params.require(:party).permit(
:job_id,
:skill0_id,
:skill1_id,
:skill2_id,
:skill3_id
)
end
end

View file

@ -5,7 +5,13 @@ class Api::V1::PartiesController < Api::V1::ApiController
def create
@party = Party.new(shortcode: random_string)
@party.extra = party_params["extra"]
@party.extra = party_params['extra']
job = Job.find(party_params['job_id']) if party_params['job_id'].present?
job_skills = JobSkill.where(job: job.id, main: true)
job_skills.each_with_index do |skill, index|
@party["skill#{index}_id"] = skill.id
end
@party.user = current_user if current_user
@ -21,28 +27,6 @@ class Api::V1::PartiesController < Api::V1::ApiController
render_unauthorized_response
else
@party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id)
ap party_params
# Determine which incoming keys contain new skills
skill_keys = %w[skill1_id skill2_id skill3_id]
if (party_params.keys & skill_keys).any?
new_skill_keys = party_params.keys - skill_keys
# If there are new skills, merge them with the existing skills
unless new_skill_keys.empty?
existing_skills = [@party.skill1, @party.skill2, @party.skill3]
new_skill_ids = new_skill_keys.map { |key| party_params[key] }
positions = extract_positions_from_keys(new_skill_keys)
new_skills = merge_skills_with_existing_skills(existing_skills, new_skill_ids, positions)
new_skill_ids = {}
new_skills.each_with_index do |skill, index|
new_skill_ids["skill#{index + 1}_id"] = skill.id
end
@party.attributes = new_skill_ids
end
end
end
render :update, status: :ok if @party.save!
@ -121,8 +105,8 @@ class Api::V1::PartiesController < Api::V1::ApiController
def destroy
if @party.user != current_user
render_unauthorized_response
else
render :destroyed, status: :ok if @party.destroy
elsif @party.destroy
render :destroyed, status: :ok
end
end
@ -143,69 +127,6 @@ class Api::V1::PartiesController < Api::V1::ApiController
private
def merge_skills_with_existing_skills(
existing_skills,
new_skill_ids,
positions
)
new_skills = []
new_skill_ids.each { |id| new_skills << JobSkill.find(id) }
progress = existing_skills
new_skills.each do |skill, index|
progress = place_skill_in_existing_skills(progress, skill, positions[0])
end
progress
end
def place_skill_in_existing_skills(existing_skills, skill, position)
old_position = existing_skills.index { |x| x.id == skill.id }
if old_position
existing_skills = swap_skills_at_position(existing_skills, skill, position, old_position)
else
# Test if skill will exceed allowances of skill types
skill_type = skill.sub ? 'sub' : 'emp'
unless can_add_skill_of_type(existing_skills, position, skill_type)
raise Api::V1::TooManySkillsOfTypeError.new(skill_type: skill_type)
end
existing_skills[position] = skill
end
existing_skills
end
def swap_skills_at_position(skills, new_skill, position1, position2)
# Check desired position for a skill
displaced_skill = skills[position1] if skills[position1].present?
# Put skill in new position
skills[position1] = new_skill
skills[position2] = displaced_skill
skills
end
def can_add_skill_of_type(skills, position, type)
max_skill_of_type = 2
count = skills.reject
.with_index { |_el, index| index == position }
.reduce(0) do |sum, skill|
sum + 1 if type == 'emp' && skill.emp
sum + 1 if type == 'sub' && skill.sub
end
count + 1 <= max_skill_of_type
end
def extract_positions_from_keys(keys)
# Subtract by 1 because we won't operate on the 0th skill, so we don't pass it
keys.map { |key| key["skill".length].to_i - 1 }
end
def random_string
numChars = 6
o = [("a".."z"), ("A".."Z"), (0..9)].map(&:to_a).flatten

View file

@ -0,0 +1,20 @@
object @party
attributes :id, :user_id, :shortcode
node :is_extra do |p|
p.extra
end
node :job do |p|
partial("jobs/base", object: p.job)
end
node :job_skills do |p|
{
"0" => partial("job_skills/base", object: p.skill0),
"1" => partial("job_skills/base", object: p.skill1),
"2" => partial("job_skills/base", object: p.skill2),
"3" => partial("job_skills/base", object: p.skill3),
}
end

View file

@ -1,54 +1,57 @@
Rails.application.routes.draw do
use_doorkeeper do
controllers :tokens => 'tokens'
skip_controllers :applications, :authorized_applications
end
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :parties, only: [:index, :create, :update, :destroy]
resources :users, only: [:create, :update, :show]
resources :grid_weapons, only: [:update]
resources :favorites, only: [:create]
get 'users/info/:id', to: 'users#info'
get 'parties/favorites', to: 'parties#favorites'
get 'parties/:id', to: 'parties#show'
get 'parties/:id/weapons', to: 'parties#weapons'
get 'parties/:id/summons', to: 'parties#summons'
get 'parties/:id/characters', to: 'parties#characters'
post 'check/email', to: 'users#check_email'
post 'check/username', to: 'users#check_username'
post 'search/characters', to: 'search#characters'
post 'search/weapons', to: 'search#weapons'
post 'search/summons', to: 'search#summons'
post 'search/job_skills', to: 'search#job_skills'
get 'jobs', to: 'jobs#all'
get 'jobs/skills', to: 'job_skills#all'
get 'jobs/:id/skills', to: 'job_skills#job'
get 'raids', to: 'raids#all'
get 'weapon_keys', to: 'weapon_keys#all'
post 'characters', to: 'grid_characters#create'
post 'characters/resolve', to: 'grid_characters#resolve'
post 'characters/update_uncap', to: 'grid_characters#update_uncap_level'
delete 'characters', to: 'grid_characters#destroy'
post 'weapons', to: 'grid_weapons#create'
post 'weapons/update_uncap', to: 'grid_weapons#update_uncap_level'
delete 'weapons', to: 'grid_weapons#destroy'
post 'summons', to: 'grid_summons#create'
post 'summons/update_uncap', to: 'grid_summons#update_uncap_level'
delete 'summons', to: 'grid_summons#destroy'
delete 'favorites', to: 'favorites#destroy'
end
use_doorkeeper do
controllers :tokens => 'tokens'
skip_controllers :applications, :authorized_applications
end
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :parties, only: [:index, :create, :update, :destroy]
resources :users, only: [:create, :update, :show]
resources :grid_weapons, only: [:update]
resources :favorites, only: [:create]
get 'users/info/:id', to: 'users#info'
get 'parties/favorites', to: 'parties#favorites'
get 'parties/:id', to: 'parties#show'
get 'parties/:id/weapons', to: 'parties#weapons'
get 'parties/:id/summons', to: 'parties#summons'
get 'parties/:id/characters', to: 'parties#characters'
put 'parties/:id/job', to: 'jobs#update_job'
put 'parties/:id/job_skills', to: 'jobs#update_job_skills'
post 'check/email', to: 'users#check_email'
post 'check/username', to: 'users#check_username'
post 'search/characters', to: 'search#characters'
post 'search/weapons', to: 'search#weapons'
post 'search/summons', to: 'search#summons'
post 'search/job_skills', to: 'search#job_skills'
get 'jobs', to: 'jobs#all'
get 'jobs/skills', to: 'job_skills#all'
get 'jobs/:id/skills', to: 'job_skills#job'
get 'raids', to: 'raids#all'
get 'weapon_keys', to: 'weapon_keys#all'
post 'characters', to: 'grid_characters#create'
post 'characters/resolve', to: 'grid_characters#resolve'
post 'characters/update_uncap', to: 'grid_characters#update_uncap_level'
delete 'characters', to: 'grid_characters#destroy'
post 'weapons', to: 'grid_weapons#create'
post 'weapons/update_uncap', to: 'grid_weapons#update_uncap_level'
delete 'weapons', to: 'grid_weapons#destroy'
post 'summons', to: 'grid_summons#create'
post 'summons/update_uncap', to: 'grid_summons#update_uncap_level'
delete 'summons', to: 'grid_summons#destroy'
delete 'favorites', to: 'favorites#destroy'
end
end
end