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