diff --git a/app/controllers/contests_controller.rb b/app/controllers/contests_controller.rb index 40c0fd9..a98aa83 100644 --- a/app/controllers/contests_controller.rb +++ b/app/controllers/contests_controller.rb @@ -1,4 +1,6 @@ class ContestsController < ApplicationController + include CompletionsConcern + before_action :set_contest, only: %i[ destroy edit show update ] before_action :offline_setup, only: %i[ offline_new offline_create offline_edit offline_update offline_completed ] skip_before_action :require_authentication, only: %i[ scoreboard offline_new offline_create offline_edit offline_update offline_completed ] @@ -139,8 +141,18 @@ class ContestsController < ApplicationController end @offline.completed = true + @offline.end_time = Time.now() @offline.images.attach(params[:offline][:end_image]) if @offline.save + if @contest.puzzles.length > 0 + dp = display_time(@offline.end_time.to_i - @offline.start_time.to_i) + contestant = Contestant.create(contest: @contest, name: @offline.name, offline: @offline) + Completion.create(contest: @contest, + contestant: contestant, + puzzle: @contest.puzzles[0], + display_time_from_start: dp) + extend_completions!(contestant) + end redirect_to "/public/#{@contest.friendly_id}/offline/#{@offline.generate_token_for(:token)}/completed" else render :offline_edit, status: :unprocessable_entity diff --git a/app/models/contestant.rb b/app/models/contestant.rb index 5e6751f..89ec326 100644 --- a/app/models/contestant.rb +++ b/app/models/contestant.rb @@ -22,6 +22,7 @@ class Contestant < ApplicationRecord belongs_to :contest has_many :completions, dependent: :destroy + has_one :offline has_and_belongs_to_many :categories before_validation :initialize_time_seconds_if_empty diff --git a/app/models/offline.rb b/app/models/offline.rb index 1baed99..9f366b9 100644 --- a/app/models/offline.rb +++ b/app/models/offline.rb @@ -2,25 +2,29 @@ # # Table name: offlines # -# id :integer not null, primary key -# completed :boolean -# end_time :datetime -# name :string not null -# start_time :datetime not null -# created_at :datetime not null -# updated_at :datetime not null -# contest_id :integer not null +# id :integer not null, primary key +# completed :boolean +# end_time :datetime +# name :string not null +# start_time :datetime not null +# created_at :datetime not null +# updated_at :datetime not null +# contest_id :integer not null +# contestant_id :integer # # Indexes # -# index_offlines_on_contest_id (contest_id) +# index_offlines_on_contest_id (contest_id) +# index_offlines_on_contestant_id (contestant_id) # # Foreign Keys # -# contest_id (contest_id => contests.id) +# contest_id (contest_id => contests.id) +# contestant_id (contestant_id => contestants.id) # class Offline < ApplicationRecord belongs_to :contest + belongs_to :contestant, optional: true has_many_attached :images diff --git a/app/views/contests/offline_edit.html.slim b/app/views/contests/offline_edit.html.slim index 22a8051..f32b07e 100644 --- a/app/views/contests/offline_edit.html.slim +++ b/app/views/contests/offline_edit.html.slim @@ -13,7 +13,7 @@ displayTimeEl.innerHTML = `${hh < 10 ? `0${hh}` : hh}:${mm < 10 ? `0${mm}` : mm}:${ss < 10 ? `0${ss}` : ss}`; setTimeout(updateTime, 1000); } - setTimeout(updateTime, 5); + setTimeout(updateTime, 50); .row.mt-5.mb-3 .col .form-text.mb-1 diff --git a/app/views/contests/show.html.slim b/app/views/contests/show.html.slim index 12803b4..4299dc7 100644 --- a/app/views/contests/show.html.slim +++ b/app/views/contests/show.html.slim @@ -75,10 +75,10 @@ javascript: table.table.table-striped.table-hover thead tr - th - = t("helpers.rank") th = t("activerecord.attributes.contestant.name") + th + = t("activerecord.attributes.contestant.offline") th = t("activerecord.attributes.contestant.completions") th @@ -86,10 +86,14 @@ javascript: tbody - @contestants.each_with_index do |contestant, index| tr scope="row" - td - = index + 1 td = contestant.name + td + - if contestant.offline.present? + + + + td = contestant.completions.where(remaining_pieces: nil).length td diff --git a/config/locales/en.yml b/config/locales/en.yml index 9ad5579..fb6b1d2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -65,6 +65,7 @@ en: display_time: Time email: Email name: Name + offline: Offline? email_description: Optional. Used for sending emails through this app, or for identifying participants whose gmeet handle doesn't match their registered name. csv_import: file: File diff --git a/config/locales/fr.yml b/config/locales/fr.yml index cf1e90d..4a7c41e 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -36,6 +36,7 @@ fr: display_time: Temps email: Email name: Nom + offline: Hors-ligne ? email_description: Optionnel. Utile pour envoyer des emails aux participant.e.s depuis cette app, ou pour reconnaître les pseudos gmeet quand ils ne correspondent pas au nom préalablement entré. csv_import: file: Fichier diff --git a/db/migrate/20251105153647_add_contestant_to_offline.rb b/db/migrate/20251105153647_add_contestant_to_offline.rb new file mode 100644 index 0000000..3347733 --- /dev/null +++ b/db/migrate/20251105153647_add_contestant_to_offline.rb @@ -0,0 +1,5 @@ +class AddContestantToOffline < ActiveRecord::Migration[8.0] + def change + add_reference :offlines, :contestant, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 1479ca8..420beaa 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_10_31_095604) do +ActiveRecord::Schema[8.0].define(version: 2025_11_05_153647) do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -134,7 +134,9 @@ ActiveRecord::Schema[8.0].define(version: 2025_10_31_095604) do t.datetime "end_time" t.string "name", null: false t.boolean "completed" + t.integer "contestant_id" t.index ["contest_id"], name: "index_offlines_on_contest_id" + t.index ["contestant_id"], name: "index_offlines_on_contestant_id" end create_table "puzzles", force: :cascade do |t| @@ -177,6 +179,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_10_31_095604) do add_foreign_key "contestants", "contests" add_foreign_key "contests", "users" add_foreign_key "messages", "contests" + add_foreign_key "offlines", "contestants" add_foreign_key "offlines", "contests" add_foreign_key "puzzles", "contests" add_foreign_key "sessions", "users" diff --git a/spec/factories/offlines.rb b/spec/factories/offlines.rb index 5cf6d4a..f0c4aba 100644 --- a/spec/factories/offlines.rb +++ b/spec/factories/offlines.rb @@ -2,22 +2,25 @@ # # Table name: offlines # -# id :integer not null, primary key -# completed :boolean -# end_time :datetime -# name :string not null -# start_time :datetime not null -# created_at :datetime not null -# updated_at :datetime not null -# contest_id :integer not null +# id :integer not null, primary key +# completed :boolean +# end_time :datetime +# name :string not null +# start_time :datetime not null +# created_at :datetime not null +# updated_at :datetime not null +# contest_id :integer not null +# contestant_id :integer # # Indexes # -# index_offlines_on_contest_id (contest_id) +# index_offlines_on_contest_id (contest_id) +# index_offlines_on_contestant_id (contestant_id) # # Foreign Keys # -# contest_id (contest_id => contests.id) +# contest_id (contest_id => contests.id) +# contestant_id (contestant_id => contestants.id) # FactoryBot.define do factory :offline do diff --git a/spec/models/offline_spec.rb b/spec/models/offline_spec.rb index 89e1d42..375ca67 100644 --- a/spec/models/offline_spec.rb +++ b/spec/models/offline_spec.rb @@ -2,22 +2,25 @@ # # Table name: offlines # -# id :integer not null, primary key -# completed :boolean -# end_time :datetime -# name :string not null -# start_time :datetime not null -# created_at :datetime not null -# updated_at :datetime not null -# contest_id :integer not null +# id :integer not null, primary key +# completed :boolean +# end_time :datetime +# name :string not null +# start_time :datetime not null +# created_at :datetime not null +# updated_at :datetime not null +# contest_id :integer not null +# contestant_id :integer # # Indexes # -# index_offlines_on_contest_id (contest_id) +# index_offlines_on_contest_id (contest_id) +# index_offlines_on_contestant_id (contestant_id) # # Foreign Keys # -# contest_id (contest_id => contests.id) +# contest_id (contest_id => contests.id) +# contestant_id (contestant_id => contestants.id) # require 'rails_helper'