Compare commits

..

No commits in common. "860b8eef720dfaecc08d995611da811d19eaa6a0" and "26add4577c7d5610dc4e161ef7516a30de670577" have entirely different histories.

7 changed files with 71 additions and 73 deletions

View file

@ -50,24 +50,26 @@ class OutfitsController < ApplicationController
@colors = Color.alphabetical @colors = Color.alphabetical
@species = Species.alphabetical @species = Species.alphabetical
newest_items = Item.newest. # HACK: Skip this in development, because it's slow!
select(:id, :name, :updated_at, :thumbnail_url, :rarity_index, unless Rails.env.development?
:is_manually_nc, :cached_compatible_body_ids) newest_items = Item.newest.
.limit(18) select(:id, :name, :updated_at, :thumbnail_url, :rarity_index, :is_manually_nc)
@newest_modeled_items, @newest_unmodeled_items = .limit(18)
newest_items.partition(&:predicted_fully_modeled?) @newest_modeled_items, @newest_unmodeled_items =
newest_items.partition(&:predicted_fully_modeled?)
@newest_unmodeled_items_predicted_missing_species_by_color = {} @newest_unmodeled_items_predicted_missing_species_by_color = {}
@newest_unmodeled_items_predicted_modeled_ratio = {} @newest_unmodeled_items_predicted_modeled_ratio = {}
@newest_unmodeled_items.each do |item| @newest_unmodeled_items.each do |item|
h = item.predicted_missing_nonstandard_body_ids_by_species_by_color h = item.predicted_missing_nonstandard_body_ids_by_species_by_color
standard_body_ids_by_species = item. standard_body_ids_by_species = item.
predicted_missing_standard_body_ids_by_species predicted_missing_standard_body_ids_by_species
if standard_body_ids_by_species.present? if standard_body_ids_by_species.present?
h[:standard] = standard_body_ids_by_species h[:standard] = standard_body_ids_by_species
end
@newest_unmodeled_items_predicted_missing_species_by_color[item] = h
@newest_unmodeled_items_predicted_modeled_ratio[item] = item.predicted_modeled_ratio
end end
@newest_unmodeled_items_predicted_missing_species_by_color[item] = h
@newest_unmodeled_items_predicted_modeled_ratio[item] = item.predicted_modeled_ratio
end end
@species_count = Species.count @species_count = Species.count

View file

