Compare commits

...

5 commits

Author SHA1 Message Date
ed6fc388ac Finish last bugs
We tested to ensure that conflict resolution appears for

* Opus and Draconic
* Draconic and Draconic 2
* Draconic 2 + Opus and Draconic 1
2023-12-26 03:20:45 -08:00
251d7f708e (WIP) Update conflict view rendering
Conflict blueprints should render multiple conflict weapons instead of just one.

Also adds Draconic Weapon Providence series to various places that check series by number
2023-12-05 10:33:30 -08:00
17cdd4cf2c Update grid_weapon.rb
Update conflict detection to:
* Detect Draconic Weapons Providence
* Add multiple weapons to conflicting weapons instead of just one
2023-12-05 10:32:24 -08:00
20b3ec993c Update weapon.rb
* Update to check key compatibility against an array instead of an int
* Add convenience function to check if the weapon is part of a Draconic Weapon series
2023-12-05 10:30:55 -08:00
8f5a4af68f Make weapon key series an array
Draconic Weapons Providence can have original Draconic Weapon keys, but also have a new key that can only be equipped to them. Thanks, Cygames.
2023-12-05 10:30:05 -08:00
10 changed files with 74 additions and 97 deletions

View file

@ -18,8 +18,8 @@ module Api
end end
view :weapons do view :weapons do
field :conflicts, if: ->(_fn, _obj, options) { options.key?(:conflict_weapon) } do |_, options| field :conflicts, if: ->(_fn, _obj, options) { options.key?(:conflict_weapons) } do |_, options|
GridWeaponBlueprint.render_as_hash(options[:conflict_weapon], view: :nested) GridWeaponBlueprint.render_as_hash(options[:conflict_weapons], view: :nested)
end end
field :incoming, if: ->(_fn, _obj, options) { options.key?(:incoming_weapon) } do |_, options| field :incoming, if: ->(_fn, _obj, options) { options.key?(:incoming_weapon) } do |_, options|

View file

@ -15,7 +15,7 @@ module Api
association :weapon_keys, association :weapon_keys,
blueprint: WeaponKeyBlueprint, blueprint: WeaponKeyBlueprint,
if: lambda { |_field_name, w, _options| if: lambda { |_field_name, w, _options|
[2, 3, 17, 24].include?(w.weapon.series) [2, 3, 17, 24, 34].include?(w.weapon.series)
} }
field :ax, if: ->(_field_name, w, _options) { w.weapon.ax } do |w| field :ax, if: ->(_field_name, w, _options) { w.weapon.ax } do |w|

View file

@ -93,7 +93,7 @@ module Api
# Check if the incoming weapon is compatible with the specified position # Check if the incoming weapon is compatible with the specified position
def compatible_with_position?(incoming_weapon, position) def compatible_with_position?(incoming_weapon, position)
false if [9, 10, 11].include?(position.to_i) && ![11, 16, 17, 28, 29].include?(incoming_weapon.series) false if [9, 10, 11].include?(position.to_i) && ![11, 16, 17, 28, 29, 34].include?(incoming_weapon.series)
true true
end end
@ -126,9 +126,9 @@ module Api
end end
# Render the conflict view as a string # Render the conflict view as a string
def render_conflict_view(conflict_weapon, incoming_weapon, incoming_position) def render_conflict_view(conflict_weapons, incoming_weapon, incoming_position)
ConflictBlueprint.render(nil, view: :weapons, ConflictBlueprint.render(nil, view: :weapons,
conflict_weapon: conflict_weapon, conflict_weapons: conflict_weapons,
incoming_weapon: incoming_weapon, incoming_weapon: incoming_weapon,
incoming_position: incoming_position) incoming_position: incoming_position)
end end
@ -166,12 +166,14 @@ module Api
end end
def handle_conflict(weapon) def handle_conflict(weapon)
conflict_weapon = weapon.conflicts(party) conflict_weapons = weapon.conflicts(party)
if conflict_weapon.weapon.id != incoming_weapon.id # Map conflict weapon IDs into an array
conflict_weapon_ids = conflict_weapons.map(&:id)
if !conflict_weapon_ids.include?(incoming_weapon.id)
# Render conflict view if the underlying canonical weapons # Render conflict view if the underlying canonical weapons
# are not identical # are not identical
output = render_conflict_view([conflict_weapon], incoming_weapon, weapon_params[:position]) output = render_conflict_view(conflict_weapons, incoming_weapon, weapon_params[:position])
render json: output render json: output
else else
# Move the original grid weapon to the new position # Move the original grid weapon to the new position

