module GameHelper
|
|
def frontend_javascript_importmap_tags(only_use = %w[application])
|
|
only_use = Array(only_use)
|
|
importmap_json = JSON.parse(Rails.application.importmap.to_json(resolver: self))["imports"].select { |k, v| only_use.include?(k) }
|
|
safe_join [
|
|
javascript_inline_importmap_tag(JSON.pretty_generate({ "imports" => importmap_json })),
|
|
javascript_module_preload_tag(*importmap_json.map { |v| v[1] }),
|
|
javascript_import_module_tag(only_use[0])
|
|
], "\n"
|
|
end
|
|
|
|
|
|
def node_title(node)
|
|
parts = [ node.page_title.blank? ? node.title : node.page_title ]
|
|
parts << t(:client_name)
|
|
parts.uniq.join(" - ")
|
|
rescue
|
|
t(:client_name)
|
|
end
|
|
|
|
|
|
def render_responsive_picture(asset = nil, alt: "", lazy: false, fetchpriority: nil)
|
|
return unless asset
|
|
|
|
widths = [ 800, 1600, 2400 ]
|
|
metadata = asset.file.metadata
|
|
|
|
image_tag(rails_storage_proxy_path(asset.file.variant(resize_to_limit: [ 1600, nil ], format: "webp")),
|
|
alt: alt,
|
|
srcset: responsive_srcset(asset, widths),
|
|
sizes: "100vw",
|
|
width: metadata[:width],
|
|
height: metadata[:height],
|
|
loading: ("lazy" if lazy),
|
|
fetchpriority: fetchpriority,
|
|
decoding: "async")
|
|
end
|
|
|
|
|
|
def responsive_srcset(asset, widths)
|
|
widths.map { |w|
|
|
"#{rails_storage_proxy_path(asset.file.variant(resize_to_limit: [ w, nil ], format: "webp"))} #{w}w"
|
|
}.join(", ")
|
|
end
|
|
|
|
|
|
RESULT_BANDS = [ [ 8, :best ], [ 5, :balanced ], [ 0, :worst ] ].freeze
|
|
|
|
def result_state(player)
|
|
if (answer_id = player.last_save_answer_id)
|
|
return last_save_result_state(answer_id)
|
|
end
|
|
|
|
overall = player.score.to_i
|
|
RESULT_BANDS.find { |threshold, _| overall >= threshold }.last
|
|
end
|
|
|
|
|
|
def result_headline(player)
|
|
t("game.results.#{result_state(player)}.headline").html_safe
|
|
end
|
|
|
|
|
|
def result_description(player)
|
|
t("game.results.#{result_state(player)}.description").html_safe
|
|
end
|
|
|
|
|
|
IMPACT_TONE_BANDS = {
|
|
default: [ [ 3, :positive ], [ 1, :neutral ], [ -Float::INFINITY, :negative ] ],
|
|
income: [ [ 2, :positive ], [ 0, :neutral ], [ -Float::INFINITY, :negative ] ]
|
|
}.freeze
|
|
|
|
def impact_tone(player, category)
|
|
score = player.score_for(category)
|
|
bands = IMPACT_TONE_BANDS[category] || IMPACT_TONE_BANDS[:default]
|
|
bands.find { |threshold, _| score >= threshold }.last
|
|
end
|
|
|
|
|
|
def impact_label(category)
|
|
t("game.results.#{category}.label")
|
|
end
|
|
|
|
|
|
def impact_message(player, category)
|
|
if category == :income && player.last_save_answer_id.present?
|
|
return t("game.results.income.early_exit")
|
|
end
|
|
|
|
t("game.results.#{category}.#{impact_tone(player, category)}")
|
|
end
|
|
|
|
|
|
def impact_learn_more(category)
|
|
t("game.results.#{category}.learn_more")
|
|
end
|
|
|
|
|
|
private
|
|
|
|
def last_save_result_state(answer_id)
|
|
answer = Node.find_by(id: answer_id)
|
|
config = JSON.parse(Rails.root.join("config", "question_scores.json").read)
|
|
type = config.dig("last_save", "answers", answer.position - 1, "result_type") if answer
|
|
type&.to_sym || :compost
|
|
end
|
|
end
|