From d34bebc336e5bccc5ddc53bc855ccc7ddfdbeffa Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 22 May 2024 17:53:52 -0700 Subject: [PATCH] Use a pet face when there's no paint brush, in Item Getting Guide Now, for colors like Mutant or Magma where there's no paint brush image to show, we use a sample pet image instead, to help it have equal visual weight and clarity as the cases with the paint brushes. We do some cleverness in here to make sure to always show the relevant species, if possible! --- app/controllers/items_controller.rb | 15 +++++++++++++ app/helpers/items_helper.rb | 33 ++++++++++++++++++----------- app/models/color.rb | 5 +++++ app/models/item.rb | 8 +++++++ app/views/items/sources.html.haml | 4 ++++ 5 files changed, 53 insertions(+), 12 deletions(-) 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"})