diff --git a/app/controllers/api/v1/api_controller.rb b/app/controllers/api/v1/api_controller.rb index 73c51a1..087b455 100644 --- a/app/controllers/api/v1/api_controller.rb +++ b/app/controllers/api/v1/api_controller.rb @@ -20,6 +20,7 @@ module Api rescue_from Api::V1::FavoriteAlreadyExistsError, with: :render_unprocessable_entity_response rescue_from Api::V1::NoJobProvidedError, with: :render_unprocessable_entity_response rescue_from Api::V1::TooManySkillsOfTypeError, with: :render_unprocessable_entity_response + rescue_from Api::V1::IncompatibleWeaponForPositionError, with: :render_unprocessable_entity_response rescue_from Api::V1::UnauthorizedError, with: :render_unauthorized_response rescue_from ActionController::ParameterMissing, with: :render_unprocessable_entity_response diff --git a/app/controllers/api/v1/grid_weapons_controller.rb b/app/controllers/api/v1/grid_weapons_controller.rb index a6324bd..8ecb573 100644 --- a/app/controllers/api/v1/grid_weapons_controller.rb +++ b/app/controllers/api/v1/grid_weapons_controller.rb @@ -6,11 +6,45 @@ module Api before_action :set, except: %w[create update_uncap_level destroy] def create + # BUG: I can create grid weapons even when I'm not logged in on an authenticated party party = Party.find(weapon_params[:party_id]) - canonical_weapon = Weapon.find(weapon_params[:weapon_id]) - render_unauthorized_response if current_user && (party.user != current_user) + incoming_weapon = Weapon.find(weapon_params[:weapon_id]) + incoming_weapon.limit + + # Set up conflict_position in case it is used + conflict_position = nil + + if [9, 10, 11].include?(weapon_params[:position].to_i) && ![11, 16, 17, 28, 29].include?(incoming_weapon.series) + raise Api::V1::IncompatibleWeaponForPositionError.new(weapon: incoming_weapon) + end + + # 1. If the weapon has a limit + # 2. If the weapon does not match a weapon already in grid + # 3. If the incoming weapon has a limit and other weapons of the same series are in grid + if incoming_weapon.limit && incoming_weapon.limit.positive? + conflict_weapon = party.weapons.find do |weapon| + weapon if incoming_weapon.series == weapon.weapon.series || + ([2, 3].include?(incoming_weapon.series) && [2, 3].include?(weapon.weapon.series)) + end + + if conflict_weapon + if conflict_weapon.weapon.id != incoming_weapon.id + return render json: ConflictBlueprint.render(nil, view: :weapons, + conflict_weapons: [conflict_weapon], + incoming_weapon: incoming_weapon, + incoming_position: weapon_params[:position]) + else + # Destroy the original grid weapon + # TODO: Use conflict_position to alert the client that that position has changed + conflict_position = conflict_weapon.position + GridWeapon.destroy(conflict_weapon.id) + end + end + end + + # Destroy the existing item before adding a new one if (grid_weapon = GridWeapon.where( party_id: party.id, position: weapon_params[:position] @@ -18,14 +52,44 @@ module Api GridWeapon.destroy(grid_weapon.id) end - weapon = GridWeapon.create!(weapon_params.merge(party_id: party.id, weapon_id: canonical_weapon.id)) + weapon = GridWeapon.new + weapon.attributes = weapon_params.merge(party_id: party.id, weapon_id: incoming_weapon.id) if weapon.position == -1 party.element = weapon.weapon.element party.save! end - render json: GridWeaponBlueprint.render(weapon, view: :full), status: :created if weapon.save! + # Render the new weapon and any weapons changed + return unless weapon.save! + + render json: GridWeaponBlueprint.render(weapon, view: :full, + root: :grid_weapon, + meta: { + replaced: conflict_position + }), + status: :created + end + + def resolve + incoming = Weapon.find(resolve_params[:incoming]) + conflicting = resolve_params[:conflicting].map { |id| GridWeapon.find(id) } + party = conflicting.first.party + + # Destroy each conflicting weapon + conflicting.each { |weapon| GridWeapon.destroy(weapon.id) } + + # Destroy the weapon at the desired position if it exists + existing_weapon = GridWeapon.where(party: party.id, position: resolve_params[:position]).first + GridWeapon.destroy(existing_weapon.id) if existing_weapon + + uncap_level = 3 + uncap_level = 4 if incoming.flb + uncap_level = 5 if incoming.ulb + + weapon = GridWeapon.create!(party_id: party.id, weapon_id: incoming.id, + position: resolve_params[:position], uncap_level: uncap_level) + render json: GridWeaponBlueprint.render(weapon, view: :nested), status: :created if weapon.save! end def update @@ -71,6 +135,10 @@ module Api :awakening_type, :awakening_level ) end + + def resolve_params + params.require(:resolve).permit(:position, :incoming, conflicting: []) + end end end end diff --git a/app/controllers/api/v1/search_controller.rb b/app/controllers/api/v1/search_controller.rb index e317c96..9792109 100644 --- a/app/controllers/api/v1/search_controller.rb +++ b/app/controllers/api/v1/search_controller.rb @@ -57,6 +57,7 @@ module Api filters['proficiency1'] end conditions[:series] = filters['series'] unless filters['series'].blank? || filters['series'].empty? + conditions[:extra] = filters['extra'] unless filters['extra'].blank? end weapons = if search_params[:query].present? && search_params[:query].length >= 2 @@ -89,6 +90,7 @@ module Api if filters conditions[:rarity] = filters['rarity'] unless filters['rarity'].blank? || filters['rarity'].empty? conditions[:element] = filters['element'] unless filters['element'].blank? || filters['element'].empty? + conditions[:subaura] = filters['subaura'] unless filters['subaura'].blank? end summons = if search_params[:query].present? && search_params[:query].length >= 2 diff --git a/app/errors/api/v1/incompatible_weapon_for_position_error.rb b/app/errors/api/v1/incompatible_weapon_for_position_error.rb new file mode 100644 index 0000000..48ab067 --- /dev/null +++ b/app/errors/api/v1/incompatible_weapon_for_position_error.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Api + module V1 + class IncompatibleWeaponForPositionError < GranblueError + def http_status + 422 + end + + def code + 'incompatible_weapon_for_position' + end + + def message + 'A weapon of this series cannot be added to Additional Weapons' + end + + def to_hash + { + message: message, + code: code, + weapon: @data[:weapon] + } + end + end + end +end diff --git a/config/routes.rb b/config/routes.rb index de3e5f7..91094d7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -41,6 +41,7 @@ Rails.application.routes.draw do delete 'characters', to: 'grid_characters#destroy' post 'weapons', to: 'grid_weapons#create' + post 'weapons/resolve', to: 'grid_weapons#resolve' post 'weapons/update_uncap', to: 'grid_weapons#update_uncap_level' delete 'weapons', to: 'grid_weapons#destroy'