From 0e6ed040d7c4d1a9ea05b31fdeb171c94d8be328 Mon Sep 17 00:00:00 2001 From: Mattias Bodlund Date: Fri, 18 Sep 2026 16:42:59 +0200 Subject: [PATCH] na --- AGENTS.md | 12 +--- Gemfile.lock | 8 +-- app/assets/stylesheets/analytics.css | 16 +---- app/assets/stylesheets/application.css | 66 ++----------------- app/controllers/game_controller.rb | 9 --- app/javascript/application.js | 2 - app/models/player.rb | 20 ------ app/services/game_analytics.rb | 23 ------- app/views/admin/analytics/index.html.erb | 24 ------- app/views/game/results.html.erb | 25 ++----- app/views/layouts/application.html.erb | 4 +- app/views/shared/_dev_jump.html.erb | 2 +- config/importmap.rb | 1 - config/locales/cs.yml | 4 +- config/locales/da.yml | 4 +- config/locales/de.yml | 4 +- config/locales/en.yml | 4 +- config/locales/es.yml | 4 +- config/locales/fi.yml | 4 +- config/locales/fr-CA.yml | 4 +- config/locales/fr.yml | 4 +- config/locales/hr.yml | 4 +- config/locales/hu.yml | 4 +- config/locales/it.yml | 4 +- config/locales/ja.yml | 4 +- config/locales/ko.yml | 4 +- config/locales/nb.yml | 4 +- config/locales/nl.yml | 4 +- config/locales/pl.yml | 4 +- config/locales/pt.yml | 4 +- config/locales/ro.yml | 4 +- config/locales/sk.yml | 4 +- config/locales/sl.yml | 4 +- config/locales/sr.yml | 4 +- config/locales/sv.yml | 4 +- config/locales/uk.yml | 4 +- config/locales/zh.yml | 4 +- config/routes.rb | 1 - ...260918120000_remove_rating_from_players.rb | 9 +++ db/schema.rb | 5 +- 40 files changed, 103 insertions(+), 220 deletions(-) create mode 100644 db/migrate/20260918120000_remove_rating_from_players.rb diff --git a/AGENTS.md b/AGENTS.md index e4a322f..8c04409 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,8 +17,7 @@ This project is a Ruby on Rails application developed for the IKEA Foundation. I the next stage. Mobile only. See below. - **Scoring:** Answer scores live in `config/question_scores.json`, not in the database. See below. - **Analytics:** An admin dashboard at `/admin/:locale/analytics` reporting funnel drop-off, - answer distribution, the results-screen thumbs vote and who played — device, language and - country. See below. + answer distribution and who played — device, language and country. See below. - **Admin Interface:** A backend for managing nodes, assets (Active Storage), users, and translations. - **Search:** `pg_search` integration for content discovery. @@ -39,8 +38,7 @@ This project is a Ruby on Rails application developed for the IKEA Foundation. I - **Level 3 (outcomes under a chance):** `good_answer`, `bad_answer` - `Player`: Tracks session state, `progress` (per-stage `answer_id` / `result_id`), the cumulative `score`, the `scores` hash keyed by `food_waste`, `emissions`, `income`, - the furthest screen reached (`furthest_step`), the `device` class they played on and - the results-screen thumbs vote (`rating` / `rated_at`). + the furthest screen reached (`furthest_step`) and the `device` class they played on. - `Asset` & `Attachment`: Handles media and its contextual content (body text, styling) associated with nodes. - `User`: Admin authentication and roles. @@ -151,12 +149,6 @@ is pinned to the bottom of the panel so the QR rows stay together at the top. **Not counted here:** the board game QR points at `dice.ikeafoundation.org`, a different app. Its `utm_content=board_game` scans are recorded there, not in this dashboard. -### Thumbs up / down - -`Player#rate!` stores `rating` as `1` / `-1` (`Player::RATINGS`), one per player — voting -again overwrites. The results screen posts to `game#rate` via `rating_controller.js`, which -flips the button state immediately and does not await the response. - ## Screens and animation Every screen lives inside the single `turbo-frame#game`, so there is no page render to hang an diff --git a/Gemfile.lock b/Gemfile.lock index af17c62..a989369 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -134,7 +134,7 @@ GEM actionpack (>= 6.0.0) activesupport (>= 6.0.0) railties (>= 6.0.0) - io-console (0.9.3) + io-console (0.9.4) irb (1.18.0) pp (>= 0.6.0) prism (>= 1.3.0) @@ -186,7 +186,7 @@ GEM net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.3.0) + net-protocol (0.4.0) timeout net-smtp (0.5.1) net-protocol @@ -464,7 +464,7 @@ CHECKSUMS i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5 image_processing (1.14.0) sha256=754cc169c9c262980889bec6bfd325ed1dafad34f85242b5a07b60af004742fb importmap-rails (2.2.3) sha256=7101be2a4dc97cf1558fb8f573a718404c5f6bcfe94f304bf1f39e444feeb16a - io-console (0.9.3) sha256=f555049461b0afb78a5448b5be8e7c7b48371347cd48abfc22814764160000dd + io-console (0.9.4) sha256=a403304f32928ee85e56d457b4612ca43f2703b561a3258844992bd24085fbb1 irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3 jbuilder (2.15.1) sha256=2430bec28fb0cebacb5875b1009cf9d8bc3c303ccb810c4c8b062a4b51457637 json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a @@ -486,7 +486,7 @@ CHECKSUMS msgpack (1.8.5) sha256=97419eaa7b35dfe3e462c0e6c1a3dfdcbfc8756605c09e46e4c6daef127517ba net-imap (0.6.7) sha256=b5c9573be975d856de252ee851871724da66aa2d449b2482d5690bd12bc23660 net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3 - net-protocol (0.3.0) sha256=ba310c3d4f1cad46bb1ab20336b06669b1ff8f7c568d9cb9342b32a718547472 + net-protocol (0.4.0) sha256=f9f90c8c6f64794a45160bf422177a336db12809de3beeeaa26b88fcd2e8c853 net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736 nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1 nokogiri (1.19.4-aarch64-linux-gnu) sha256=1269fb644a6de405057a53dd5c762b1209b43ca7424f839454d3dbc677c31a8f diff --git a/app/assets/stylesheets/analytics.css b/app/assets/stylesheets/analytics.css index 53cf44e..d7e009f 100644 --- a/app/assets/stylesheets/analytics.css +++ b/app/assets/stylesheets/analytics.css @@ -223,21 +223,7 @@ } -/* ------------------------------------------------------------ split & stage */ - -.analytics-split { - display: flex; - height: 14px; - border-radius: 3px; - overflow: hidden; - margin-top: 1.25rem; - background: var(--clr-grey-200); -} - -.analytics-split-part { - &.positive { background: var(--analytics-positive); } - &.negative { background: var(--analytics-negative); } -} +/* ------------------------------------------------------------------- stage */ .analytics-stage { margin-top: 2rem; diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1ed3af0..5941b91 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1456,48 +1456,6 @@ dialog::backdrop { } } -.like-container { - margin: 0 1rem 1.5rem 1rem; - - & h3 { - font: var(--td-base); - font-weight: 700; - margin: 0 0 0.5rem 0; - } - - & > div { - display: flex; - gap: 0.5rem; - } - - button { - appearance: none; - border-radius: 50%; - width: 40px; - aspect-ratio: 1; - border: 1px solid var(--clr-black); - background-color: transparent; - display: flex; - justify-content: center; - align-items: center; - - &.thumbs-down { - & svg { - rotate: 180deg; - } - } - - &.is-selected { - background-color: var(--clr-green); - border-color: var(--clr-green); - - & svg { - fill: var(--clr-black); - } - } - } -} - .newsletter-container { margin: 0 1rem 2rem 1rem; @@ -1512,14 +1470,8 @@ dialog::backdrop { color: var(--clr-black); text-decoration: none; - & span:has(svg) { + & .arrow { background-color: var(--clr-green); - width: 32px; - height: 32px; - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 50%; } } } @@ -1883,6 +1835,9 @@ dialog::backdrop { transform: rotate(90deg) translate(345px, -174px) scaleX(-1); } } + .newsletter-container a .arrow { + background-color: var(--clr-white); + } .cta-container { gap: 1rem; padding-bottom: 2.5rem; @@ -1891,19 +1846,6 @@ dialog::backdrop { } } } - - .like-container { - button { - &.is-selected { - background-color: var(--clr-white); - border-color: var(--clr-white); - - & svg { - fill: var(--clr-black); - } - } - } - } } .debug-score { diff --git a/app/controllers/game_controller.rb b/app/controllers/game_controller.rb index c14ec85..43de771 100644 --- a/app/controllers/game_controller.rb +++ b/app/controllers/game_controller.rb @@ -122,15 +122,6 @@ class GameController < ApplicationController end - # POST -- thumbs up / down on the results screen. One rating per player; - # tapping the other thumb (or the same one again) just overwrites it. - def rate - current_player.rate!(params[:direction]) - - head :no_content - end - - private diff --git a/app/javascript/application.js b/app/javascript/application.js index ea1feab..4910960 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -7,7 +7,6 @@ import IntroController from "intro_controller" import ChanceController from "chance_controller" import ShareController from "share_controller" import ModalController from "modal_controller" -import RatingController from "rating_controller" import StartController from "start_controller" import AnswerController from "answer_controller" @@ -19,7 +18,6 @@ application.register("intro", IntroController) application.register("chance", ChanceController) application.register("share", ShareController) application.register("modal", ModalController) -application.register("rating", RatingController) application.register("start", StartController) application.register("answer", AnswerController) diff --git a/app/models/player.rb b/app/models/player.rb index b835b6a..3c2c60d 100644 --- a/app/models/player.rb +++ b/app/models/player.rb @@ -7,8 +7,6 @@ class Player < ApplicationRecord SCORE_KEYS = %w[food_waste emissions income].freeze - RATINGS = { up: 1, down: -1 }.freeze - # Campaign tags carried in from the printed QR codes. See UtmTracking. UTM_KEYS = %i[utm_source utm_medium utm_campaign utm_content].freeze @@ -21,11 +19,6 @@ class Player < ApplicationRecord STEP_RANKS = { "start" => 0, "facts" => 1, "intro" => 2, "last_save" => 900, "done" => 901, "results" => 902 }.freeze - scope :rated, -> { where.not(rating: nil) } - scope :thumbs_up, -> { where(rating: RATINGS[:up]) } - scope :thumbs_down, -> { where(rating: RATINGS[:down]) } - - # Stage screens interleave: stage 1 (10), its result (11), stage 2 (12)... # Everything before stages sits below 10, everything after above 900. def self.step_rank(step) @@ -50,19 +43,6 @@ class Player < ApplicationRecord end - def rate!(direction) - value = RATINGS[direction.to_s.to_sym] - return false unless value - - update(rating: value, rated_at: Time.current) - end - - - def rating_direction - RATINGS.key(rating) - end - - # ---------------------------------------------------------------- device diff --git a/app/services/game_analytics.rb b/app/services/game_analytics.rb index 24bb659..8d40550 100644 --- a/app/services/game_analytics.rb +++ b/app/services/game_analytics.rb @@ -52,29 +52,6 @@ class GameAnalytics def completion_rate = percent(completed_players, total_players) - # ---------------------------------------------------------------- ratings - - def ratings - @ratings ||= begin - counts = players.rated.group(:rating).count - up = counts[Player::RATINGS[:up]].to_i - down = counts[Player::RATINGS[:down]].to_i - - { - up: up, - down: down, - total: up + down, - up_share: percent(up, up + down), - down_share: percent(down, up + down), - # Share of people who saw the results screen and bothered to vote. A vote - # proves the player got there, so it also acts as the floor on reach -- - # players backfilled from before step tracking stop at "done". - response_rate: percent(up + down, [ reached("results"), up + down ].max) - } - end - end - - # ----------------------------------------------------------------- funnel # One row per screen, with how many players got that far and how many were diff --git a/app/views/admin/analytics/index.html.erb b/app/views/admin/analytics/index.html.erb index 703d036..d9e61d6 100644 --- a/app/views/admin/analytics/index.html.erb +++ b/app/views/admin/analytics/index.html.erb @@ -37,30 +37,6 @@ -
-

