diff --git a/app/models/grid_artifact.rb b/app/models/grid_artifact.rb index e6ef66f..156ca23 100644 --- a/app/models/grid_artifact.rb +++ b/app/models/grid_artifact.rb @@ -6,6 +6,7 @@ class GridArtifact < ApplicationRecord # Associations belongs_to :grid_character belongs_to :artifact + belongs_to :collection_artifact, optional: true has_one :party, through: :grid_character has_one :character, through: :grid_character @@ -54,6 +55,47 @@ class GridArtifact < ApplicationRecord quirk_artifact? ? proficiency : artifact&.proficiency end + ## + # Syncs customizations from the linked collection artifact. + # + # @return [Boolean] true if sync was performed, false if no collection link + def sync_from_collection! + return false unless collection_artifact.present? + + attrs = { + element: collection_artifact.element, + level: collection_artifact.level, + skill1: collection_artifact.skill1, + skill2: collection_artifact.skill2, + skill3: collection_artifact.skill3, + skill4: collection_artifact.skill4, + reroll_slot: collection_artifact.reroll_slot + } + + # Only sync proficiency for quirk artifacts + attrs[:proficiency] = collection_artifact.proficiency if quirk_artifact? + + update!(attrs) + true + end + + ## + # Checks if grid artifact is out of sync with collection. + # + # @return [Boolean] true if any customization differs from collection + def out_of_sync? + return false unless collection_artifact.present? + + element != collection_artifact.element || + level != collection_artifact.level || + skill1 != collection_artifact.skill1 || + skill2 != collection_artifact.skill2 || + skill3 != collection_artifact.skill3 || + skill4 != collection_artifact.skill4 || + reroll_slot != collection_artifact.reroll_slot || + (quirk_artifact? && proficiency != collection_artifact.proficiency) + end + private def quirk_artifact? diff --git a/app/models/grid_character.rb b/app/models/grid_character.rb index 0a54b17..32ea9a3 100644 --- a/app/models/grid_character.rb +++ b/app/models/grid_character.rb @@ -23,6 +23,7 @@ class GridCharacter < ApplicationRecord belongs_to :party, counter_cache: :characters_count, inverse_of: :characters + belongs_to :collection_character, optional: true has_one :grid_artifact, dependent: :destroy @@ -188,6 +189,50 @@ class GridCharacter < ApplicationRecord GridCharacterBlueprint end + ## + # Syncs customizations from the linked collection character. + # + # Copies uncap level, transcendence, rings, earring, and awakening from the collection. + # No-op if no collection character is linked. + # + # @return [Boolean] true if sync was performed, false if no collection link + def sync_from_collection! + return false unless collection_character.present? + + update!( + uncap_level: collection_character.uncap_level, + transcendence_step: collection_character.transcendence_step, + perpetuity: collection_character.perpetuity, + ring1: collection_character.ring1, + ring2: collection_character.ring2, + ring3: collection_character.ring3, + ring4: collection_character.ring4, + earring: collection_character.earring, + awakening_id: collection_character.awakening_id, + awakening_level: collection_character.awakening_level + ) + true + end + + ## + # Checks if grid character is out of sync with collection. + # + # @return [Boolean] true if any customization differs from collection + def out_of_sync? + return false unless collection_character.present? + + uncap_level != collection_character.uncap_level || + transcendence_step != collection_character.transcendence_step || + perpetuity != collection_character.perpetuity || + ring1 != collection_character.ring1 || + ring2 != collection_character.ring2 || + ring3 != collection_character.ring3 || + ring4 != collection_character.ring4 || + earring != collection_character.earring || + awakening_id != collection_character.awakening_id || + awakening_level != collection_character.awakening_level + end + private ## diff --git a/app/models/grid_summon.rb b/app/models/grid_summon.rb index 16811b2..596a7ed 100644 --- a/app/models/grid_summon.rb +++ b/app/models/grid_summon.rb @@ -16,6 +16,7 @@ class GridSummon < ApplicationRecord belongs_to :party, counter_cache: :summons_count, inverse_of: :summons + belongs_to :collection_summon, optional: true validates_presence_of :party # Validate that position is provided. @@ -39,6 +40,31 @@ class GridSummon < ApplicationRecord GridSummonBlueprint end + ## + # Syncs customizations from the linked collection summon. + # + # @return [Boolean] true if sync was performed, false if no collection link + def sync_from_collection! + return false unless collection_summon.present? + + update!( + uncap_level: collection_summon.uncap_level, + transcendence_step: collection_summon.transcendence_step + ) + true + end + + ## + # Checks if grid summon is out of sync with collection. + # + # @return [Boolean] true if any customization differs from collection + def out_of_sync? + return false unless collection_summon.present? + + uncap_level != collection_summon.uncap_level || + transcendence_step != collection_summon.transcendence_step + end + ## # Returns any conflicting grid summon for the given party. # diff --git a/app/models/grid_weapon.rb b/app/models/grid_weapon.rb index ef85d9c..73b439d 100644 --- a/app/models/grid_weapon.rb +++ b/app/models/grid_weapon.rb @@ -37,6 +37,7 @@ class GridWeapon < ApplicationRecord belongs_to :weapon_key4, class_name: 'WeaponKey', foreign_key: :weapon_key4_id, optional: true belongs_to :awakening, optional: true + belongs_to :collection_weapon, optional: true # Validate that uncap_level is present and numeric, transcendence_step is optional but must be numeric if present. validates :uncap_level, presence: true, numericality: { only_integer: true } @@ -63,6 +64,53 @@ class GridWeapon < ApplicationRecord GridWeaponBlueprint end + ## + # Syncs customizations from the linked collection weapon. + # + # @return [Boolean] true if sync was performed, false if no collection link + def sync_from_collection! + return false unless collection_weapon.present? + + update!( + uncap_level: collection_weapon.uncap_level, + transcendence_step: collection_weapon.transcendence_step, + element: collection_weapon.element, + weapon_key1_id: collection_weapon.weapon_key1_id, + weapon_key2_id: collection_weapon.weapon_key2_id, + weapon_key3_id: collection_weapon.weapon_key3_id, + weapon_key4_id: collection_weapon.weapon_key4_id, + ax_modifier1: collection_weapon.ax_modifier1, + ax_strength1: collection_weapon.ax_strength1, + ax_modifier2: collection_weapon.ax_modifier2, + ax_strength2: collection_weapon.ax_strength2, + awakening_id: collection_weapon.awakening_id, + awakening_level: collection_weapon.awakening_level + ) + true + end + + ## + # Checks if grid weapon is out of sync with collection. + # + # @return [Boolean] true if any customization differs from collection + def out_of_sync? + return false unless collection_weapon.present? + + uncap_level != collection_weapon.uncap_level || + transcendence_step != collection_weapon.transcendence_step || + element != collection_weapon.element || + weapon_key1_id != collection_weapon.weapon_key1_id || + weapon_key2_id != collection_weapon.weapon_key2_id || + weapon_key3_id != collection_weapon.weapon_key3_id || + weapon_key4_id != collection_weapon.weapon_key4_id || + ax_modifier1 != collection_weapon.ax_modifier1 || + ax_strength1 != collection_weapon.ax_strength1 || + ax_modifier2 != collection_weapon.ax_modifier2 || + ax_strength2 != collection_weapon.ax_strength2 || + awakening_id != collection_weapon.awakening_id || + awakening_level != collection_weapon.awakening_level + end + ## # Returns an array of assigned weapon keys. #