diff --git a/app/controllers/contests_controller.rb b/app/controllers/contests_controller.rb index ed10354..7ac922b 100644 --- a/app/controllers/contests_controller.rb +++ b/app/controllers/contests_controller.rb @@ -78,6 +78,8 @@ class ContestsController < ApplicationController @title = I18n.t("contests.scoreboard.title", name: @contest.name) @contestants = @contest.contestants.sort_by { |contestant| [ -contestant.completions.size, contestant.time_seconds ] } @puzzles = @contest.puzzles.order(:id) + @action_name = t("helpers.buttons.refresh") + @action_path = "/public/#{@contest.friendly_id}" render :scoreboard end diff --git a/app/helpers/contests_helper.rb b/app/helpers/contests_helper.rb index 1bec615..157ff86 100644 --- a/app/helpers/contests_helper.rb +++ b/app/helpers/contests_helper.rb @@ -1,2 +1,20 @@ module ContestsHelper + def pad(n) + if n > 9 + return n.to_s + end + "0" + n.to_s + end + + def display_time(time) + h = time / 3600 + m = (time % 3600) / 60 + s = (time % 3600) % 60 + if h > 0 + return h.to_s + ":" + pad(m) + ":" + pad(s) + elsif m > 0 + return m.to_s + ":" + pad(s) + end + s.to_s + end end diff --git a/app/views/contests/scoreboard.html.slim b/app/views/contests/scoreboard.html.slim index 0844942..ff0be43 100644 --- a/app/views/contests/scoreboard.html.slim +++ b/app/views/contests/scoreboard.html.slim @@ -1,56 +1,122 @@ -.d-flex.flex-column style="height: calc(100vh - 180px)" - .d-flex.flex-row.justify-content-center.mb-5 +javascript: + function refresh() { + const el = document.querySelector('input[type="checkbox"]'); + if (el.checked) location.replace("/public/#{@contest.friendly_id}?refresh=1") + setTimeout(refresh, 5000); + } + + / const params = new URL(document.location.toString()).searchParams; + / if (params.get("refresh") == "1") { + / const el = document.querySelector('input[type="checkbox"]'); + / el.checked = true; + / } + + / setTimeout(refresh, 5000); + +css: + @media (max-width: 800px) { + a.btn { display: none; } + .col-5 { display: none; } + .col-6 { width: 100% !important; display: block !important; } + .small-screen-image { display: block !important; } + .container { margin-top: 2rem !important; } + } + +- if @contest.puzzles.size <= 1 + .row.small-screen-image style="display: none" - @contest.puzzles.each do |puzzle| - = image_tag(puzzle.image, class: "img-fluid ms-3 me-3", style: "max-height: 220px") if puzzle.image.attached? - - javascript: - function refresh() { - const el = document.querySelector('input[type="checkbox"]'); - if (el.checked) location.replace("/public/#{@contest.friendly_id}?refresh=1") - setTimeout(refresh, 5000); - } + .d-flex.flex-column.justify-content-center.mb-5 + = image_tag(puzzle.image, style: "max-height: 200px; object-fit: contain") if puzzle.image.attached? + .mt-2.fs-6 style="text-align: center" + => "#{puzzle.name} -" + = puzzle.brand + .row + .col-6.d-flex.flex-column style="height: calc(100vh - 180px)" + / = form_with model: Contest do |form| + / .row.mb-3 + / .col + / .form-check.form-switch + / = form.check_box :refresh, class: "form-check-input" + / = form.label t("contests.scoreboard.refresh") - / const params = new URL(document.location.toString()).searchParams; - / if (params.get("refresh") == "1") { - / const el = document.querySelector('input[type="checkbox"]'); - / el.checked = true; - / } + .d-flex.flex-column style="overflow-y: auto" + table.table.table-striped.table-hover + thead + tr + th + = t("helpers.rank") + th + = t("activerecord.attributes.contestant.name") + - if @contest.puzzles.size > 1 + th + = t("activerecord.attributes.contestant.completions") + th style="width: 170px" + = t("activerecord.attributes.contestant.display_time") + tbody + - @contestants.each_with_index do |contestant, index| + tr scope="row" + td + = index + 1 + td + = contestant.name + - if @contest.puzzles.size > 1 + td + = contestant.completions.length + td style="position: relative" + - if index > 0 && contestant.time_seconds > 0 + .relative-time style="position:absolute; margin: 1px 0 0 64px; font-size: 14px; color: grey" + |> + + = display_time(contestant.time_seconds - @contestants[index - 1].time_seconds) + = contestant.display_time + .col-1 + .col-5 + - @contest.puzzles.each do |puzzle| + = image_tag(puzzle.image, class: "img-fluid ms-3 me-3") if puzzle.image.attached? + .mt-3.fs-4 style="margin-left: 15px" + = puzzle.name + .fs-6 style="margin-left: 15px" + b + = puzzle.brand - / setTimeout(refresh, 5000); +- else + .d-flex.flex-column style="height: calc(100vh - 180px)" + .d-flex.flex-row.justify-content-center.mb-5 + - @contest.puzzles.each do |puzzle| + = image_tag(puzzle.image, class: "img-fluid ms-3 me-3", style: "max-height: 220px") if puzzle.image.attached? - .mb-3 style="display: inline-flex" - a.btn.btn-primary href="/public/#{@contest.friendly_id}" - = t("helpers.buttons.refresh") + .mb-3 style="display: inline-flex" + a.btn.btn-primary href="/public/#{@contest.friendly_id}" + = t("helpers.buttons.refresh") - / = form_with model: Contest do |form| - / .row.mb-3 - / .col - / .form-check.form-switch - / = form.check_box :refresh, class: "form-check-input" - / = form.label t("contests.scoreboard.refresh") + / = form_with model: Contest do |form| + / .row.mb-3 + / .col + / .form-check.form-switch + / = form.check_box :refresh, class: "form-check-input" + / = form.label t("contests.scoreboard.refresh") - .d-flex.flex-column style="overflow-y: auto" - table.table.table-striped.table-hover - thead - tr - th scope="col" - = t("helpers.rank") - th scope="col" - = t("activerecord.attributes.contestant.name") - - if @contest.puzzles.size > 1 + .d-flex.flex-column style="overflow-y: auto" + table.table.table-striped.table-hover + thead + tr th scope="col" - = t("activerecord.attributes.contestant.completions") - th scope="col" - = t("activerecord.attributes.contestant.display_time") - tbody - - @contestants.each_with_index do |contestant, index| - tr scope="row" - td - = index + 1 - td - = contestant.name + = t("helpers.rank") + th scope="col" + = t("activerecord.attributes.contestant.name") - if @contest.puzzles.size > 1 + th scope="col" + = t("activerecord.attributes.contestant.completions") + th scope="col" + = t("activerecord.attributes.contestant.display_time") + tbody + - @contestants.each_with_index do |contestant, index| + tr scope="row" td - = contestant.completions.length - td - = contestant.display_time \ No newline at end of file + = index + 1 + td + = contestant.name + - if @contest.puzzles.size > 1 + td + = contestant.completions.length + td + = contestant.display_time \ No newline at end of file