Did you like this game?

- - <% ratings = @analytics.ratings %> - <% if ratings[:total].zero? %> -

No votes yet.

- <% else %> -
- <%= render "card", label: "Thumbs up", value: number_with_delimiter(ratings[:up]), - sub: "#{ratings[:up_share]}%", modifier: "positive" %> - <%= render "card", label: "Thumbs down", value: number_with_delimiter(ratings[:down]), - sub: "#{ratings[:down_share]}%", modifier: "negative" %> - <%= render "card", label: "Votes", value: number_with_delimiter(ratings[:total]), - sub: "#{ratings[:response_rate]}% of players who reached the results" %> -
- -
-
-
-
- <% end %> -
- -

Funnel

diff --git a/app/views/game/results.html.erb b/app/views/game/results.html.erb index b0c765a..7a5d0f5 100644 --- a/app/views/game/results.html.erb +++ b/app/views/game/results.html.erb @@ -64,29 +64,18 @@ -

-
- <%= link_to tag.span(t("game.subscribe_to_newsletter")), "https://www.ikeafoundation.org/newsletter", class: "cta cta-link", target: "_blank" %> + <%= link_to tag.span(t("game.learn_more")), t("game.learn_more_url"), class: "cta cta-link", target: "_blank" %> <%= button_to start_path(skip_facts: true), class: "cta" do %> <%= tag.span(t("game.save_another_tomato")) %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5f3c41f..3073edb 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -17,7 +17,7 @@ <%= stylesheet_link_tag "reset", "application" %> - <%= frontend_javascript_importmap_tags %w[application @hotwired/turbo-rails @hotwired/stimulus language_menu_controller carousel_controller intro_controller chance_controller share_controller modal_controller rating_controller start_controller answer_controller] %> + <%= frontend_javascript_importmap_tags %w[application @hotwired/turbo-rails @hotwired/stimulus language_menu_controller carousel_controller intro_controller chance_controller share_controller modal_controller start_controller answer_controller] %> <%= turbo_frame_tag "game" do %> @@ -46,6 +46,6 @@ <% end %> <% end %> - <%# render "shared/dev_jump" if Rails.env.development? %> + <%= render "shared/dev_jump" if Rails.env.development? %> diff --git a/app/views/shared/_dev_jump.html.erb b/app/views/shared/_dev_jump.html.erb index 8df4651..1a3d52f 100644 --- a/app/views/shared/_dev_jump.html.erb +++ b/app/views/shared/_dev_jump.html.erb @@ -39,7 +39,7 @@