oh yum, this is really starting to come together :)
This commit is contained in:
parent
85e1973f55
commit
9a4e114964
5 changed files with 196 additions and 18 deletions
|
@ -139,11 +139,34 @@ body.outfits-new
|
||||||
#whats-new
|
#whats-new
|
||||||
margin-bottom: 1em
|
margin-bottom: 1em
|
||||||
|
|
||||||
#newest-items
|
h3
|
||||||
|
font-size: 125%
|
||||||
|
font-style: italic
|
||||||
|
margin-bottom: .5em
|
||||||
|
|
||||||
|
#newest-modeled-items
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
.object
|
||||||
|
margin: 2px
|
||||||
|
padding: 0
|
||||||
|
width: 80px
|
||||||
|
|
||||||
|
.name
|
||||||
|
display: none
|
||||||
|
|
||||||
|
img
|
||||||
|
margin: 0
|
||||||
|
|
||||||
|
.nc-icon
|
||||||
|
right: 0
|
||||||
|
|
||||||
|
#newest-unmodeled-items
|
||||||
list-style: none
|
list-style: none
|
||||||
|
|
||||||
li
|
li
|
||||||
+clearfix
|
+clearfix
|
||||||
|
margin: .5em 0
|
||||||
|
|
||||||
a.header
|
a.header
|
||||||
background: $module-bg-color
|
background: $module-bg-color
|
||||||
|
@ -153,7 +176,7 @@ body.outfits-new
|
||||||
color: white
|
color: white
|
||||||
display: block
|
display: block
|
||||||
margin-left: 81px
|
margin-left: 81px
|
||||||
padding: .5em .75em
|
padding: .5em 8px
|
||||||
position: relative
|
position: relative
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
text-shadow: $text-color 1px 1px 2px
|
text-shadow: $text-color 1px 1px 2px
|
||||||
|
@ -185,6 +208,14 @@ body.outfits-new
|
||||||
height: 80px
|
height: 80px
|
||||||
width: 80px
|
width: 80px
|
||||||
|
|
||||||
|
.missing-bodies
|
||||||
|
font-size: 85%
|
||||||
|
margin-left: 82px
|
||||||
|
padding: .5em 8px
|
||||||
|
p
|
||||||
|
font-family: $main-font
|
||||||
|
margin-bottom: .5em
|
||||||
|
|
||||||
#latest-contribution
|
#latest-contribution
|
||||||
+subtle-banner
|
+subtle-banner
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,25 @@ class OutfitsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
unless localized_fragment_exist?('outfits#new newest_items')
|
unless localized_fragment_exist?('outfits#new newest_items')
|
||||||
@newest_items = Item.newest.select([:id, :thumbnail_url]).
|
newest_items = Item.newest.select([:id, :thumbnail_url, :rarity_index]).
|
||||||
includes(:translations).limit(9)
|
includes(:translations).limit(18)
|
||||||
|
@newest_modeled_items, @newest_unmodeled_items =
|
||||||
|
newest_items.partition(&:predicted_fully_modeled?)
|
||||||
|
|
||||||
|
@newest_unmodeled_items_predicted_missing_species_by_color = {}
|
||||||
|
@newest_unmodeled_items_predicted_modeled_ratio = {}
|
||||||
|
@newest_unmodeled_items.each do |item|
|
||||||
|
h = item.predicted_missing_nonstandard_body_species_by_color(
|
||||||
|
Color.includes(:translations).select([:id]),
|
||||||
|
Species.includes(:translations).select([:id]))
|
||||||
|
standard_species = item.predicted_missing_standard_body_species.
|
||||||
|
select([:id]).includes(:translations)
|
||||||
|
h[:standard] = standard_species if standard_species.present?
|
||||||
|
@newest_unmodeled_items_predicted_missing_species_by_color[item] = h
|
||||||
|
@newest_unmodeled_items_predicted_modeled_ratio[item] = item.predicted_modeled_ratio
|
||||||
|
end
|
||||||
|
|
||||||
|
@species_count = Species.count
|
||||||
end
|
end
|
||||||
|
|
||||||
unless localized_fragment_exist?('outfits#new latest_contribution')
|
unless localized_fragment_exist?('outfits#new latest_contribution')
|
||||||
|
|
|
@ -54,6 +54,27 @@ module OutfitsHelper
|
||||||
"http://#{Rails.configuration.neopia_host}/api/1/pet/customization"
|
"http://#{Rails.configuration.neopia_host}/api/1/pet/customization"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_predicted_missing_species_by_color(species_by_color)
|
||||||
|
# TODO: i18n
|
||||||
|
standard = species_by_color.delete(:standard)
|
||||||
|
sorted_pairs = species_by_color.to_a.map { |k, v| [k.human_name, v] }.
|
||||||
|
sort_by { |k, v| k }
|
||||||
|
sorted_pairs.unshift(['', standard]) if standard
|
||||||
|
species_by_color[:standard] = standard # undo mutation
|
||||||
|
|
||||||
|
first = true
|
||||||
|
contents = sorted_pairs.map { |color_human_name, species|
|
||||||
|
species_sentence = species.map(&:human_name).sort.to_sentence(
|
||||||
|
two_words_connector: ' or ', last_word_connector: ', or ')
|
||||||
|
content = first ? "Have you seen the #{color_human_name} #{species_sentence} wearing this item?" : "Or maybe the #{color_human_name} #{species_sentence}?"
|
||||||
|
first = false
|
||||||
|
content
|
||||||
|
}
|
||||||
|
contents.last << " If so, please model it above! Thanks!"
|
||||||
|
content_tags = contents.map { |c| content_tag(:p, c) }
|
||||||
|
content_tags.join('').html_safe
|
||||||
|
end
|
||||||
|
|
||||||
def outfit_creation_summary(outfit)
|
def outfit_creation_summary(outfit)
|
||||||
user = outfit.user
|
user = outfit.user
|
||||||
user_link = link_to(user.name, user_contributions_path(user))
|
user_link = link_to(user.name, user_contributions_path(user))
|
||||||
|
|
|
@ -193,11 +193,9 @@ class Item < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def supported_species_ids
|
def supported_species_ids
|
||||||
body_ids = swf_assets.select([:body_id]).map(&:body_id)
|
return Species.select([:id]).map(&:id) if modeled_body_ids.include?(0)
|
||||||
|
|
||||||
return Species.select([:id]).map(&:id) if body_ids.include?(0)
|
pet_types = PetType.where(:body_id => modeled_body_ids).select('DISTINCT species_id')
|
||||||
|
|
||||||
pet_types = PetType.where(:body_id => body_ids).select('DISTINCT species_id')
|
|
||||||
species_ids = pet_types.map(&:species_id)
|
species_ids = pet_types.map(&:species_id)
|
||||||
|
|
||||||
# If there are multiple known supported species, it probably supports them
|
# If there are multiple known supported species, it probably supports them
|
||||||
|
@ -209,6 +207,106 @@ class Item < ActiveRecord::Base
|
||||||
species_support_ids.blank? || species_support_ids.include?(species.id)
|
species_support_ids.blank? || species_support_ids.include?(species.id)
|
||||||
end
|
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 modeled_colors
|
||||||
|
@modeled_colors ||= Color.select([:id, :standard]).find(modeled_color_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
def modeled_standard_colors?
|
||||||
|
modeled_colors.any?(&:standard)
|
||||||
|
end
|
||||||
|
|
||||||
|
def modeled_nonstandard_colors
|
||||||
|
modeled_colors.reject(&:standard)
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_body_ids
|
||||||
|
@predicted_body_ids ||= if modeled_body_ids.include?(0)
|
||||||
|
# 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
|
||||||
|
# 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
|
||||||
|
# behavior elsewhere in the app by saying that we can put this item on
|
||||||
|
# anybody. (Heh. Any body.))
|
||||||
|
modeled_body_ids
|
||||||
|
elsif modeled_body_ids.size == 1
|
||||||
|
# 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.
|
||||||
|
modeled_body_ids
|
||||||
|
else
|
||||||
|
# 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
|
||||||
|
# of any exceptions.) So, let's find those bodies by first finding those
|
||||||
|
# colors.
|
||||||
|
PetType.select('DISTINCT body_id').
|
||||||
|
where(color_id: modeled_color_ids).
|
||||||
|
map(&:body_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_missing_body_ids
|
||||||
|
@predicted_missing_body_ids ||= predicted_body_ids - modeled_body_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_missing_standard_body_species_ids
|
||||||
|
PetType.select('DISTINCT species_id').
|
||||||
|
joins(:color).
|
||||||
|
where(body_id: predicted_missing_body_ids,
|
||||||
|
colors: {standard: true}).
|
||||||
|
map(&:species_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_missing_standard_body_species
|
||||||
|
Species.where(id: predicted_missing_standard_body_species_ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_missing_nonstandard_body_pet_types
|
||||||
|
PetType.joins(:color).
|
||||||
|
where(body_id: predicted_missing_body_ids,
|
||||||
|
colors: {standard: false})
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_missing_nonstandard_body_species_by_color(colors_scope=Color.scoped, species_scope=Species.scoped)
|
||||||
|
pet_types = predicted_missing_nonstandard_body_pet_types
|
||||||
|
|
||||||
|
species_by_id = {}
|
||||||
|
species_scope.find(pet_types.map(&:species_id)).each do |species|
|
||||||
|
species_by_id[species.id] = species
|
||||||
|
end
|
||||||
|
|
||||||
|
colors_by_id = {}
|
||||||
|
colors_scope.find(pet_types.map(&:color_id)).each do |color|
|
||||||
|
colors_by_id[color.id] = color
|
||||||
|
end
|
||||||
|
|
||||||
|
species_by_color = {}
|
||||||
|
pet_types.each do |pt|
|
||||||
|
color = colors_by_id[pt.color_id]
|
||||||
|
species_by_color[color] ||= []
|
||||||
|
species_by_color[color] << species_by_id[pt.species_id]
|
||||||
|
end
|
||||||
|
species_by_color
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_fully_modeled?
|
||||||
|
predicted_missing_body_ids.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def predicted_modeled_ratio
|
||||||
|
modeled_body_ids.size.to_f / predicted_body_ids.size
|
||||||
|
end
|
||||||
|
|
||||||
def as_json(options={})
|
def as_json(options={})
|
||||||
json = {
|
json = {
|
||||||
:description => description,
|
:description => description,
|
||||||
|
|
|
@ -75,16 +75,27 @@
|
||||||
#whats-new
|
#whats-new
|
||||||
-# TODO: remove newest_items.header i18n key?
|
-# TODO: remove newest_items.header i18n key?
|
||||||
- localized_cache 'outfits#new newest_items' do
|
- localized_cache 'outfits#new newest_items' do
|
||||||
%ul#newest-items
|
- if @newest_unmodeled_items.present?
|
||||||
- @newest_items.each do |item|
|
%h3 We need your help! Can you model these items?
|
||||||
%li
|
%ul#newest-unmodeled-items
|
||||||
= link_to image_tag(item.thumbnail_url), item, :class => 'image-link'
|
- @newest_unmodeled_items.each do |item|
|
||||||
= link_to item, :class => 'header' do
|
%li
|
||||||
- lolremove = rand(54)
|
= link_to image_tag(item.thumbnail_url), item, :class => 'image-link'
|
||||||
-# TODO: i18n
|
= link_to item, :class => 'header' do
|
||||||
%h2= item.name
|
-# TODO: i18n
|
||||||
-#: we need #{lolremove} more models
|
%h2= item.name
|
||||||
%span.meter{style: "width: #{100-lolremove/0.54}%"}
|
-#: we need #{lolremove} more models
|
||||||
|
%span.meter{style: "width: #{@newest_unmodeled_items_predicted_modeled_ratio[item]*100}%"}
|
||||||
|
.missing-bodies
|
||||||
|
= render_predicted_missing_species_by_color(@newest_unmodeled_items_predicted_missing_species_by_color[item])
|
||||||
|
- if @newest_modeled_items.present?
|
||||||
|
%h3 These items have already been modeled—thanks for your help!
|
||||||
|
%ul#newest-modeled-items
|
||||||
|
- @newest_modeled_items.each do |item|
|
||||||
|
%li.object
|
||||||
|
= link_to item, title: item.name, alt: item.name do
|
||||||
|
= image_tag item.thumbnail_url
|
||||||
|
= nc_icon_for(item)
|
||||||
|
|
||||||
|
|
||||||
- localized_cache :action_suffix => 'templates' do
|
- localized_cache :action_suffix => 'templates' do
|
||||||
|
|
Loading…
Reference in a new issue