Add ranking mode
Some checks failed
CI / scan_ruby (push) Successful in 20s
CI / scan_js (push) Successful in 13s
CI / lint (push) Successful in 12s
CI / test (push) Failing after 35s

This commit is contained in:
sto
2025-11-14 10:19:08 +01:00
parent cdf87e48f2
commit f91145637f
12 changed files with 51 additions and 38 deletions

View File

@@ -54,10 +54,6 @@ class CompletionsController < ApplicationController
redirect_to @contest, notice: t("completions.edit.notice")
end
else
if @contestant
@action_name = t("helpers.buttons.back_to_contestant")
@action_path = edit_contest_contestant_path(@contest, @contestant)
end
render :edit, status: :unprocessable_entity
end
end

View File

@@ -0,0 +1,12 @@
module ContestantsConcern
extend ActiveSupport::Concern
def ranked_contestants(contest)
contest.contestants.sort_by { |contestant| [
-contestant.completions.where(remaining_pieces: nil).size,
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
contestant.time_seconds
] }
end
end

View File

@@ -1,4 +1,6 @@
class ContestantsController < ApplicationController
include ContestantsConcern
before_action :set_contest
before_action :set_contestant, only: %i[ destroy edit update]
before_action :set_completions, only: %i[edit update ]
@@ -6,12 +8,7 @@ class ContestantsController < ApplicationController
def index
authorize @contest
@contestants = @contest.contestants.sort_by { |contestant| [
-contestant.completions.where(remaining_pieces: nil).size,
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
contestant.time_seconds
] }
@contestants = @contest.contestants.sort_by { |contestant| contestant.name }
filter_contestants_per_category
end
@@ -111,12 +108,7 @@ class ContestantsController < ApplicationController
def export
authorize @contest
@contestants = @contest.contestants.sort_by { |contestant| [
-contestant.completions.where(remaining_pieces: nil).size,
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
contestant.time_seconds
] }
@contestants = ranked_contestants(@contest)
respond_to do |format|
format.csv do

View File

@@ -1,7 +1,8 @@
class ContestsController < ApplicationController
include CompletionsConcern
include ContestantsConcern
before_action :set_contest, only: %i[ destroy show update ]
before_action :set_contest, only: %i[ destroy show ]
before_action :set_settings_contest, only: %i[ settings_general_edit settings_general_update settings_offline_edit settings_offline_update settings_categories_edit ]
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 ]
@@ -60,7 +61,7 @@ class ContestsController < ApplicationController
def create
authorize :contest
@contest = Contest.new(contest_params)
@contest = Contest.new(new_contest_params)
@contest.user_id = current_user.id
if @contest.save
redirect_to "/contests/#{@contest.id}/settings/general", notice: t("contests.new.notice")
@@ -69,16 +70,6 @@ class ContestsController < ApplicationController
end
end
def update
authorize @contest
if @contest.update(contest_params)
redirect_to @contest, notice: t("contests.edit.notice")
else
render :edit, status: :unprocessable_entity
end
end
def destroy
authorize @contest
@@ -97,12 +88,7 @@ class ContestsController < ApplicationController
I18n.locale = @contest.lang
@title = I18n.t("contests.scoreboard.title", name: @contest.name)
@contestants = @contest.contestants.sort_by { |contestant| [
-contestant.completions.where(remaining_pieces: nil).size,
(contestant.completions.where(remaining_pieces: nil).size == @contest.puzzles.length ? 1 : 0) * contestant.time_seconds,
contestant.completions.size > 0 && contestant.completions[-1].remaining_pieces ? contestant.completions[-1].remaining_pieces : 1000000,
contestant.time_seconds
] }
@contestants = ranked_contestants(@contest)
filter_contestants_per_category
if params.key?(:hide_offline) && params[:hide_offline] == "true"
@contestants = @contestants.select { |contestant| !contestant.offline.present? }
@@ -212,12 +198,12 @@ class ContestsController < ApplicationController
@contest = Contest.find(params[:contest_id])
end
def contest_params
params.expect(contest: [ :lang, :name, :offline_form, :public, :team, :allow_registration ])
def new_contest_params
params.expect(contest: [ :name ])
end
def settings_general_params
params.expect(contest: [ :lang, :name, :public, :team, :allow_registration ])
params.expect(contest: [ :lang, :name, :public, :ranking_mode, :team, :allow_registration ])
end
def settings_offline_params

3
app/lib/ranking.rb Normal file
View File

@@ -0,0 +1,3 @@
module Ranking
AVAILABLE_RANKING_MODES = [ { id: "actual", name: I18n.t("lib.ranking.actual") }, { id: "theorical", name: I18n.t("lib.ranking.theorical") } ]
end

View File

@@ -8,6 +8,7 @@
# name :string
# offline_form :boolean default(FALSE)
# public :boolean default(FALSE)
# ranking_mode :string
# slug :string
# team :boolean default(FALSE)
# created_at :datetime not null
@@ -38,6 +39,7 @@ class Contest < ApplicationRecord
validates :name, presence: true
validates :lang, inclusion: { in: Languages::AVAILABLE_LANGUAGES.map { |lang| lang[:id] } }
validates :ranking_mode, inclusion: { in: Ranking::AVAILABLE_RANKING_MODES.map { |lang| lang[:id] } }
generates_token_for :token
end

View File

@@ -14,6 +14,11 @@
.form-check.form-switch
= form.check_box :public, class: "form-check-input"
= form.label :public
.row.mb-3
.col
.form-floating
= form.select :ranking_mode, Ranking::AVAILABLE_RANKING_MODES.map { |mode| [ mode[:name], mode[:id] ] }, {}, class: "form-select"
= form.label :ranking_mode
.row.mb-3
.col
.form-check.form-switch