diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index e6b7580f..eed7fe03 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -122,13 +122,28 @@ class ItemsController < ApplicationController return end + # Group the items by category! @nc_mall_items = @items.select(&:currently_in_mall?) @other_nc_items = @items.select(&:nc?).reject(&:currently_in_mall?) @np_items = @items.select(&:np?) @pb_items = @items.select(&:pb?) + + # Also, PB items have some special handling: we group them by color, then + # load example pet types for the colors that don't have paint brushes. @pb_items_by_color = @pb_items.group_by(&:pb_color). sort_by { |color, items| color.name }.to_h + colors_without_thumbnails = + @pb_items_by_color.keys.reject(&:pb_item_thumbnail_url?) + + @pb_color_pet_types = colors_without_thumbnails.map do |color| + # Infer the ideal species from the first item we can, then try to find a + # matching pet type to use as the thumbnail, if needed. + species = @pb_items_by_color[color].map(&:pb_species).select(&:present?) + .first + [color, color.example_pet_type(preferred_species: species)] + end.to_h + render layout: "application" end diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index ad0d42b2..19f9e47a 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -2,23 +2,34 @@ require "addressable/template" module ItemsHelper module PetTypeImage - Format = 'https://pets.neopets.com/cp/%s/%i/%i.png' + Template = Addressable::Template.new( + "https://pets.neopets.com/cp/{hash}/{emotion}/{size}.png" + ) Emotions = { - :happy => 1, - :sad => 2, - :angry => 3, - :ill => 4 + happy: 1, + sad: 2, + angry: 3, + ill: 4, } Sizes = { - :face => 1, - :thumb => 2, - :zoom => 3, - :full => 4 + face: 1, + thumb: 2, + zoom: 3, + full: 4, + face_2x: 6, } end + def pet_type_image_url(pet_type, emotion: :happy, size: :face) + PetTypeImage::Template.expand( + hash: pet_type.basic_image_hash || pet_type.image_hash, + emotion: PetTypeImage::Emotions[emotion], + size: PetTypeImage::Sizes[size], + ).to_s + end + def standard_species_search_links build_on_pet_types(Species.alphabetical) do |pet_type| image = pet_type_image(pet_type, :happy, :zoom) @@ -157,9 +168,7 @@ module ItemsHelper end def pet_type_image(pet_type, emotion, size) - emotion_id = PetTypeImage::Emotions[emotion] - size_id = PetTypeImage::Sizes[size] - src = sprintf(PetTypeImage::Format, pet_type.basic_image_hash, emotion_id, size_id) + src = pet_type_image_url(pet_type, emotion:, size:) human_name = pet_type.species.name.humanize image_tag(src, :alt => human_name, :title => human_name) end diff --git a/app/models/color.rb b/app/models/color.rb index 94a2b5f1..42ee4415 100644 --- a/app/models/color.rb +++ b/app/models/color.rb @@ -21,6 +21,11 @@ class Color < ApplicationRecord end end + def example_pet_type(preferred_species: Species.first) + pet_types.order([Arel.sql("species_id = ? DESC"), preferred_species.id], + "species_id ASC").first + end + def unfunny_human_name if name name.split(' ').map { |word| word.capitalize }.join(' ') diff --git a/app/models/item.rb b/app/models/item.rb index 1c70ae5d..e0ea7b4b 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -197,6 +197,14 @@ class Item < ApplicationRecord find { |c| normalized_name.include?(c.name.downcase.gsub(/\s/, "")) } end + # If this is a PB item, return the corresponding Species, inferred from the + # item name. If it's not a PB item, or we fail to infer, return nil. + def pb_species + return nil unless pb? + normalized_name = name.downcase + Species.order(:name).find { |s| normalized_name.include?(s.name.downcase) } + end + def pb_item_name pb_color&.pb_item_name end diff --git a/app/views/items/sources.html.haml b/app/views/items/sources.html.haml index 76bedf46..a67a9854 100644 --- a/app/views/items/sources.html.haml +++ b/app/views/items/sources.html.haml @@ -67,6 +67,10 @@ - if color.pb_item_thumbnail_url? = image_tag color.pb_item_thumbnail_url, alt: "Item thumbnail for #{color.pb_item_name}" + - else + = image_tag pet_type_image_url(@pb_color_pet_types[color], size: :face), + srcset: ["#{pet_type_image_url(@pb_color_pet_types[color], size: :face_2x)} 2x"], + alt: @pb_color_pet_types[color].human_name %th #{color.pb_item_name || color.name.humanize} (#{pluralize items.size, "item"})