Compare commits

..

7 commits

Author SHA1 Message Date
3310394fb8 Improve Owls value presentation in Item Getting Guide 2024-06-09 19:22:34 -07:00
be525d1d67 Oops, fix bug with empty subtitles in Item Getting Guide
Oh weird, even with `flush: true`, `content_for` will ignore an empty
block and *not* flush out the previous content. This could cause rows
whose subtitles *should* have been empty (e.g. no NC trade value) to
display the previous row's value instead.

Let's make this whole situation a bit more robust by having the
*template* clear out the subtitle right before calling the block. That
way, a previous row's value *can't* get in, no matter what.
2024-06-09 15:40:58 -07:00
3dbcf41e4f Restyle Owls link a bit in Item Getting Guide
I think it helps a bit to have only the label be dotted-underlined, to
hint that I'm offering help about what that *means*, but clear the way
for the value itself to be more visible and less cluttered.
2024-06-09 15:22:21 -07:00
9bc6be05f8 Add "Permanent" label to permanent Dyeworks items in Item Getting Guide 2024-06-09 15:21:42 -07:00
a3f910b7ce Add more line breaks to Item Getting Guide template source
Idk, as things get more complex, it was starting to get too crunchy!
2024-06-09 15:05:00 -07:00
1f0c8b87a6 Move Item Getting Guide subtitle UI out of helpers, into templates
I thought to myself, "I wonder if it's possible to use a sneaky hacky
`content_for` trick to be able to run this code in the template." And
indeed it is!

It's tricky cuz like, I want to render this template, and I want to
provide _multiple_ slots of content to it. So, in this variant, we keep
the block as being primarily for the actions, but also optionally
accept `content_for :subtitle` inside that block, too.

Executing that correctly is a bit tricky! The subtitle comes *before*
the actions. So, we `yield` the actions block immediately, save it to a
variable, and *then* get the subtitle block.
2024-06-09 15:03:35 -07:00
b22ccbc2a3 Use Owls to check for Permanent Dyeworks items
Previously, I added a Dyeworks section that was incorrect: the base
item being available in the NC Mall does *not* mean you can necessarily
dye it with a potion!

In this change, we lean on Owls to tell us more about Dyeworks status,
and only group items in this section that Owls has marked as "Permanent
Dyeworks".

We don't have support for limited-time Dyeworks items yet—I've sent out
a message asking the Owls team for more info on what they do for those
items!
2024-06-09 14:46:24 -07:00
6 changed files with 127 additions and 44 deletions

View file

@ -67,6 +67,12 @@
text-decoration-style: dotted
cursor: help
.dyeworks-timeframe
font-style: italic
text-decoration-line: underline
text-decoration-style: dotted
cursor: help
.special-color-explanation
text-wrap: balance
font-style: italic
@ -78,13 +84,12 @@
a
color: inherit
a[title]
.owls-info-link
cursor: help
.owls-info-label
text-decoration-line: underline
text-decoration-style: dotted
cursor: help
&:hover, &:focus
text-decoration-style: solid
/* For wearable items that belong to a specific set that all come together,
* like a Paint Brush. */

View file

@ -122,14 +122,19 @@ class ItemsController < ApplicationController
return
end
# For Dyeworks items whose base is currently in the NC Mall, preload their
# trade values. We'll use this to determine which ones are fully buyable rn
# (because Owls tracks this data and we don't).
Item.preload_nc_trade_values(@items.select(&:dyeworks_base_buyable?))
# Group the items by category!
@nc_mall_items = @items.select(&:currently_in_mall?).
reject(&:dyeworks_active?)
@active_dyeworks_items = @items.select(&:dyeworks_active?)
reject(&:dyeworks_buyable?)
@buyable_dyeworks_items = @items.select(&:dyeworks_buyable?)
@np_items = @items.select(&:np?)
@pb_items = @items.select(&:pb?)
@other_nc_items = @items.select(&:nc?).reject(&:currently_in_mall?).
reject(&:dyeworks_active?)
reject(&:dyeworks_buyable?)
# Start loading the NC trade values for the non-Mall NC items.
trade_values_task = Async { Item.preload_nc_trade_values(@other_nc_items) }

View file

