From b18d147418cf38b59f5868dd0a0910528af82234 Mon Sep 17 00:00:00 2001 From: Mattias Bodlund Date: Wed, 30 Apr 2025 14:53:50 +0200 Subject: [PATCH] na --- Gemfile.lock | 2 +- app/assets/stylesheets/application.css | 91 ++++++++++++++----- app/controllers/answers_controller.rb | 1 + .../concerns/quiz_helper_methods.rb | 11 ++- app/controllers/questions_controller.rb | 29 ++++++ app/models/answer.rb | 2 + app/models/player.rb | 28 ++++++ app/views/questions/answer.html.erb | 6 +- app/views/questions/result.html.erb | 28 ++++++ config/locales/en.yml | 4 + config/routes.rb | 2 + db/migrate/20250429085114_create_players.rb | 3 + db/schema.rb | 2 + 13 files changed, 184 insertions(+), 25 deletions(-) create mode 100644 app/views/questions/result.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index 26e8c88..62b76df 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -162,7 +162,7 @@ GEM i18n (>= 0.6.10, < 2) request_store (~> 1.0) msgpack (1.8.0) - net-imap (0.5.7) + net-imap (0.5.8) date net-protocol net-pop (0.1.2) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3fc4023..4be7087 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -89,7 +89,7 @@ --fs-lg: 1.8rem; --fs-xl: 2.8rem; --fs-2xl: 3.2rem; - --fs-3xl: 5.6rem; + --fs-3xl: 4.0rem; --fs-4xl: 9.0rem; --flip-deg: 0deg; @@ -107,13 +107,15 @@ body { display: flex; flex-direction: column; gap: 0; - min-height: 100svh; - justify-content: end; - position: relative; + min-height: 100svh; -webkit-font-smoothing: antialiased; touch-action: manipulation; } + + + + ul[class] { margin: 0 auto; padding: 0; @@ -122,11 +124,9 @@ ul[class] { header { - position: fixed; - top: 1.2rem; - left: 1.2rem; - - + padding: 1.2rem; + flex-grow: 0; + & svg { width: 70px; height: auto; @@ -219,7 +219,17 @@ footer { main { - margin: 1.2rem 1.2rem 1.6rem 1.2rem; + margin: 0 1.2rem 1.6rem 1.2rem; + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: end; +} + +@media (min-width: 474px) { + main { + justify-content: center; + } } .intro-container { @@ -235,6 +245,14 @@ main { grid-template-columns: 1; grid-template-rows: auto; gap: 8px; + + +} + +.intro-container, +.question-container { + max-width: 450px; + margin: 0 auto; } .intro-content-header, @@ -291,12 +309,7 @@ main { line-height: 1.4; padding: 1.6rem 1.2rem; - & em { - font-style: normal; - background-color: var(--clr-text-highlight); - padding: 1px 2px; - margin-right: -2px; - } + & input[type=radio] { position: absolute; @@ -312,15 +325,39 @@ main { } } -.question-result { +.question-container { + & em { + font-style: normal; + background-color: var(--clr-text-highlight); + padding: 1px 2px; + margin-right: -2px; + } + + & strong { + font-weight: 700; + } + +} + + +.question-result, .result-stats { background-color: var(--clr-medium-yellow); border-radius: 1.2rem; font-size: var(--fs-base); line-height: 1.4; padding: 1.6rem 1.2rem; + +} - & strong { - font-weight: 700; +.result-actions { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.8rem; + + & a { + background-color: var(--clr-medium-yellow); + border-color: var(--clr-medium-yellow); + color: var(--clr-black) } } @@ -353,8 +390,20 @@ main { font-size: 4rem; } } - +} +.result-msg { + background-color: var(--clr-white); + border-radius: 1.2rem; + font-size: var(--fs-base); + line-height: 1.4; + padding: 2.0rem 1.2rem; + + & h1 { + font-size: var(--fs-3xl); + line-height: 1.1; + margin: 0 0 0.4em 0; + } } @@ -395,7 +444,7 @@ label.question-answer { } main { - margin: 2rem 3rem; + margin: 0 2rem 3rem 2rem; } footer { diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index d4fbb35..ae22234 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -10,6 +10,7 @@ class AnswersController < ApplicationController respond_to do |format| if @answer.save + current_player.update_answer_cache format.html { redirect_to url_for(controller: 'questions', action: 'answer', id: params[:id]) } else format.html { render 'questions/show', status: :unprocessable_entity } diff --git a/app/controllers/concerns/quiz_helper_methods.rb b/app/controllers/concerns/quiz_helper_methods.rb index 3b8a991..4b1b41c 100644 --- a/app/controllers/concerns/quiz_helper_methods.rb +++ b/app/controllers/concerns/quiz_helper_methods.rb @@ -10,7 +10,8 @@ module QuizHelperMethods :question, :questions_size, :question_index, - :player_question_answer + :player_question_answer, + :result_node end @@ -19,7 +20,11 @@ private def questions - @questions ||= Node.at_depth(1).viewable.ordered.to_a + @questions ||= Node.at_depth(1).tmpl_article.viewable.ordered.to_a + end + + def result_node + @result_node ||= Node.at_depth(1).tmpl_list.viewable.first end @@ -63,4 +68,6 @@ private def player_present? current_player.present? end + + end diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 84dc039..c28b0aa 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -16,9 +16,38 @@ class QuestionsController < ApplicationController end + def result + not_found if result_node.blank? or current_player.answers.count < questions.size + + planet_score = 0 + + current_player.answers.ordered.each_with_index do |answer, i| + case i + when 0, 3 + planet_score += 1 if answer.value == 0 + else + planet_score += 1 if answer.value == 1 + end + end + + attachment_index = case + when planet_score < 2 + 0 # People + when planet_score > 3 + 1 # Planet + else + 2 # Balanced + end + + @result_attachment = result_node.attachments.offset(attachment_index).first + @stats_attachment = result_node.attachments.offset(3).first + + end + + end diff --git a/app/models/answer.rb b/app/models/answer.rb index 8013e39..6daf68a 100644 --- a/app/models/answer.rb +++ b/app/models/answer.rb @@ -6,4 +6,6 @@ class Answer < ApplicationRecord validates :value, presence: true validates :value, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 1 } + scope :ordered, -> { joins(:node).order('nodes.position ASC, nodes.ancestry ASC') } + end diff --git a/app/models/player.rb b/app/models/player.rb index 8284220..e17d071 100644 --- a/app/models/player.rb +++ b/app/models/player.rb @@ -4,4 +4,32 @@ class Player < ApplicationRecord has_many :answers, dependent: :destroy + + def update_answer_cache + self.update_column(:answer_cache, self.answers.ordered.pluck(:value)) + end + + + def stats + total_with_five = Player.where("array_length(answer_cache, 1) = 5") + .where.not(id: self.id) + .count + + matching_answers = Player.where(answer_cache: self.answer_cache) + .where("array_length(answer_cache, 1) = 5") + .where.not(id: self.id) + .count + + # Calculate percentage + if total_with_five > 0 + percentage = (matching_answers.to_f / total_with_five) * 100 + percentage_string = percentage.round.to_s + else + percentage_string = "0" + end + + percentage_string + + end + end diff --git a/app/views/questions/answer.html.erb b/app/views/questions/answer.html.erb index 5858c87..c147c08 100644 --- a/app/views/questions/answer.html.erb +++ b/app/views/questions/answer.html.erb @@ -23,6 +23,10 @@ <%= @question_answer.last.body.html_safe %> - <%= link_to t('next_question'), url_for(controller: 'questions', action: 'show', id: question_index), class: 'button__base' %> + <% if question == questions.last %> + <%= link_to t('see_results'), url_for(controller: 'questions', action: 'result'), class: 'button__base' %> + <% else %> + <%= link_to t('next_question'), url_for(controller: 'questions', action: 'show', id: question_index), class: 'button__base' %> + <% end %> \ No newline at end of file diff --git a/app/views/questions/result.html.erb b/app/views/questions/result.html.erb new file mode 100644 index 0000000..a87a04e --- /dev/null +++ b/app/views/questions/result.html.erb @@ -0,0 +1,28 @@ +<%- + content_for :title, result_node.page_title.blank? ? result_node.title : result_node.page_title + content_for :meta_description, result_node.page_description +%> + + +
+ +
+
<%= t 'results' %>
+
+ + + +
+ <%= @result_attachment&.body&.sub("<name>", html_escape(current_player.name)).html_safe %> +
+ +
+ <%= @stats_attachment&.body&.sub("<score>", current_player.stats).html_safe %> +
+ +
+ <%= link_to t('read_more'), "#", class: 'button__base' %> + <%= button_tag t('share_on_story'), type: 'button', class: 'button__base' %> +
+ +
\ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index ea04a5c..e65842f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -9,6 +9,10 @@ en: submit: Submit next_question: Next question of_people_worldwide_think_just_lik_you: of people worldwide think like you. + see_results: See results + results: Results + read_more: Read more + share_on_story: Share on story languages: diff --git a/config/routes.rb b/config/routes.rb index 1fadf57..cd37267 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -59,6 +59,8 @@ Rails.application.routes.draw do get 'q/:id/answer', to: 'questions#answer' get 'q/:id', to: 'questions#show' + get 'result', to: 'questions#result' + get '', to: 'languages#show' # get '*url', to: 'site#page', constraints: lambda { |req| req.path.exclude?('storage') } diff --git a/db/migrate/20250429085114_create_players.rb b/db/migrate/20250429085114_create_players.rb index 5fb4765..eee8105 100644 --- a/db/migrate/20250429085114_create_players.rb +++ b/db/migrate/20250429085114_create_players.rb @@ -4,8 +4,11 @@ class CreatePlayers < ActiveRecord::Migration[8.0] t.text :name t.text :locale + t.integer :answer_cache, array: true, default: [] t.timestamps + t.index :answer_cache, using: :gin end + end end diff --git a/db/schema.rb b/db/schema.rb index 56a56fc..a630c3f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -117,8 +117,10 @@ ActiveRecord::Schema[8.0].define(version: 2025_04_29_121602) do create_table "players", force: :cascade do |t| t.text "name" t.text "locale" + t.integer "answer_cache", default: [], array: true t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["answer_cache"], name: "index_players_on_answer_cache", using: :gin end create_table "users", force: :cascade do |t|