View file

@ -17,7 +17,7 @@ class GridWeapon < ApplicationRecord
validate :compatible_with_position, on: :create validate :compatible_with_position, on: :create
validate :no_conflicts, on: :create validate :no_conflicts, on: :create
before_save :is_mainhand before_save :mainhand?
##### Amoeba configuration ##### Amoeba configuration
amoeba do amoeba do
@ -44,14 +44,20 @@ class GridWeapon < ApplicationRecord
def conflicts(party) def conflicts(party)
return unless weapon.limit return unless weapon.limit
party.weapons.find do |party_weapon| conflicting_weapons = []
return unless party_weapon.id
party.weapons.each do |party_weapon|
next unless party_weapon.id
id_match = weapon.id == party_weapon.id id_match = weapon.id == party_weapon.id
series_match = weapon.series == party_weapon.weapon.series series_match = weapon.series == party_weapon.weapon.series
both_opus_or_draconic = weapon.opus_or_draconic? && party_weapon.weapon.opus_or_draconic? both_opus_or_draconic = weapon.opus_or_draconic? && party_weapon.weapon.opus_or_draconic?
weapon if (series_match || both_opus_or_draconic) && !id_match both_draconic = weapon.draconic_or_providence? && party_weapon.weapon.draconic_or_providence?
conflicting_weapons << party_weapon if (series_match || both_opus_or_draconic || both_draconic) && !id_match
end end
conflicting_weapons
end end
private private
@ -60,9 +66,15 @@ class GridWeapon < ApplicationRecord
# Validates whether the weapon can be added to the desired position # Validates whether the weapon can be added to the desired position
def compatible_with_position def compatible_with_position
return unless [9, 10, 11].include?(position.to_i) && ![11, 16, 17, 28, 29, 32].include?(weapon.series) is_extra_position = [9, 10, 11].include?(position.to_i)
is_extra_weapon = [11, 16, 17, 28, 29, 32, 34].include?(weapon.series.to_i)
return unless is_extra_position
return true if is_extra_weapon
errors.add(:series, 'must be compatible with position') errors.add(:series, 'must be compatible with position')
false
end end
# Validates whether the desired weapon key can be added to the weapon # Validates whether the desired weapon key can be added to the weapon
@ -75,11 +87,13 @@ class GridWeapon < ApplicationRecord
# Validates whether there is a conflict with the party # Validates whether there is a conflict with the party
def no_conflicts def no_conflicts
# Check if the grid weapon conflicts with any of the other grid weapons in the party # Check if the grid weapon conflicts with any of the other grid weapons in the party
errors.add(:series, 'must not conflict with existing weapons') unless conflicts(party).nil? return unless !conflicts(party).nil? && !conflicts(party).empty?
errors.add(:series, 'must not conflict with existing weapons')
end end
# Checks if the weapon should be a mainhand before saving the model # Checks if the weapon should be a mainhand before saving the model
def is_mainhand def mainhand?
self.mainhand = position == -1 self.mainhand = position == -1
end end
end end

View file

@ -48,11 +48,16 @@ class Weapon < ApplicationRecord
end end
def compatible_with_key?(key) def compatible_with_key?(key)
key.series == series key.series.include?(series)
end end
# Returns whether the weapon is included in the Draconic or Dark Opus series # Returns whether the weapon is included in the Draconic or Dark Opus series
def opus_or_draconic? def opus_or_draconic?
[2, 3].include?(series) [2, 3].include?(series)
end end
# Returns whether the weapon belongs to the Draconic Weapon series or the Draconic Weapon Providence series
def draconic_or_providence?
[3, 34].include?(series)
end
end end

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
class MigrateSeries < ActiveRecord::Migration[7.0]
def up
WeaponKey.find_each do |weapon_key|
weapon_key.update(new_series: [weapon_key.series])
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View file

@ -1 +1 @@
DataMigrate::Data.define(version: 20230816061005) DataMigrate::Data.define(version: 20231119051223)

View file

@ -0,0 +1,5 @@
class AddNewSeriesToWeaponKeys < ActiveRecord::Migration[7.0]
def change
add_column :weapon_keys, :new_series, :integer, null: false, default: [], array: true
end
end

View file