@ -156,22 +156,36 @@ module ItemsHelper
"Last updated: #{date_str} (#{time_ago_str} ago)"
end
def nc_trade_value_subtitle_for(item)
value = item.nc_trade_value
return nil if value.nil?
link_to "Owls listing: #{item.nc_trade_value.value_text}",
"https://www.neopets.com/~owls", target: "_blank",
title: 'Owls keeps track of approximate "capsule" values of NC items ' +
"for trading. Items with similar values can often be traded for one " +
"another. This is an estimate, not a rule!"
NC_TRADE_VALUE_ESTIMATE_PATTERN = %r{
^\s*
(?:
# Case 1: A single number
(?<single>[0-9]+)
|
# Case 2: A range from low to high
(?<low>[0-9]+)
\p{Dash_Punctuation}
(?<high>[0-9]+)
)
\s*$
}x
def nc_trade_value_is_estimate(nc_trade_value)
nc_trade_value.value_text.match?(NC_TRADE_VALUE_ESTIMATE_PATTERN)
end
def dyeworks_explanation_subtitle_for(item)
base_item = item.dyeworks_base_item
content_tag :span, class: "dyeworks-explanation" do
concat link_to(base_item.name, base_item, target: "_blank")
concat " + 1 Potion"
# Try to parse the NC trade value's text into something styled a bit more
# nicely for our use case.
def nc_trade_value_estimate_text(nc_trade_value)
match = nc_trade_value.value_text.match(NC_TRADE_VALUE_ESTIMATE_PATTERN)
return nc_trade_value if match.nil?
match => {single:, low:, high:}
if single.present?
pluralize single.to_i, "capsule"
elsif low.present? && high.present?
"#{low}#{high} capsules"
else
nc_trade_value
end
end

View file

