Implement missing & remaining pieces propagation + cleaner forms
This commit is contained in:
@@ -24,6 +24,7 @@ class CompletionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
@completion = Completion.new
|
@completion = Completion.new
|
||||||
|
@completion.completed = true
|
||||||
if params[:contestant_id]
|
if params[:contestant_id]
|
||||||
@completion.contestant_id = params[:contestant_id]
|
@completion.contestant_id = params[:contestant_id]
|
||||||
end
|
end
|
||||||
@@ -111,6 +112,6 @@ class CompletionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def completion_params
|
def completion_params
|
||||||
params.expect(completion: [ :display_time_from_start, :remaining_pieces, :contestant_id, :message_id, :puzzle_id ])
|
params.expect(completion: [ :display_time_from_start, :completed, :missing_pieces, :remaining_pieces, :contestant_id, :message_id, :puzzle_id ])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ class ContestsController < ApplicationController
|
|||||||
not_found and return
|
not_found and return
|
||||||
end
|
end
|
||||||
|
|
||||||
if @offline.images.length > 1
|
if @offline.submitted
|
||||||
render :offline_already_submitted and return
|
render :offline_already_submitted and return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -144,11 +144,15 @@ class ContestsController < ApplicationController
|
|||||||
not_found and return
|
not_found and return
|
||||||
end
|
end
|
||||||
|
|
||||||
@offline.completed = true
|
@offline.submitted = true
|
||||||
|
@offline.completed = params[:offline][:completed]
|
||||||
@offline.end_time = Time.now()
|
@offline.end_time = Time.now()
|
||||||
@offline.images.attach(params[:offline][:end_image])
|
@offline.images.attach(params[:offline][:end_image])
|
||||||
@offline.missing_pieces = params[:offline][:missing_pieces]
|
if @offline.completed
|
||||||
@offline.remaining_pieces = params[:offline][:remaining_pieces]
|
@offline.missing_pieces = params[:offline][:missing_pieces]
|
||||||
|
else
|
||||||
|
@offline.remaining_pieces = params[:offline][:remaining_pieces]
|
||||||
|
end
|
||||||
if @offline.save
|
if @offline.save
|
||||||
if @contest.puzzles.length > 0
|
if @contest.puzzles.length > 0
|
||||||
dp = display_time(@offline.end_time.to_i - @offline.start_time.to_i)
|
dp = display_time(@offline.end_time.to_i - @offline.start_time.to_i)
|
||||||
@@ -156,7 +160,10 @@ class ContestsController < ApplicationController
|
|||||||
Completion.create(contest: @contest,
|
Completion.create(contest: @contest,
|
||||||
contestant: contestant,
|
contestant: contestant,
|
||||||
puzzle: @contest.puzzles[0],
|
puzzle: @contest.puzzles[0],
|
||||||
display_time_from_start: dp)
|
completed: @offline.completed,
|
||||||
|
display_time_from_start: dp,
|
||||||
|
missing_pieces: @offline.missing_pieces,
|
||||||
|
remaining_pieces: @offline.remaining_pieces)
|
||||||
extend_completions!(contestant)
|
extend_completions!(contestant)
|
||||||
end
|
end
|
||||||
redirect_to "/public/#{@contest.friendly_id}/offline/#{@offline.generate_token_for(:token)}/completed"
|
redirect_to "/public/#{@contest.friendly_id}/offline/#{@offline.generate_token_for(:token)}/completed"
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
# Table name: completions
|
# Table name: completions
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# completed :boolean
|
||||||
# display_relative_time :string
|
# display_relative_time :string
|
||||||
# display_time_from_start :string
|
# display_time_from_start :string
|
||||||
|
# missing_pieces :integer
|
||||||
# remaining_pieces :integer
|
# remaining_pieces :integer
|
||||||
# time_seconds :integer
|
# time_seconds :integer
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
@@ -36,8 +38,10 @@ class Completion < ApplicationRecord
|
|||||||
|
|
||||||
before_save :add_time_seconds, if: -> { display_time_from_start.present? }
|
before_save :add_time_seconds, if: -> { display_time_from_start.present? }
|
||||||
before_save :nullify_display_time
|
before_save :nullify_display_time
|
||||||
|
before_save :clean_pieces
|
||||||
|
|
||||||
validates :display_time_from_start, presence: true, format: { with: /\A(((\d\d|\d):\d\d|\d\d|\d):\d\d|\d\d|\d)\z/ }, if: -> { remaining_pieces == nil }
|
validates :display_time_from_start, presence: true, format: { with: /\A(((\d\d|\d):\d\d|\d\d|\d):\d\d|\d\d|\d)\z/ }, if: -> { completed }
|
||||||
|
validates :remaining_pieces, presence: true, if: -> { !completed }
|
||||||
validates :contestant_id, uniqueness: { scope: :puzzle }, if: -> { contest.puzzles.size == 1 }
|
validates :contestant_id, uniqueness: { scope: :puzzle }, if: -> { contest.puzzles.size == 1 }
|
||||||
validates :puzzle_id, uniqueness: { scope: :contestant }, if: -> { contest.puzzles.size > 1 }
|
validates :puzzle_id, uniqueness: { scope: :contestant }, if: -> { contest.puzzles.size > 1 }
|
||||||
validates :remaining_pieces, numericality: { only_integer: true }, if: -> { remaining_pieces.present? }
|
validates :remaining_pieces, numericality: { only_integer: true }, if: -> { remaining_pieces.present? }
|
||||||
@@ -66,4 +70,12 @@ class Completion < ApplicationRecord
|
|||||||
self.time_seconds = arr[0].to_i
|
self.time_seconds = arr[0].to_i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def clean_pieces
|
||||||
|
if self.completed
|
||||||
|
self.remaining_pieces = nil
|
||||||
|
else
|
||||||
|
self.missing_pieces = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
# name :string not null
|
# name :string not null
|
||||||
# remaining_pieces :integer
|
# remaining_pieces :integer
|
||||||
# start_time :datetime not null
|
# start_time :datetime not null
|
||||||
|
# submitted :boolean
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# contest_id :integer not null
|
# contest_id :integer not null
|
||||||
@@ -32,7 +33,10 @@ class Offline < ApplicationRecord
|
|||||||
|
|
||||||
generates_token_for :token
|
generates_token_for :token
|
||||||
|
|
||||||
|
before_save :clean_pieces
|
||||||
|
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
|
validates :remaining_pieces, presence: true, if: -> { submitted && !completed }
|
||||||
validates :start_time, presence: true
|
validates :start_time, presence: true
|
||||||
|
|
||||||
validate :end_image_is_present
|
validate :end_image_is_present
|
||||||
@@ -56,10 +60,7 @@ class Offline < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def end_image_is_present
|
def end_image_is_present
|
||||||
logger = Logger.new(STDOUT)
|
if self.submitted && self.images.length < 2
|
||||||
logger.info(self.missing_pieces)
|
|
||||||
logger.info(self.missing_pieces.present?)
|
|
||||||
if self.completed && self.images.length < 2
|
|
||||||
errors.add(:end_image, I18n.t("activerecord.errors.models.offline.attributes.end_image.blank"))
|
errors.add(:end_image, I18n.t("activerecord.errors.models.offline.attributes.end_image.blank"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -69,4 +70,12 @@ class Offline < ApplicationRecord
|
|||||||
errors.add(:images, I18n.t("activerecord.errors.models.offline.attributes.start_image.blank"))
|
errors.add(:images, I18n.t("activerecord.errors.models.offline.attributes.start_image.blank"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def clean_pieces
|
||||||
|
if self.completed
|
||||||
|
self.remaining_pieces = nil
|
||||||
|
else
|
||||||
|
self.missing_pieces = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,17 +32,55 @@
|
|||||||
- else
|
- else
|
||||||
= form.hidden_field :puzzle_id
|
= form.hidden_field :puzzle_id
|
||||||
.row.mb-3
|
.row.mb-3
|
||||||
|
.col
|
||||||
|
.form-check.form-switch
|
||||||
|
= form.check_box :completed, class: "form-check-input"
|
||||||
|
= form.label :completed
|
||||||
|
javascript:
|
||||||
|
completedEl = document.getElementById('completion_completed');
|
||||||
|
completedEl.addEventListener('change', (e) => {
|
||||||
|
const timeEl = document.getElementById('time');
|
||||||
|
const missingPiecesEl = document.getElementById('missing_pieces');
|
||||||
|
const remainingPiecesEl = document.getElementById('remaining_pieces');
|
||||||
|
if (e.target.checked) {
|
||||||
|
timeEl.style.display = 'block';
|
||||||
|
missingPiecesEl.style.display = 'block';
|
||||||
|
remainingPiecesEl.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
timeEl.style.display = 'none';
|
||||||
|
missingPiecesEl.style.display = 'none';
|
||||||
|
remainingPiecesEl.style.display = 'block';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.row.mb-3 id="time"
|
||||||
.col
|
.col
|
||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :display_time_from_start, autocomplete: "off", class: "form-control"
|
= form.text_field :display_time_from_start, autocomplete: "off", class: "form-control"
|
||||||
= form.label :display_time_from_start, class: "required"
|
= form.label :display_time_from_start, class: "required"
|
||||||
.row.mb-3
|
.row.mb-3 id="missing_pieces"
|
||||||
|
.col
|
||||||
|
.form-floating
|
||||||
|
= form.text_field :missing_pieces, autocomplete: "off", class: "form-control"
|
||||||
|
= form.label :missing_pieces
|
||||||
|
.row.mb-3 id="remaining_pieces" style="display: none;"
|
||||||
.col
|
.col
|
||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :remaining_pieces, autocomplete: "off", class: "form-control"
|
= form.text_field :remaining_pieces, autocomplete: "off", class: "form-control"
|
||||||
= form.label :remaining_pieces
|
= form.label :remaining_pieces
|
||||||
.form-text
|
javascript:
|
||||||
= t("activerecord.attributes.completion.remaining_pieces_description")
|
completedEl = document.getElementById('completion_completed');
|
||||||
|
timeEl = document.getElementById('time');
|
||||||
|
missingPiecesEl = document.getElementById('missing_pieces');
|
||||||
|
remainingPiecesEl = document.getElementById('remaining_pieces');
|
||||||
|
if (completedEl.checked) {
|
||||||
|
timeEl.style.display = 'block';
|
||||||
|
missingPiecesEl.style.display = 'block';
|
||||||
|
remainingPiecesEl.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
timeEl.style.display = 'none';
|
||||||
|
missingPiecesEl.style.display = 'none';
|
||||||
|
remainingPiecesEl.style.display = 'block';
|
||||||
|
}
|
||||||
.row
|
.row
|
||||||
.col
|
.col
|
||||||
= form.submit submit_text, class: "btn btn-primary"
|
= form.submit submit_text, class: "btn btn-primary"
|
||||||
@@ -33,6 +33,10 @@
|
|||||||
.row.mt-5
|
.row.mt-5
|
||||||
.col
|
.col
|
||||||
h3 Completions
|
h3 Completions
|
||||||
|
.row
|
||||||
|
.col
|
||||||
|
.alert.alert-info
|
||||||
|
= t("contestants.edit.completions_note")
|
||||||
table.table.table-striped.table-hover
|
table.table.table-striped.table-hover
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
@@ -44,6 +48,8 @@
|
|||||||
- else
|
- else
|
||||||
th scope="col"
|
th scope="col"
|
||||||
= t("activerecord.attributes.completion.display_time")
|
= t("activerecord.attributes.completion.display_time")
|
||||||
|
th scope="col"
|
||||||
|
= t("activerecord.attributes.completion.missing_pieces")
|
||||||
th scope="col"
|
th scope="col"
|
||||||
= t("activerecord.attributes.completion.remaining_pieces")
|
= t("activerecord.attributes.completion.remaining_pieces")
|
||||||
th scope="col"
|
th scope="col"
|
||||||
@@ -56,6 +62,8 @@
|
|||||||
- if @contest.puzzles.size > 1
|
- if @contest.puzzles.size > 1
|
||||||
td
|
td
|
||||||
= completion.display_relative_time
|
= completion.display_relative_time
|
||||||
|
td
|
||||||
|
= completion.missing_pieces
|
||||||
td
|
td
|
||||||
= completion.remaining_pieces
|
= completion.remaining_pieces
|
||||||
td
|
td
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
= form_with model: @offline, url: "/public/#{@contest.friendly_id}/offline/#{@offline.generate_token_for(:token)}" do |form|
|
= form_with model: @offline, url: "/public/#{@contest.friendly_id}/offline/#{@offline.generate_token_for(:token)}" do |form|
|
||||||
= form.hidden_field :completed
|
h3 = t("offlines.form.start_message", name: @offline.name)
|
||||||
h3 = t("offlines.form.start_message")
|
|
||||||
h1 id="display-time" style="font-size: 80px;"
|
h1 id="display-time" style="font-size: 80px;"
|
||||||
javascript:
|
javascript:
|
||||||
const startTime = #{@offline.start_time.to_i};
|
startTime = #{@offline.start_time.to_i};
|
||||||
function updateTime() {
|
function updateTime() {
|
||||||
const displayTimeEl = document.getElementById('display-time');
|
const displayTimeEl = document.getElementById('display-time');
|
||||||
const s = Math.floor((Date.now() - 1000 * startTime) / 1000);
|
if (displayTimeEl) {
|
||||||
let ss = s % 60;
|
const s = Math.floor((Date.now() - 1000 * startTime) / 1000);
|
||||||
let mm = Math.floor(s / 60) % 60;
|
let ss = s % 60;
|
||||||
let hh = Math.floor(s / 3600);
|
let mm = Math.floor(s / 60) % 60;
|
||||||
displayTimeEl.innerHTML = `${hh < 10 ? `0${hh}` : hh}:${mm < 10 ? `0${mm}` : mm}:${ss < 10 ? `0${ss}` : ss}`;
|
let hh = Math.floor(s / 3600);
|
||||||
setTimeout(updateTime, 1000);
|
displayTimeEl.innerHTML = `${hh < 10 ? `0${hh}` : hh}:${mm < 10 ? `0${mm}` : mm}:${ss < 10 ? `0${ss}` : ss}`;
|
||||||
|
setTimeout(updateTime, 1000);
|
||||||
|
} else {
|
||||||
|
setTimeout(updateTime, 20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setTimeout(updateTime, 50);
|
setTimeout(updateTime, 1);
|
||||||
.row.mt-5.mb-3
|
.row.mt-5.mb-3
|
||||||
.col
|
.col
|
||||||
.form-text.mb-1
|
.form-text.mb-1
|
||||||
@@ -35,20 +38,49 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
setMaxUploadSize();
|
setMaxUploadSize();
|
||||||
.row.mt-4.mb-3
|
.row.mb-3
|
||||||
|
.col
|
||||||
|
.form-check.form-switch
|
||||||
|
= form.check_box :completed, class: "form-check-input"
|
||||||
|
= form.label :completed
|
||||||
|
javascript:
|
||||||
|
completedEl = document.getElementById('offline_completed');
|
||||||
|
completedEl.addEventListener('change', (e) => {
|
||||||
|
missingPiecesEl = document.getElementById('missing_pieces');
|
||||||
|
remainingPiecesEl = document.getElementById('remaining_pieces');
|
||||||
|
if (e.target.checked) {
|
||||||
|
missingPiecesEl.style.display = 'block';
|
||||||
|
remainingPiecesEl.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
missingPiecesEl.style.display = 'none';
|
||||||
|
remainingPiecesEl.style.display = 'block';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.row.mb-3 id="missing_pieces" style="display: none;"
|
||||||
.col
|
.col
|
||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :missing_pieces, autocomplete: "off", class: "form-control"
|
= form.text_field :missing_pieces, autocomplete: "off", class: "form-control"
|
||||||
= form.label :missing_pieces
|
= form.label :missing_pieces
|
||||||
.form-text
|
.form-text
|
||||||
= t("offlines.form.missing_pieces")
|
= t("offlines.form.missing_pieces")
|
||||||
.row.mb-3
|
.row.mb-3 id="remaining_pieces"
|
||||||
.col
|
.col
|
||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :remaining_pieces, autocomplete: "off", class: "form-control"
|
= form.text_field :remaining_pieces, autocomplete: "off", class: "form-control"
|
||||||
= form.label :remaining_pieces
|
= form.label :remaining_pieces
|
||||||
.form-text
|
.form-text
|
||||||
= t("offlines.form.remaining_pieces")
|
= t("offlines.form.remaining_pieces")
|
||||||
|
javascript:
|
||||||
|
completedEl = document.getElementById('offline_completed');
|
||||||
|
missingPiecesEl = document.getElementById('missing_pieces');
|
||||||
|
remainingPiecesEl = document.getElementById('remaining_pieces');
|
||||||
|
if (completedEl.checked) {
|
||||||
|
missingPiecesEl.style.display = 'block';
|
||||||
|
remainingPiecesEl.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
missingPiecesEl.style.display = 'none';
|
||||||
|
remainingPiecesEl.style.display = 'block';
|
||||||
|
}
|
||||||
.row.mt-4
|
.row.mt-4
|
||||||
.col
|
.col
|
||||||
= form.submit t("helpers.buttons.end"), class: "btn btn-primary"
|
= form.submit t("helpers.buttons.end"), class: "btn btn-primary"
|
||||||
@@ -43,13 +43,14 @@ en:
|
|||||||
new: New category
|
new: New category
|
||||||
name: Category
|
name: Category
|
||||||
completion:
|
completion:
|
||||||
|
completed: Puzzle completed
|
||||||
contestant: Participant
|
contestant: Participant
|
||||||
display_time: Time
|
display_time: Time
|
||||||
display_time_from_start: Time since start
|
display_time_from_start: Time since start
|
||||||
display_relative_time: Time for this puzzle
|
display_relative_time: Time for this puzzle
|
||||||
puzzle: Puzzle
|
puzzle: Puzzle
|
||||||
remaining_pieces: Remaining pieces
|
missing_pieces: Missing pieces
|
||||||
remaining_pieces_description: When this field is filled, the above time will not be taken into account
|
remaining_pieces: Remaining pieces (not completed puzzle)
|
||||||
contest:
|
contest:
|
||||||
lang: Language for the public scoreboard
|
lang: Language for the public scoreboard
|
||||||
name: Name
|
name: Name
|
||||||
@@ -77,6 +78,7 @@ en:
|
|||||||
text: Content
|
text: Content
|
||||||
time: Time
|
time: Time
|
||||||
offline:
|
offline:
|
||||||
|
completed: Puzzle completed
|
||||||
name: Your name
|
name: Your name
|
||||||
missing_pieces: Missing pieces
|
missing_pieces: Missing pieces
|
||||||
remaining_pieces: Remaining pieces
|
remaining_pieces: Remaining pieces
|
||||||
@@ -105,6 +107,7 @@ en:
|
|||||||
puzzle_id:
|
puzzle_id:
|
||||||
taken: "This contestant has already completed this puzzle"
|
taken: "This contestant has already completed this puzzle"
|
||||||
remaining_pieces:
|
remaining_pieces:
|
||||||
|
blank: This is required
|
||||||
not_an_integer: This is not an integer
|
not_an_integer: This is not an integer
|
||||||
not_a_number: This is not an integer
|
not_a_number: This is not an integer
|
||||||
contest:
|
contest:
|
||||||
@@ -131,6 +134,7 @@ en:
|
|||||||
name:
|
name:
|
||||||
blank: Please enter a name for your participation
|
blank: Please enter a name for your participation
|
||||||
remaining_pieces:
|
remaining_pieces:
|
||||||
|
blank: You need to provide the number of remaining pieces to assemble
|
||||||
not_an_integer: This is not an integer
|
not_an_integer: This is not an integer
|
||||||
not_a_number: This is not an integer
|
not_a_number: This is not an integer
|
||||||
start_image:
|
start_image:
|
||||||
@@ -200,6 +204,7 @@ en:
|
|||||||
destroy:
|
destroy:
|
||||||
notice: Participant deleted
|
notice: Participant deleted
|
||||||
edit:
|
edit:
|
||||||
|
completions_note: The time doesn't automatically account penalties for missing pieces. The ability to specify time penalties will be added later on, stay tuned!
|
||||||
end_image: End image
|
end_image: End image
|
||||||
notice: Participant updated
|
notice: Participant updated
|
||||||
not_finished: Not yet finished
|
not_finished: Not yet finished
|
||||||
@@ -268,10 +273,10 @@ en:
|
|||||||
already_submitted: You have already completed the puzzle
|
already_submitted: You have already completed the puzzle
|
||||||
completed_message: Thanks for your participation!
|
completed_message: Thanks for your participation!
|
||||||
end_image_select: Take a photo of your completed puzzle, or on the state it is if you decide to give up
|
end_image_select: Take a photo of your completed puzzle, or on the state it is if you decide to give up
|
||||||
missing_pieces: If completed, indicate the number of missing pieces, if any
|
missing_pieces: Indicate the number of missing pieces, if any
|
||||||
remaining_pieces: If your puzzle isn't complete, indicate here the number of remaining pieces to assemble
|
remaining_pieces: Indicate the number of remaining pieces to assemble
|
||||||
start_image_select: Take a photo of the puzzle with the provided code written on a paper before starting it
|
start_image_select: Take a photo of the puzzle with the provided code written on a paper before starting it
|
||||||
start_message: Let's go!
|
start_message: Let's go %{name}!
|
||||||
puzzles:
|
puzzles:
|
||||||
destroy:
|
destroy:
|
||||||
notice: Puzzle deleted
|
notice: Puzzle deleted
|
||||||
|
|||||||
@@ -14,13 +14,14 @@ fr:
|
|||||||
new: Nouvelle catégorie
|
new: Nouvelle catégorie
|
||||||
name: Catégorie
|
name: Catégorie
|
||||||
completion:
|
completion:
|
||||||
|
completed: Puzzle terminé
|
||||||
contestant_id: Participant.e
|
contestant_id: Participant.e
|
||||||
display_time: Temps
|
display_time: Temps
|
||||||
display_time_from_start: Temps depuis le début
|
display_time_from_start: Temps depuis le début
|
||||||
display_relative_time: Temps pour ce puzzle
|
display_relative_time: Temps pour ce puzzle
|
||||||
puzzle: Puzzle
|
puzzle: Puzzle
|
||||||
remaining_pieces: Nombre de pièces restantes
|
missing_pieces: Pièces manquantes
|
||||||
remaining_pieces_description: Si ce champ est rempli, le temps ci-dessus ne sera pas pris en compte
|
remaining_pieces: Pièces restantes (puzzle non fini)
|
||||||
contest:
|
contest:
|
||||||
lang: Langue pour le classement public
|
lang: Langue pour le classement public
|
||||||
name: Nom
|
name: Nom
|
||||||
@@ -48,6 +49,7 @@ fr:
|
|||||||
text: Contenu
|
text: Contenu
|
||||||
time: Temps
|
time: Temps
|
||||||
offline:
|
offline:
|
||||||
|
completed: Puzzle terminé
|
||||||
name: Ton nom ou pseudo
|
name: Ton nom ou pseudo
|
||||||
missing_pieces: Pièces manquantes
|
missing_pieces: Pièces manquantes
|
||||||
remaining_pieces: Pièces restantes
|
remaining_pieces: Pièces restantes
|
||||||
@@ -76,6 +78,7 @@ fr:
|
|||||||
puzzle_id:
|
puzzle_id:
|
||||||
taken: "Ce.tte participant.e a déjà complété ce puzzle"
|
taken: "Ce.tte participant.e a déjà complété ce puzzle"
|
||||||
remaining_pieces:
|
remaining_pieces:
|
||||||
|
blank: Ce champ est obligatoire
|
||||||
not_an_integer: Ce n'est pas un nombre entier
|
not_an_integer: Ce n'est pas un nombre entier
|
||||||
not_a_number: Ce n'est pas un nombre entier
|
not_a_number: Ce n'est pas un nombre entier
|
||||||
contest:
|
contest:
|
||||||
@@ -95,13 +98,14 @@ fr:
|
|||||||
offline:
|
offline:
|
||||||
attributes:
|
attributes:
|
||||||
end_image:
|
end_image:
|
||||||
blank: Tu dois inclure cette image pour pouvoir valider ton puzzle complété
|
blank: Tu dois inclure cette image pour pouvoir valider ta participation
|
||||||
missing_pieces:
|
missing_pieces:
|
||||||
not_an_integer: Ce n'est pas un entier
|
not_an_integer: Ce n'est pas un entier
|
||||||
not_a_number: Ce n'est pas un entier
|
not_a_number: Ce n'est pas un entier
|
||||||
name:
|
name:
|
||||||
blank: Tu dois entrer un nom pour pouvoir participer
|
blank: Tu dois entrer un nom pour pouvoir participer
|
||||||
remaining_pieces:
|
remaining_pieces:
|
||||||
|
blank: Tu dois renseigner le nombre de pièces restantes à assembler
|
||||||
not_an_integer: Ce n'est pas un entier
|
not_an_integer: Ce n'est pas un entier
|
||||||
not_a_number: Ce n'est pas un entier
|
not_a_number: Ce n'est pas un entier
|
||||||
start_image:
|
start_image:
|
||||||
@@ -171,6 +175,7 @@ fr:
|
|||||||
destroy:
|
destroy:
|
||||||
notice: Participant.e supprimé.e
|
notice: Participant.e supprimé.e
|
||||||
edit:
|
edit:
|
||||||
|
completions_note: Le temps n'inclut actuellement pas de pénalité pour les pièces manquantes. La possibilité de spécifier des pénalités en temps sera ajouté plus tard à l'interface !
|
||||||
end_image: Image de fin
|
end_image: Image de fin
|
||||||
notice: Participant.e modifié.e
|
notice: Participant.e modifié.e
|
||||||
not_finished: Non terminé
|
not_finished: Non terminé
|
||||||
@@ -239,10 +244,10 @@ fr:
|
|||||||
already_submitted: Tu as déjà complété ton puzzle
|
already_submitted: Tu as déjà complété ton puzzle
|
||||||
completed_message: Merci pour ta participation !
|
completed_message: Merci pour ta participation !
|
||||||
end_image_select: Prends une photo du puzzle une fois complété, ou de l'état actuel si tu choisis de t'arrêter là
|
end_image_select: Prends une photo du puzzle une fois complété, ou de l'état actuel si tu choisis de t'arrêter là
|
||||||
missing_pieces: Si complété, indique le nombre de pièces manquantes s'il y en a
|
missing_pieces: Indique le nombre de pièces manquantes s'il y en a
|
||||||
remaining_pieces: Si tu as choisis de t'arrêter avant la fin du puzzle, indique ici le nombre de pièces restantes à assembler
|
remaining_pieces: Indique ici le nombre de pièces restantes à assembler
|
||||||
start_image_select: Prends une photo du puzzle avant de le commencer, avec le code donné par l'organisateur.ice écrit sur du papier
|
start_image_select: Prends une photo du puzzle avant de le commencer, avec le code donné par l'organisateur.ice écrit sur du papier
|
||||||
start_message: C'est parti !
|
start_message: C'est parti %{name} !
|
||||||
puzzles:
|
puzzles:
|
||||||
destroy:
|
destroy:
|
||||||
notice: Puzzle supprimé
|
notice: Puzzle supprimé
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class AddMissingPiecesToCompletion < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_column :completions, :missing_pieces, :integer
|
||||||
|
end
|
||||||
|
end
|
||||||
5
db/migrate/20251110103247_add_completed_to_completion.rb
Normal file
5
db/migrate/20251110103247_add_completed_to_completion.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class AddCompletedToCompletion < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_column :completions, :completed, :boolean
|
||||||
|
end
|
||||||
|
end
|
||||||
5
db/migrate/20251110110151_add_submitted_to_offline.rb
Normal file
5
db/migrate/20251110110151_add_submitted_to_offline.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class AddSubmittedToOffline < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_column :offlines, :submitted, :boolean
|
||||||
|
end
|
||||||
|
end
|
||||||
5
db/schema.rb
generated
5
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2025_11_08_082751) do
|
ActiveRecord::Schema[8.0].define(version: 2025_11_10_110151) do
|
||||||
create_table "active_storage_attachments", force: :cascade do |t|
|
create_table "active_storage_attachments", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", null: false
|
t.string "record_type", null: false
|
||||||
@@ -65,6 +65,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_08_082751) do
|
|||||||
t.string "display_relative_time"
|
t.string "display_relative_time"
|
||||||
t.integer "message_id"
|
t.integer "message_id"
|
||||||
t.integer "remaining_pieces"
|
t.integer "remaining_pieces"
|
||||||
|
t.integer "missing_pieces"
|
||||||
|
t.boolean "completed"
|
||||||
t.index ["contest_id"], name: "index_completions_on_contest_id"
|
t.index ["contest_id"], name: "index_completions_on_contest_id"
|
||||||
t.index ["contestant_id"], name: "index_completions_on_contestant_id"
|
t.index ["contestant_id"], name: "index_completions_on_contestant_id"
|
||||||
t.index ["message_id"], name: "index_completions_on_message_id"
|
t.index ["message_id"], name: "index_completions_on_message_id"
|
||||||
@@ -137,6 +139,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_08_082751) do
|
|||||||
t.integer "contestant_id"
|
t.integer "contestant_id"
|
||||||
t.integer "missing_pieces"
|
t.integer "missing_pieces"
|
||||||
t.integer "remaining_pieces"
|
t.integer "remaining_pieces"
|
||||||
|
t.boolean "submitted"
|
||||||
t.index ["contest_id"], name: "index_offlines_on_contest_id"
|
t.index ["contest_id"], name: "index_offlines_on_contest_id"
|
||||||
t.index ["contestant_id"], name: "index_offlines_on_contestant_id"
|
t.index ["contestant_id"], name: "index_offlines_on_contestant_id"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
# name :string not null
|
# name :string not null
|
||||||
# remaining_pieces :integer
|
# remaining_pieces :integer
|
||||||
# start_time :datetime not null
|
# start_time :datetime not null
|
||||||
|
# submitted :boolean
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# contest_id :integer not null
|
# contest_id :integer not null
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
# name :string not null
|
# name :string not null
|
||||||
# remaining_pieces :integer
|
# remaining_pieces :integer
|
||||||
# start_time :datetime not null
|
# start_time :datetime not null
|
||||||
|
# submitted :boolean
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# contest_id :integer not null
|
# contest_id :integer not null
|
||||||
|
|||||||
Reference in New Issue
Block a user