forked from OpenNeo/impress
Emi Matchu
cb90b79efe
Two motivations here: 1. Unconverted pets should no longer exist on Neopets.com (and we especially don't expect new ones), so this logic helps no one. 2. The Baby Pteri keeps getting overridden to be marked as Unconverted because it has only one asset, which is incorrect. A decent heuristic for a bygone era, goodbye!
175 lines
5.1 KiB
Ruby
175 lines
5.1 KiB
Ruby
class PetState < ApplicationRecord
|
|
SwfAssetType = 'biology'
|
|
|
|
has_many :contributions, :as => :contributed,
|
|
:inverse_of => :contributed # in case of duplicates being merged
|
|
has_many :outfits
|
|
has_many :parent_swf_asset_relationships, :as => :parent,
|
|
:autosave => false
|
|
has_many :swf_assets, :through => :parent_swf_asset_relationships
|
|
|
|
belongs_to :pet_type
|
|
|
|
delegate :color, to: :pet_type
|
|
|
|
alias_method :swf_asset_ids_from_association, :swf_asset_ids
|
|
|
|
attr_writer :parent_swf_asset_relationships_to_update
|
|
|
|
# A simple ordering that tries to bring reliable pet states to the front.
|
|
scope :emotion_order, -> {
|
|
order(Arel.sql(
|
|
"(mood_id IS NULL) ASC, mood_id ASC, female DESC, unconverted DESC, " +
|
|
"glitched ASC, id DESC"
|
|
))
|
|
}
|
|
|
|
# Filter pet states using the "pose" concept we use in the editor.
|
|
scope :with_pose, -> pose {
|
|
case pose
|
|
when "UNCONVERTED"
|
|
where(unconverted: true)
|
|
when "HAPPY_MASC"
|
|
where(mood_id: 1, female: false)
|
|
when "HAPPY_FEM"
|
|
where(mood_id: 1, female: true)
|
|
when "SAD_MASC"
|
|
where(mood_id: 2, female: false)
|
|
when "SAD_FEM"
|
|
where(mood_id: 2, female: true)
|
|
when "SICK_MASC"
|
|
where(mood_id: 4, female: false)
|
|
when "SICK_FEM"
|
|
where(mood_id: 4, female: true)
|
|
when "UNKNOWN"
|
|
where(mood_id: nil).or(where(female: nil))
|
|
else
|
|
raise ArgumentError, "unexpected pose value #{pose}"
|
|
end
|
|
}
|
|
|
|
def pose
|
|
if unconverted?
|
|
"UNCONVERTED"
|
|
elsif mood_id.nil? || female.nil?
|
|
"UNKNOWN"
|
|
elsif mood_id == 1 && !female?
|
|
"HAPPY_MASC"
|
|
elsif mood_id == 1 && female?
|
|
"HAPPY_FEM"
|
|
elsif mood_id == 2 && !female?
|
|
"SAD_MASC"
|
|
elsif mood_id == 2 && female?
|
|
"SAD_FEM"
|
|
elsif mood_id == 4 && !female?
|
|
"SICK_MASC"
|
|
elsif mood_id == 4 && female?
|
|
"SICK_FEM"
|
|
else
|
|
raise "could not identify pose: moodId=#{mood_id}, female=#{female}, " +
|
|
"unconverted=#{unconverted}"
|
|
end
|
|
end
|
|
|
|
def reassign_children_to!(main_pet_state)
|
|
self.contributions.each do |contribution|
|
|
contribution.contributed = main_pet_state
|
|
contribution.save
|
|
end
|
|
self.outfits.each do |outfit|
|
|
outfit.pet_state = main_pet_state
|
|
outfit.save
|
|
end
|
|
ParentSwfAssetRelationship.where(ParentSwfAssetRelationship.arel_table[:parent_id].eq(self.id)).delete_all
|
|
end
|
|
|
|
def reassign_duplicates!
|
|
raise "This may only be applied to pet states that represent many duplicate entries" unless duplicate_ids
|
|
pet_states = duplicate_ids.split(',').map do |id|
|
|
PetState.find(id.to_i)
|
|
end
|
|
main_pet_state = pet_states.shift
|
|
pet_states.each do |pet_state|
|
|
pet_state.reassign_children_to!(main_pet_state)
|
|
pet_state.destroy
|
|
end
|
|
end
|
|
|
|
def sort_swf_asset_ids!
|
|
self.swf_asset_ids = swf_asset_ids_array.sort.join(',')
|
|
end
|
|
|
|
def swf_asset_ids
|
|
self['swf_asset_ids']
|
|
end
|
|
|
|
def swf_asset_ids_array
|
|
swf_asset_ids.split(',').map(&:to_i)
|
|
end
|
|
|
|
def swf_asset_ids=(ids)
|
|
self['swf_asset_ids'] = ids
|
|
end
|
|
|
|
def handle_assets!
|
|
@parent_swf_asset_relationships_to_update.each do |rel|
|
|
rel.swf_asset.save!
|
|
rel.save!
|
|
end
|
|
end
|
|
|
|
def self.from_pet_type_and_biology_info(pet_type, info)
|
|
swf_asset_ids = []
|
|
info.each do |zone_id, asset_info|
|
|
if zone_id.present? && asset_info
|
|
swf_asset_ids << asset_info[:part_id].to_i
|
|
end
|
|
end
|
|
swf_asset_ids_str = swf_asset_ids.sort.join(',')
|
|
if pet_type.new_record?
|
|
pet_state = self.new :swf_asset_ids => swf_asset_ids_str
|
|
else
|
|
pet_state = self.find_or_initialize_by(
|
|
pet_type_id: pet_type.id,
|
|
swf_asset_ids: swf_asset_ids_str
|
|
)
|
|
end
|
|
existing_swf_assets = SwfAsset.biology_assets.includes(:zone).
|
|
where(remote_id: swf_asset_ids)
|
|
existing_swf_assets_by_id = {}
|
|
existing_swf_assets.each do |swf_asset|
|
|
existing_swf_assets_by_id[swf_asset.remote_id] = swf_asset
|
|
end
|
|
existing_relationships_by_swf_asset_id = {}
|
|
unless pet_state.new_record?
|
|
pet_state.parent_swf_asset_relationships.each do |relationship|
|
|
existing_relationships_by_swf_asset_id[relationship.swf_asset_id] = relationship
|
|
end
|
|
end
|
|
pet_state.pet_type = pet_type # save the second case from having to look it up by ID
|
|
relationships = []
|
|
info.each do |zone_id, asset_info|
|
|
if zone_id.present? && asset_info
|
|
swf_asset_id = asset_info[:part_id].to_i
|
|
swf_asset = existing_swf_assets_by_id[swf_asset_id]
|
|
unless swf_asset
|
|
swf_asset = SwfAsset.new
|
|
swf_asset.remote_id = swf_asset_id
|
|
end
|
|
swf_asset.origin_biology_data = asset_info
|
|
swf_asset.origin_pet_type = pet_type
|
|
relationship = existing_relationships_by_swf_asset_id[swf_asset.id]
|
|
unless relationship
|
|
relationship ||= ParentSwfAssetRelationship.new
|
|
relationship.parent = pet_state
|
|
relationship.swf_asset_id = swf_asset.id
|
|
end
|
|
relationship.swf_asset = swf_asset
|
|
relationships << relationship
|
|
end
|
|
end
|
|
pet_state.parent_swf_asset_relationships_to_update = relationships
|
|
pet_state
|
|
end
|
|
end
|
|
|