@ -0,0 +1,6 @@
class RenameNewSeriesAndDeleteSeries < ActiveRecord::Migration[7.0]
def change
remove_column :weapon_keys, :series, :integer
rename_column :weapon_keys, :new_series, :series
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do ActiveRecord::Schema[7.0].define(version: 2023_11_19_051231) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "btree_gin" enable_extension "btree_gin"
enable_extension "pg_trgm" enable_extension "pg_trgm"
@ -30,50 +30,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.integer "order", default: 0, null: false t.integer "order", default: 0, null: false
end end
create_table "character_charge_attacks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "character_id"
t.string "name_en", null: false
t.string "name_jp", null: false
t.string "description_en", null: false
t.string "description_jp", null: false
t.integer "order", null: false
t.string "form"
t.uuid "effects", array: true
t.index ["character_id"], name: "index_character_charge_attacks_on_character_id"
end
create_table "character_skills", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "character_id"
t.string "name_en", null: false
t.string "name_jp", null: false
t.string "description_en", null: false
t.string "description_jp", null: false
t.integer "type", null: false
t.integer "position", null: false
t.string "form"
t.integer "cooldown", default: 0, null: false
t.integer "lockout", default: 0, null: false
t.integer "duration", array: true
t.boolean "recast", default: false, null: false
t.integer "obtained_at", default: 1, null: false
t.uuid "effects", array: true
t.index ["character_id"], name: "index_character_skills_on_character_id"
end
create_table "character_support_skills", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "character_id"
t.string "name_en", null: false
t.string "name_jp", null: false
t.string "description_en", null: false
t.string "description_jp", null: false
t.integer "position", null: false
t.integer "obtained_at"
t.boolean "emp", default: false, null: false
t.boolean "transcendence", default: false, null: false
t.uuid "effects", array: true
t.index ["character_id"], name: "index_character_support_skills_on_character_id"
end
create_table "characters", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table "characters", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "name_en" t.string "name_en"
t.string "name_jp" t.string "name_jp"
@ -101,8 +57,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.integer "max_hp_ulb" t.integer "max_hp_ulb"
t.integer "max_atk_ulb" t.integer "max_atk_ulb"
t.integer "character_id", default: [], null: false, array: true t.integer "character_id", default: [], null: false, array: true
t.string "nicknames_en", default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true
t.string "wiki_en", default: "", null: false t.string "wiki_en", default: "", null: false
t.date "release_date" t.date "release_date"
t.date "flb_date" t.date "flb_date"
@ -110,29 +64,11 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.string "wiki_ja", default: "", null: false t.string "wiki_ja", default: "", null: false
t.string "gamewith", default: "", null: false t.string "gamewith", default: "", null: false
t.string "kamigame", default: "", null: false t.string "kamigame", default: "", null: false
t.string "nicknames_en", default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true
t.index ["name_en"], name: "index_characters_on_name_en", opclass: :gin_trgm_ops, using: :gin t.index ["name_en"], name: "index_characters_on_name_en", opclass: :gin_trgm_ops, using: :gin
end end
create_table "data_migrations", primary_key: "version", id: :string, force: :cascade do |t|
end
create_table "effects", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "name_en", null: false
t.string "name_jp", null: false
t.string "description_en", null: false
t.string "description_jp", null: false
t.integer "accuracy_value"
t.string "accuracy_suffix"
t.string "accuracy_comparator"
t.jsonb "strength", array: true
t.integer "healing_cap"
t.boolean "duration_indefinite", default: false, null: false
t.integer "duration_value"
t.string "duration_unit"
t.string "notes_en"
t.string "notes_jp"
end
create_table "favorites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table "favorites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "user_id" t.uuid "user_id"
t.uuid "party_id" t.uuid "party_id"
@ -179,10 +115,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.jsonb "ring3", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb "ring3", default: {"modifier"=>nil, "strength"=>nil}, null: false
t.jsonb "ring4", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb "ring4", default: {"modifier"=>nil, "strength"=>nil}, null: false
t.jsonb "earring", default: {"modifier"=>nil, "strength"=>nil}, null: false t.jsonb "earring", default: {"modifier"=>nil, "strength"=>nil}, null: false
t.boolean "skill0_enabled", default: true, null: false
t.boolean "skill1_enabled", default: true, null: false
t.boolean "skill2_enabled", default: true, null: false
t.boolean "skill3_enabled", default: true, null: false
t.uuid "awakening_id" t.uuid "awakening_id"
t.integer "awakening_level", default: 1 t.integer "awakening_level", default: 1
t.index ["awakening_id"], name: "index_grid_characters_on_awakening_id" t.index ["awakening_id"], name: "index_grid_characters_on_awakening_id"
@ -200,7 +132,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.integer "transcendence_step", default: 0, null: false t.integer "transcendence_step", default: 0, null: false
t.boolean "quick_summon", default: false, null: false t.boolean "quick_summon", default: false
t.index ["party_id"], name: "index_grid_summons_on_party_id" t.index ["party_id"], name: "index_grid_summons_on_party_id"
t.index ["summon_id"], name: "index_grid_summons_on_summon_id" t.index ["summon_id"], name: "index_grid_summons_on_summon_id"
end end
@ -302,7 +234,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.datetime "revoked_at", precision: nil t.datetime "revoked_at", precision: nil
t.datetime "created_at", precision: nil, null: false t.datetime "created_at", precision: nil, null: false
t.string "scopes" t.string "scopes"
t.string "previous_refresh_token", default: "" t.string "previous_refresh_token", default: "", null: false
t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id" t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
@ -353,7 +285,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.uuid "guidebook3_id" t.uuid "guidebook3_id"
t.uuid "guidebook1_id" t.uuid "guidebook1_id"
t.uuid "guidebook2_id" t.uuid "guidebook2_id"
t.boolean "auto_summon", default: false, null: false t.boolean "auto_summon", default: false
t.boolean "remix", default: false, null: false t.boolean "remix", default: false, null: false
t.integer "visibility", default: 1, null: false t.integer "visibility", default: 1, null: false
t.index ["accessory_id"], name: "index_parties_on_accessory_id" t.index ["accessory_id"], name: "index_parties_on_accessory_id"
@ -440,8 +372,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.boolean "xlb", default: false, null: false t.boolean "xlb", default: false, null: false
t.integer "max_atk_xlb" t.integer "max_atk_xlb"
t.integer "max_hp_xlb" t.integer "max_hp_xlb"
t.string "nicknames_en", default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true
t.integer "summon_id" t.integer "summon_id"
t.date "release_date" t.date "release_date"
t.date "flb_date" t.date "flb_date"
@ -451,6 +381,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.string "gamewith", default: "" t.string "gamewith", default: ""
t.string "kamigame", default: "" t.string "kamigame", default: ""
t.date "xlb_date" t.date "xlb_date"
t.string "nicknames_en", default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true
t.index ["name_en"], name: "index_summons_on_name_en", opclass: :gin_trgm_ops, using: :gin t.index ["name_en"], name: "index_summons_on_name_en", opclass: :gin_trgm_ops, using: :gin
end end
@ -480,12 +412,12 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
create_table "weapon_keys", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table "weapon_keys", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "name_en" t.string "name_en"
t.string "name_jp" t.string "name_jp"
t.integer "series"
t.integer "slot" t.integer "slot"
t.integer "group" t.integer "group"
t.integer "order" t.integer "order"
t.string "slug" t.string "slug"
t.integer "granblue_id" t.integer "granblue_id"
t.integer "series", default: [], null: false, array: true
end end
create_table "weapons", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| create_table "weapons", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
@ -512,8 +444,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.integer "ax_type" t.integer "ax_type"
t.boolean "limit", default: false, null: false t.boolean "limit", default: false, null: false
t.boolean "ax", default: false, null: false t.boolean "ax", default: false, null: false
t.string "nicknames_en", default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true
t.uuid "recruits_id" t.uuid "recruits_id"
t.integer "max_awakening_level" t.integer "max_awakening_level"
t.date "release_date" t.date "release_date"
@ -523,6 +453,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_24_222107) do
t.string "wiki_ja", default: "" t.string "wiki_ja", default: ""
t.string "gamewith", default: "" t.string "gamewith", default: ""
t.string "kamigame", default: "" t.string "kamigame", default: ""
t.string "nicknames_en", default: [], null: false, array: true
t.string "nicknames_jp", default: [], null: false, array: true
t.index ["name_en"], name: "index_weapons_on_name_en", opclass: :gin_trgm_ops, using: :gin t.index ["name_en"], name: "index_weapons_on_name_en", opclass: :gin_trgm_ops, using: :gin
t.index ["recruits_id"], name: "index_weapons_on_recruits_id" t.index ["recruits_id"], name: "index_weapons_on_recruits_id"
end end