Compare commits
7 commits
5de9e2a27b
...
3310394fb8
Author | SHA1 | Date | |
---|---|---|---|
3310394fb8 | |||
be525d1d67 | |||
3dbcf41e4f | |||
9bc6be05f8 | |||
a3f910b7ce | |||
1f0c8b87a6 | |||
b22ccbc2a3 |
6 changed files with 127 additions and 44 deletions
|
@ -67,6 +67,12 @@
|
||||||
text-decoration-style: dotted
|
text-decoration-style: dotted
|
||||||
cursor: help
|
cursor: help
|
||||||
|
|
||||||
|
.dyeworks-timeframe
|
||||||
|
font-style: italic
|
||||||
|
text-decoration-line: underline
|
||||||
|
text-decoration-style: dotted
|
||||||
|
cursor: help
|
||||||
|
|
||||||
.special-color-explanation
|
.special-color-explanation
|
||||||
text-wrap: balance
|
text-wrap: balance
|
||||||
font-style: italic
|
font-style: italic
|
||||||
|
@ -78,13 +84,12 @@
|
||||||
a
|
a
|
||||||
color: inherit
|
color: inherit
|
||||||
|
|
||||||
a[title]
|
.owls-info-link
|
||||||
|
cursor: help
|
||||||
|
|
||||||
|
.owls-info-label
|
||||||
text-decoration-line: underline
|
text-decoration-line: underline
|
||||||
text-decoration-style: dotted
|
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,
|
/* For wearable items that belong to a specific set that all come together,
|
||||||
* like a Paint Brush. */
|
* like a Paint Brush. */
|
||||||
|
|
|
@ -122,14 +122,19 @@ class ItemsController < ApplicationController
|
||||||
return
|
return
|
||||||
end
|
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!
|
# Group the items by category!
|
||||||
@nc_mall_items = @items.select(&:currently_in_mall?).
|
@nc_mall_items = @items.select(&:currently_in_mall?).
|
||||||
reject(&:dyeworks_active?)
|
reject(&:dyeworks_buyable?)
|
||||||
@active_dyeworks_items = @items.select(&:dyeworks_active?)
|
@buyable_dyeworks_items = @items.select(&:dyeworks_buyable?)
|
||||||
@np_items = @items.select(&:np?)
|
@np_items = @items.select(&:np?)
|
||||||
@pb_items = @items.select(&:pb?)
|
@pb_items = @items.select(&:pb?)
|
||||||
@other_nc_items = @items.select(&:nc?).reject(&:currently_in_mall?).
|
@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.
|
# Start loading the NC trade values for the non-Mall NC items.
|
||||||
trade_values_task = Async { Item.preload_nc_trade_values(@other_nc_items) }
|
trade_values_task = Async { Item.preload_nc_trade_values(@other_nc_items) }
|
||||||
|
|
|
@ -156,22 +156,36 @@ module ItemsHelper
|
||||||
"Last updated: #{date_str} (#{time_ago_str} ago)"
|
"Last updated: #{date_str} (#{time_ago_str} ago)"
|
||||||
end
|
end
|
||||||
|
|
||||||
def nc_trade_value_subtitle_for(item)
|
NC_TRADE_VALUE_ESTIMATE_PATTERN = %r{
|
||||||
value = item.nc_trade_value
|
^\s*
|
||||||
return nil if value.nil?
|
(?:
|
||||||
|
# Case 1: A single number
|
||||||
link_to "Owls listing: #{item.nc_trade_value.value_text}",
|
(?<single>[0-9]+)
|
||||||
"https://www.neopets.com/~owls", target: "_blank",
|
|
|
||||||
title: 'Owls keeps track of approximate "capsule" values of NC items ' +
|
# Case 2: A range from low to high
|
||||||
"for trading. Items with similar values can often be traded for one " +
|
(?<low>[0-9]+)
|
||||||
"another. This is an estimate, not a rule!"
|
\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
|
end
|
||||||
|
|
||||||
def dyeworks_explanation_subtitle_for(item)
|
# Try to parse the NC trade value's text into something styled a bit more
|
||||||
base_item = item.dyeworks_base_item
|
# nicely for our use case.
|
||||||
content_tag :span, class: "dyeworks-explanation" do
|
def nc_trade_value_estimate_text(nc_trade_value)
|
||||||
concat link_to(base_item.name, base_item, target: "_blank")
|
match = nc_trade_value.value_text.match(NC_TRADE_VALUE_ESTIMATE_PATTERN)
|
||||||
concat " + 1 Potion"
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -203,11 +203,27 @@ class Item < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether this is a Dyeworks item whose base item can currently be purchased
|
# Whether this is a Dyeworks item whose base item can currently be purchased
|
||||||
# in the NC Mall, then dyed via Dyeworks.
|
# in the NC Mall. It may or may not currently be *dyeable* in the NC Mall,
|
||||||
def dyeworks_active?
|
# because Dyeworks eligibility is often a limited-time event.
|
||||||
|
def dyeworks_base_buyable?
|
||||||
dyeworks_base_item.present? && dyeworks_base_item.currently_in_mall?
|
dyeworks_base_item.present? && dyeworks_base_item.currently_in_mall?
|
||||||
end
|
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{
|
DYEWORKS_NAME_PATTERN = %r{
|
||||||
^(
|
^(
|
||||||
# Most Dyeworks items have a colon in the name.
|
# Most Dyeworks items have a colon in the name.
|
||||||
|
|
|
@ -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
|
%tr
|
||||||
%td.thumbnail-cell
|
%td.thumbnail-cell
|
||||||
|
@ -8,4 +12,4 @@
|
||||||
= link_to item.name, item, target: "_blank"
|
= link_to item.name, item, target: "_blank"
|
||||||
- if subtitle.present?
|
- if subtitle.present?
|
||||||
.subtitle= subtitle
|
.subtitle= subtitle
|
||||||
%td.actions-cell= yield
|
%td.actions-cell= content
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
[nc]: https://secure.nc.neopets.com/get-neocash
|
[nc]: https://secure.nc.neopets.com/get-neocash
|
||||||
[gc]: https://secure.nc.neopets.com/nickcash-cards
|
[gc]: https://secure.nc.neopets.com/nickcash-cards
|
||||||
|
|
||||||
%table.item-list
|
%table.item-list
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
= cart_icon alt: ""
|
= cart_icon alt: ""
|
||||||
Buy (#{item.current_nc_price} NC)
|
Buy (#{item.current_nc_price} NC)
|
||||||
|
|
||||||
- if @active_dyeworks_items.present?
|
- if @buyable_dyeworks_items.present?
|
||||||
%h2 Dyeworks items
|
%h2 Dyeworks items
|
||||||
:markdown
|
:markdown
|
||||||
These are recolored "Dyeworks" variants of items. First get the "base"
|
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
|
[Dyeworks][dyeworks] section of the NC Mall! Potions can also be bought in
|
||||||
bundles of 5 or 10.
|
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/
|
[dyeworks]: https://www.neopets.com/mall/dyeworks/
|
||||||
|
|
||||||
%table.item-list
|
%table.item-list
|
||||||
%thead
|
%thead
|
||||||
%td.thumbnail-cell
|
%td.thumbnail-cell
|
||||||
= image_tag "https://images.neopets.com/items/mall_80x80_cleaning.gif",
|
= image_tag "https://images.neopets.com/items/mall_80x80_cleaning.gif",
|
||||||
alt: "Dyeworks Hue Brew Potion"
|
alt: "Dyeworks Hue Brew Potion"
|
||||||
%th
|
%th
|
||||||
Total: #{dyeworks_nc_total_for @active_dyeworks_items} NC
|
Total: #{dyeworks_nc_total_for @buyable_dyeworks_items} NC
|
||||||
= surround "(", ")" do
|
= surround "(", ")" do
|
||||||
%span.price-breakdown{
|
%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{
|
%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
|
%td.actions-cell
|
||||||
%button{onclick: "alert('Todo!')"}
|
%button{onclick: "alert('Todo!')"}
|
||||||
= cart_icon alt: ""
|
= cart_icon alt: ""
|
||||||
Buy all in NC Mall
|
Buy all in NC Mall
|
||||||
%tbody
|
%tbody
|
||||||
- @active_dyeworks_items.each do |item|
|
- @buyable_dyeworks_items.each do |item|
|
||||||
= render "item_list_row", item:,
|
= render "item_list_row", item: do
|
||||||
subtitle: dyeworks_explanation_subtitle_for(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!')"}
|
%button{onclick: "alert('Todo!')"}
|
||||||
= cart_icon alt: ""
|
= cart_icon alt: ""
|
||||||
Buy base (#{item.dyeworks_base_item.current_nc_price} NC)
|
Buy base (#{item.dyeworks_base_item.current_nc_price} NC)
|
||||||
|
@ -81,6 +93,7 @@
|
||||||
[wiz]: https://www.neopets.com/shops/wizard.phtml
|
[wiz]: https://www.neopets.com/shops/wizard.phtml
|
||||||
[tp]: https://www.neopets.com/island/tradingpost.phtml?type=browse
|
[tp]: https://www.neopets.com/island/tradingpost.phtml?type=browse
|
||||||
[ag]: https://www.neopets.com/genie.phtml
|
[ag]: https://www.neopets.com/genie.phtml
|
||||||
|
|
||||||
%table.item-list
|
%table.item-list
|
||||||
%thead
|
%thead
|
||||||
%td
|
%td
|
||||||
|
@ -101,6 +114,7 @@
|
||||||
these items will be semi-permanently added to your Closet, even if your
|
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
|
pet changes color again! You can use this to mix-and-match styles for
|
||||||
"cross-paint" outfits.
|
"cross-paint" outfits.
|
||||||
|
|
||||||
- @pb_items_by_color.each do |color, items|
|
- @pb_items_by_color.each do |color, items|
|
||||||
%table.item-list{"data-group-type": "bundle"}
|
%table.item-list{"data-group-type": "bundle"}
|
||||||
%thead
|
%thead
|
||||||
|
@ -142,13 +156,21 @@
|
||||||
- if @other_nc_items.present?
|
- if @other_nc_items.present?
|
||||||
%h2 Neocash items (Capsules, events, retired, etc.)
|
%h2 Neocash items (Capsules, events, retired, etc.)
|
||||||
:markdown
|
:markdown
|
||||||
These items are part of the Neocash economy and can't be purchased with
|
These items are part of the Neocash economy, but not directly for sale.
|
||||||
Neopoints. We don't track all the details of how to get these items
|
Sometimes they're available in the [NC Mall][mall], via special
|
||||||
right now! Sometimes they're available via packs or capsules or events
|
bundles or events. Sometimes they're retired, and can only be obtained via
|
||||||
in the [NC Mall][mall]. Sometimes they're retired and can't be
|
gifts or trades.
|
||||||
purchased at all anymore, and can only be obtained via gifts or trades.
|
|
||||||
|
|
||||||
[mall]: https://ncmall.neopets.com/
|
[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
|
%table.item-list
|
||||||
%thead
|
%thead
|
||||||
%td
|
%td
|
||||||
|
@ -156,7 +178,24 @@
|
||||||
Total: #{pluralize @other_nc_items.size, "item"}
|
Total: #{pluralize @other_nc_items.size, "item"}
|
||||||
%tbody
|
%tbody
|
||||||
- @other_nc_items.each do |item|
|
- @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",
|
= button_link_to "NC Trades",
|
||||||
item_trades_path(item, type: "offering"),
|
item_trades_path(item, type: "offering"),
|
||||||
target: "_blank", icon: search_icon
|
target: "_blank", icon: search_icon
|
||||||
|
|
Loading…
Reference in a new issue