-
Notifications
You must be signed in to change notification settings - Fork 0
complite task timer #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: badge
Are you sure you want to change the base?
Changes from all commits
8216d5c
da0f41b
d5dd17b
a503017
a36efbe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,6 @@ | ||
| class SessionsController < Devise::SessionsController | ||
|
|
||
| def create | ||
| super | ||
| flash[:notice] = t('sessions_controller.welcome', name: resource.first_name || resource.email ) | ||
| flash[:notice] = t("sessions_controller.welcome", name: resource.first_name || resource.email) | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,19 @@ | ||
| class TestPassagesController < ApplicationController | ||
| before_action :authenticate_user! | ||
| before_action :set_test_passage, only: %i[ show result update ] | ||
| before_action :set_test_passage, only: %i[show result update] | ||
|
|
||
| def show; end | ||
|
|
||
| def result; end | ||
|
|
||
| def update | ||
| if @test_passage.question_any?(params) | ||
| @test_passage = TestPassage.find(params[:id]) | ||
|
|
||
| if @test_passage.time_over? | ||
| flash[:alert] = t("test_passages.times_up") | ||
|
|
||
| redirect_to result_test_passage_path(@test_passage) | ||
| elsif @test_passage.question_any?(params) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. если нет вопросов, значит тест завершился. А для этого есть уже подходящий метод #completed? который просто должен отвечать завершился ли тест. И не важно закончились вопросы и время. А сейчас получается что логику завершения теста не много размазали по коду |
||
| @test_passage.accept!(params[:answer_ids]) | ||
|
|
||
| completed_test | ||
|
|
@@ -16,6 +22,7 @@ def update | |
| end | ||
| end | ||
|
|
||
|
|
||
| private | ||
|
|
||
| def set_test_passage | ||
|
|
@@ -24,20 +31,22 @@ def set_test_passage | |
|
|
||
| def completed_test | ||
| if @test_passage.completed? | ||
|
|
||
| TestMailer.completed_test(@test_passage).deliver_later | ||
|
|
||
| if @test_passage.test_successful? | ||
| new_badges = BadgeAwardService.new(@test_passage).call | ||
|
|
||
| if new_badges.any? | ||
| flash[:notice] = t("test_passages.badge", name_badge: new_badges.map(&:title).join(", ")) | ||
| end | ||
| end | ||
|
|
||
| send_completion_notifications | ||
| award_badges | ||
| redirect_to result_test_passage_path(@test_passage) | ||
| else | ||
| redirect_to test_passage_path(@test_passage) | ||
| end | ||
| end | ||
|
|
||
| def send_completion_notifications | ||
| TestMailer.completed_test(@test_passage).deliver_later | ||
| end | ||
|
|
||
| def award_badges | ||
| new_badges = BadgeAwardService.new(@test_passage).call | ||
| return unless new_badges.any? | ||
|
|
||
| flash[:notice] = t("test_passages.badge", name_badge: new_badges.map(&:title).join(", ")) | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,9 @@ | ||
| module AnswersHelper | ||
|
|
||
| def answer_header(answer) | ||
| if answer.new_record? | ||
| t('answers_helper.create_new_answer') | ||
| t("answers_helper.create_new_answer") | ||
| else | ||
| t('answers_helper.edit_answer', body: answer.body ) | ||
| end | ||
| t("answers_helper.edit_answer", body: answer.body) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,9 @@ | ||
| module QuestionsHelper | ||
|
|
||
| def question_header(question) | ||
| if question.new_record? | ||
| t('question_helper.create_new_question', question_title: question.test.title ) | ||
| t("question_helper.create_new_question", question_title: question.test.title) | ||
| else | ||
| t('question_helper.edit_question', question_title: question.test.title ) | ||
| end | ||
| t("question_helper.edit_question", question_title: question.test.title) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,11 @@ | ||
| module TestPassagesHelper | ||
|
|
||
| def success_rate_message(test_passage) | ||
| if test_passage.test_successful? | ||
| content_tag(:h3, I18n.t('test_passages_helper.success_rate_message.success_test'), class: 'text-start md-4') + | ||
| I18n.t('test_passages_helper.success_rate_message.rate') + content_tag(:span, "#{test_passage.result_test}%", style: "color: green;") | ||
| content_tag(:h3, I18n.t("test_passages_helper.success_rate_message.success_test"), class: "text-start md-4") + | ||
| I18n.t("test_passages_helper.success_rate_message.rate") + content_tag(:span, "#{test_passage.result_test}%", style: "color: green;") | ||
| else | ||
| content_tag(:h3, I18n.t('test_passages_helper.success_rate_message.failed_test'), class: 'text-start') + | ||
| I18n.t('test_passages_helper.success_rate_message.rate') + content_tag(:span, "#{test_passage.result_test}%", style: "color: red;") | ||
| content_tag(:h3, I18n.t("test_passages_helper.success_rate_message.failed_test"), class: "text-start") + | ||
| I18n.t("test_passages_helper.success_rate_message.rate") + content_tag(:span, "#{test_passage.result_test}%", style: "color: red;") | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,9 @@ | ||
| module TestsHelper | ||
|
|
||
| def test_header(test) | ||
| if test.new_record? | ||
| t('tests_helper.create_new_test') | ||
| t("tests_helper.create_new_test") | ||
| else | ||
| t('tests_helper.edit_test', test_title: test.title) | ||
| end | ||
| t("tests_helper.edit_test", test_title: test.title) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| document.addEventListener("turbo:load", function() { | ||
| const timerElement = document.getElementById("timer"); | ||
| if (!timerElement) return; | ||
|
|
||
| const form = document.getElementById("test-passage-form"); | ||
| const initialMinutes = parseInt(timerElement.dataset.minutes) || 0; | ||
| const initialSeconds = parseInt(timerElement.dataset.seconds) || 0; | ||
| let totalSeconds = initialMinutes * 60 + initialSeconds; | ||
|
|
||
| function updateTimer() { | ||
| if (totalSeconds <= 0) { | ||
| clearInterval(timerInterval); | ||
| timerElement.textContent = "0:00"; | ||
|
|
||
| if (form) form.submit(); | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| totalSeconds--; | ||
| const minutes = Math.floor(totalSeconds / 60); | ||
| const seconds = totalSeconds % 60; | ||
| timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`; | ||
| } | ||
|
|
||
| const timerInterval = setInterval(updateTimer, 1000); | ||
|
|
||
| document.addEventListener("turbo:before-visit", () => { | ||
| clearInterval(timerInterval); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,8 @@ | ||
| class TestMailer < ApplicationMailer | ||
|
|
||
| def completed_test(test_passage) | ||
| @user = test_passage.user | ||
| @test = test_passage.test | ||
|
|
||
| mail to: @user.email | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,4 @@ | ||
| class Admin < User | ||
|
|
||
| validates :first_name, presence: true | ||
| validates :last_name, presence: true | ||
|
|
||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,4 @@ | ||
| class Answer < ApplicationRecord | ||
|
|
||
| belongs_to :question | ||
|
|
||
| validates :body, presence: true | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,7 @@ | ||
| class Category < ApplicationRecord | ||
|
|
||
| has_many :tests | ||
|
|
||
| validates :title, presence: true | ||
|
|
||
| default_scope { order(title: :asc) } | ||
|
|
||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,4 @@ | ||
| class Gist < ApplicationRecord | ||
|
|
||
| belongs_to :question | ||
| belongs_to :user | ||
|
|
||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,11 +7,49 @@ | |
|
|
||
| before_validation :set_current_question | ||
|
|
||
|
|
||
| def timer_enabled? | ||
| test.timer != 0 | ||
| end | ||
|
|
||
| def time_over? | ||
| return false unless timer_enabled? && !completed? | ||
| return false unless test_completion_time | ||
|
|
||
| Time.current >= test_completion_time | ||
| end | ||
|
|
||
| def test_completion_time | ||
| return unless test.timer.present? | ||
| created_at + (test.timer * 60) | ||
| end | ||
|
|
||
| def remaining_time | ||
| return unless timer_enabled? | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут тоже хочеться рубокоп запустить |
||
| [ test_completion_time - Time.current, 0 ].max.round | ||
| end | ||
|
|
||
| def remaining_minutes | ||
| return unless remaining_time | ||
| (remaining_time / 60).floor | ||
| end | ||
|
|
||
| def remaining_seconds | ||
| return unless remaining_time | ||
| remaining_time % 60 | ||
| end | ||
|
|
||
| def passed? | ||
| completed? && test_successful? | ||
| end | ||
|
|
||
| def accept!(answer_ids) | ||
| if time_over? | ||
| self.current_question = nil | ||
| save! | ||
| return | ||
| end | ||
|
|
||
| if correct_answer?(answer_ids) | ||
| self.correct_question += 1 | ||
| end | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
внутри if код разделяют отступами