@ -203,11 +203,27 @@ class Item < ApplicationRecord
end
# Whether this is a Dyeworks item whose base item can currently be purchased
# in the NC Mall, then dyed via Dyeworks.
def dyeworks_active?
# in the NC Mall. It may or may not currently be *dyeable* in the NC Mall,
# because Dyeworks eligibility is often a limited-time event.
def dyeworks_base_buyable?
dyeworks_base_item.present? && dyeworks_base_item.currently_in_mall?
end
# Whether this is one of the few Dyeworks items that can be dyed in the NC
# Mall at any time, rather than as part of a limited-time event. (Owls tracks
# this, not us!)
def dyeworks_permanent?
nc_trade_value.value_text.include?("Permanent Dyeworks")
end
# Whether this is a Dyeworks item whose base item can currently be purchased
# in the NC Mall, then dyed via Dyeworks. (Owls tracks this last part!)
def dyeworks_buyable?
# TODO: Add support for limited-time Dyeworks items. Does Owls offer this
# info too? (At time of writing, there are no active Dyeworks events.)
dyeworks_base_buyable? && dyeworks_permanent?
end
DYEWORKS_NAME_PATTERN = %r{
^(
# Most Dyeworks items have a colon in the name.

View file

@ -1,4 +1,8 @@
- subtitle = nil unless defined? subtitle
-# Run the block first, so we can get the subtitle content if provided! Clear
-# out any old values beforehand, too.
- content_for :subtitle, "", flush: true
- content = yield
- subtitle = yield :subtitle
%tr
%td.thumbnail-cell
@ -8,4 +12,4 @@
= link_to item.name, item, target: "_blank"
- if subtitle.present?
.subtitle= subtitle
%td.actions-cell= yield
%td.actions-cell= content

View file

@ -10,6 +10,7 @@
[nc]: https://secure.nc.neopets.com/get-neocash
[gc]: https://secure.nc.neopets.com/nickcash-cards
%table.item-list
%thead
%tr
@ -29,7 +30,7 @@
= cart_icon alt: ""
Buy (#{item.current_nc_price} NC)
- if @active_dyeworks_items.present?
- if @buyable_dyeworks_items.present?
%h2 Dyeworks items
:markdown
These are recolored "Dyeworks" variants of items. First get the "base"
@ -37,35 +38,46 @@
[Dyeworks][dyeworks] section of the NC Mall! Potions can also be bought in
bundles of 5 or 10.
TODO: This is currently incorrect! Dyeworks items can't always be dyed, we
need to keep track of which ones actually can be right now!
[dyeworks]: https://www.neopets.com/mall/dyeworks/
%table.item-list
%thead
%td.thumbnail-cell
= image_tag "https://images.neopets.com/items/mall_80x80_cleaning.gif",
alt: "Dyeworks Hue Brew Potion"
%th
Total: #{dyeworks_nc_total_for @active_dyeworks_items} NC
Total: #{dyeworks_nc_total_for @buyable_dyeworks_items} NC
= surround "(", ")" do
%span.price-breakdown{
title: "#{dyeworks_items_nc_total_for(@active_dyeworks_items)} NC"
title: "#{dyeworks_items_nc_total_for(@buyable_dyeworks_items)} NC"
}<
#{pluralize @active_dyeworks_items.size, "item"}
#{pluralize @buyable_dyeworks_items.size, "item"}
+
%span.price-breakdown{
title: dyeworks_potions_nc_summary(@active_dyeworks_items.size)
title: dyeworks_potions_nc_summary(@buyable_dyeworks_items.size)
}<
#{pluralize @active_dyeworks_items.size, "potion"}
#{pluralize @buyable_dyeworks_items.size, "potion"}
%td.actions-cell
%button{onclick: "alert('Todo!')"}
= cart_icon alt: ""
Buy all in NC Mall
%tbody
- @active_dyeworks_items.each do |item|
= render "item_list_row", item:,
subtitle: dyeworks_explanation_subtitle_for(item) do
- @buyable_dyeworks_items.each do |item|
= render "item_list_row", item: do
- base_item = item.dyeworks_base_item
- content_for :subtitle, flush: true do
= link_to base_item.name, base_item, target: "_blank"
+ 1 potion
- if item.dyeworks_permanent?
%span.dyeworks-timeframe{
title: "This recipe is NOT currently scheduled to be removed " +
"from Dyeworks. It might not stay forever, but it's also " +
"not part of a known limited-time event, like most " +
"Dyeworks items are."
}
(Permanent)
%button{onclick: "alert('Todo!')"}
= cart_icon alt: ""
Buy base (#{item.dyeworks_base_item.current_nc_price} NC)
@ -81,6 +93,7 @@
[wiz]: https://www.neopets.com/shops/wizard.phtml
[tp]: https://www.neopets.com/island/tradingpost.phtml?type=browse
[ag]: https://www.neopets.com/genie.phtml
%table.item-list
%thead
%td
@ -101,6 +114,7 @@
these items will be semi-permanently added to your Closet, even if your
pet changes color again! You can use this to mix-and-match styles for
"cross-paint" outfits.
- @pb_items_by_color.each do |color, items|
%table.item-list{"data-group-type": "bundle"}
%thead
@ -142,13 +156,21 @@
- if @other_nc_items.present?
%h2 Neocash items (Capsules, events, retired, etc.)
:markdown
These items are part of the Neocash economy and can't be purchased with
Neopoints. We don't track all the details of how to get these items
right now! Sometimes they're available via packs or capsules or events
in the [NC Mall][mall]. Sometimes they're retired and can't be
purchased at all anymore, and can only be obtained via gifts or trades.
These items are part of the Neocash economy, but not directly for sale.
Sometimes they're available in the [NC Mall][mall], via special
bundles or events. Sometimes they're retired, and can only be obtained via
gifts or trades.
[mall]: https://ncmall.neopets.com/
- if @other_nc_items.any?(&:nc_trade_value)
:markdown
The [Owls Value Guide][owls] often has more details about how to get
these items, and how much they're usually worth in the NC Trading
community. We've loaded their info here for you, too! Thanks, Owls team!
[owls]: https://www.neopets.com/~owls
%table.item-list
%thead
%td
@ -156,7 +178,24 @@
Total: #{pluralize @other_nc_items.size, "item"}
%tbody
- @other_nc_items.each do |item|
= render "item_list_row", item:, subtitle: nc_trade_value_subtitle_for(item) do
= render "item_list_row", item: do
- content_for :subtitle, flush: true do
- if item.nc_trade_value.present?
- if nc_trade_value_is_estimate(item.nc_trade_value)
= link_to "https://www.neopets.com/~owls",
class: "owls-info-link", target: "_blank",
title: 'Owls keeps track of approximate "capsule" values of NC items for trading. Items with similar values can often be traded for one another. This is an estimate, not a rule!' do
%span.owls-info-label [Owls]
Estimated value:
= nc_trade_value_estimate_text(item.nc_trade_value)
- else
= link_to "https://www.neopets.com/~owls",
class: "owls-info-link", target: "_blank",
title: "Owls keeps track of how to get certain special items, even when there isn't a clear NC trade estimate." do
%span.owls-info-label [Owls]
Trade info:
#{item.nc_trade_value.value_text}
= button_link_to "NC Trades",
item_trades_path(item, type: "offering"),
target: "_blank", icon: search_icon