@ -10,9 +10,6 @@ class Item < ApplicationRecord
SwfAssetType = 'object' SwfAssetType = 'object'
serialize :cached_compatible_body_ids, coder: Serializers::IntegerSet
serialize :cached_occupied_zone_ids, coder: Serializers::IntegerSet
has_many :closet_hangers has_many :closet_hangers
has_one :contribution, as: :contributed, inverse_of: :contributed has_one :contribution, as: :contributed, inverse_of: :contributed
has_one :nc_mall_record has_one :nc_mall_record
@ -261,8 +258,8 @@ class Item < ApplicationRecord
end end
def update_cached_fields def update_cached_fields
self.cached_occupied_zone_ids = occupied_zone_ids self.cached_occupied_zone_ids = occupied_zone_ids.sort.join(",")
self.cached_compatible_body_ids = compatible_body_ids(use_cached: false) self.cached_compatible_body_ids = compatible_body_ids.sort.join(",")
self.save! self.save!
end end
@ -276,35 +273,58 @@ class Item < ApplicationRecord
write_attribute('species_support_ids', replacement) write_attribute('species_support_ids', replacement)
end end
def support_species?(species)
species_support_ids.blank? || species_support_ids.include?(species.id)
end
def modeled_body_ids
@modeled_body_ids ||= swf_assets.select('DISTINCT body_id').map(&:body_id)
end
def modeled_color_ids
# Might be empty if modeled_body_ids is 0. But it's currently not called
# in that scenario, so, whatever.
@modeled_color_ids ||= PetType.select('DISTINCT color_id').
where(body_id: modeled_body_ids).
map(&:color_id)
end
def basic_body_ids
@basic_body_ids ||= begin
basic_color_ids ||= Color.select([:id]).basic.map(&:id)
PetType.select('DISTINCT body_id').
where(color_id: basic_color_ids).map(&:body_id)
end
end
def predicted_body_ids def predicted_body_ids
@predicted_body_ids ||= if compatible_body_ids.include?(0) @predicted_body_ids ||= if modeled_body_ids.include?(0)
# Oh, look, it's already known to fit everybody! Sweet. We're done. (This # Oh, look, it's already known to fit everybody! Sweet. We're done. (This
# isn't folded into the case below, in case this item somehow got a # isn't folded into the case below, in case this item somehow got a
# body-specific and non-body-specific asset. In all the cases I've seen # body-specific and non-body-specific asset. In all the cases I've seen
# it, that indicates a glitched item, but this method chooses to reflect # it, that indicates a glitched item, but this method chooses to reflect
# behavior elsewhere in the app by saying that we can put this item on # behavior elsewhere in the app by saying that we can put this item on
# anybody. (Heh. Any body.)) # anybody. (Heh. Any body.))
compatible_body_ids modeled_body_ids
elsif compatible_body_ids.size == 1 elsif modeled_body_ids.size == 1
# This might just be a species-specific item. Let's be conservative in # This might just be a species-specific item. Let's be conservative in
# our prediction, though we'll revise it if we see another body ID. # our prediction, though we'll revise it if we see another body ID.
compatible_body_ids modeled_body_ids
else else
# If an item is worn by more than one body, then it must be wearable by # If an item is worn by more than one body, then it must be wearable by
# all bodies of the same color. (To my knowledge, anyway. I'm not aware # all bodies of the same color. (To my knowledge, anyway. I'm not aware
# of any exceptions.) So, let's find those bodies by first finding those # of any exceptions.) So, let's find those bodies by first finding those
# colors. # colors.
basic_body_ids = PetType.basic_body_ids basic_modeled_body_ids, nonbasic_modeled_body_ids = modeled_body_ids.
basic_compatible_body_ids, nonbasic_compatible_body_ids = partition { |bi| basic_body_ids.include?(bi) }
compatible_body_ids.partition { |bi| basic_body_ids.include?(bi) }
output = [] output = []
if basic_compatible_body_ids.present? if basic_modeled_body_ids.present?
output += basic_body_ids output += basic_body_ids
end end
if nonbasic_compatible_body_ids.present? if nonbasic_modeled_body_ids.present?
nonbasic_modeled_color_ids = PetType.select('DISTINCT color_id'). nonbasic_modeled_color_ids = PetType.select('DISTINCT color_id').
where(body_id: nonbasic_compatible_body_ids). where(body_id: nonbasic_modeled_body_ids).
map(&:color_id) map(&:color_id)
output += PetType.select('DISTINCT body_id'). output += PetType.select('DISTINCT body_id').
where(color_id: nonbasic_modeled_color_ids). where(color_id: nonbasic_modeled_color_ids).
@ -315,7 +335,7 @@ class Item < ApplicationRecord
end end
def predicted_missing_body_ids def predicted_missing_body_ids
@predicted_missing_body_ids ||= predicted_body_ids - compatible_body_ids @predicted_missing_body_ids ||= predicted_body_ids - modeled_body_ids
end end
def predicted_missing_standard_body_ids_by_species_id def predicted_missing_standard_body_ids_by_species_id
@ -335,8 +355,9 @@ class Item < ApplicationRecord
end end
def predicted_missing_nonstandard_body_pet_types def predicted_missing_nonstandard_body_pet_types
body_ids = predicted_missing_body_ids - PetType.basic_body_ids PetType.joins(:color).
PetType.joins(:color).where(body_id: body_ids, colors: {standard: false}) where(body_id: predicted_missing_body_ids - basic_body_ids,
colors: {standard: false})
end end
def predicted_missing_nonstandard_body_ids_by_species_by_color def predicted_missing_nonstandard_body_ids_by_species_by_color
@ -366,7 +387,7 @@ class Item < ApplicationRecord
end end
def predicted_modeled_ratio def predicted_modeled_ratio
compatible_body_ids.size.to_f / predicted_body_ids.size modeled_body_ids.size.to_f / predicted_body_ids.size
end end
def as_json(options={}) def as_json(options={})
@ -376,9 +397,7 @@ class Item < ApplicationRecord
}.merge(options)) }.merge(options))
end end
def compatible_body_ids(use_cached: true) def compatible_body_ids
return cached_compatible_body_ids if use_cached
swf_assets.map(&:body_id).uniq swf_assets.map(&:body_id).uniq
end end

View file

@ -116,10 +116,6 @@ class PetType < ApplicationRecord
"#{color.human_name}-#{species.human_name}" "#{color.human_name}-#{species.human_name}"
end end
def self.basic_body_ids
PetType.basic.distinct.pluck(:body_id)
end
def self.all_by_ids_or_children(ids, pet_states) def self.all_by_ids_or_children(ids, pet_states)
pet_states_by_pet_type_id = {} pet_states_by_pet_type_id = {}
pet_states.each do |pet_state| pet_states.each do |pet_state|

View file

@ -90,14 +90,15 @@
%h3= t '.newest_items.unmodeled.header' %h3= t '.newest_items.unmodeled.header'
%ul#newest-unmodeled-items %ul#newest-unmodeled-items
- @newest_unmodeled_items.each do |item| - @newest_unmodeled_items.each do |item|
%li{'data-item-id' => item.id} - cache "items/#{item.id} modeling_progress locale=#{I18n.locale} updated_at=#{item.updated_at.to_i}" do
= link_to image_tag(item.thumbnail_url), item, :class => 'image-link' %li{'data-item-id' => item.id}
= link_to item, :class => 'header' do = link_to image_tag(item.thumbnail_url), item, :class => 'image-link'
%h2= item.name = link_to item, :class => 'header' do
%span.meter{style: "width: #{@newest_unmodeled_items_predicted_modeled_ratio[item]*100}%"} %h2= item.name
.missing-bodies %span.meter{style: "width: #{@newest_unmodeled_items_predicted_modeled_ratio[item]*100}%"}
= render_predicted_missing_species_by_color(@newest_unmodeled_items_predicted_missing_species_by_color[item]) .missing-bodies
.models = render_predicted_missing_species_by_color(@newest_unmodeled_items_predicted_missing_species_by_color[item])
.models
- if @newest_modeled_items.present? - if @newest_modeled_items.present?
%h3= t '.newest_items.modeled.header' %h3= t '.newest_items.modeled.header'
%ul#newest-modeled-items %ul#newest-modeled-items

View file

@ -1,9 +0,0 @@
class AllowNullInItemsCachedFields < ActiveRecord::Migration[7.2]
def change
# This is a bit more compatible with ActiveRecord's `serialize` utility,
# which seems pretty insistent that empty arrays should be saved as `NULL`,
# rather than the empty string our serializer would return if called :(
change_column_null :items, :cached_compatible_body_ids, true
change_column_null :items, :cached_occupied_zone_ids, true
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.2].define(version: 2024_10_03_004726) do ActiveRecord::Schema[7.2].define(version: 2024_10_01_052510) do
create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_520_ci", force: :cascade do |t| create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_520_ci", force: :cascade do |t|
t.integer "species_id", null: false t.integer "species_id", null: false
t.integer "color_id", null: false t.integer "color_id", null: false
@ -137,8 +137,8 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_03_004726) do
t.text "description", size: :medium, null: false t.text "description", size: :medium, null: false
t.string "rarity", default: "", null: false t.string "rarity", default: "", null: false
t.integer "dyeworks_base_item_id" t.integer "dyeworks_base_item_id"
t.string "cached_occupied_zone_ids", default: "" t.string "cached_occupied_zone_ids", default: "", null: false
t.text "cached_compatible_body_ids", default: "" t.text "cached_compatible_body_ids", default: "", null: false
t.index ["dyeworks_base_item_id"], name: "index_items_on_dyeworks_base_item_id" t.index ["dyeworks_base_item_id"], name: "index_items_on_dyeworks_base_item_id"
t.index ["modeling_status_hint", "created_at", "id"], name: "items_modeling_status_hint_and_created_at_and_id" t.index ["modeling_status_hint", "created_at", "id"], name: "items_modeling_status_hint_and_created_at_and_id"
t.index ["modeling_status_hint", "created_at"], name: "items_modeling_status_hint_and_created_at" t.index ["modeling_status_hint", "created_at"], name: "items_modeling_status_hint_and_created_at"

View file

@ -1,11 +0,0 @@
module Serializers
module IntegerSet
def self.dump(array)
array.sort.join(",")
end
def self.load(string)
(string || "").split(",").map(&:to_i)
end
end
end