diff --git a/app/assets/stylesheets/main_table.css b/app/assets/stylesheets/main_table.css index dfc0f782..b8c1f7ad 100644 --- a/app/assets/stylesheets/main_table.css +++ b/app/assets/stylesheets/main_table.css @@ -70,3 +70,6 @@ table.main_table > thead > tr > th { font-weight: bold; } +.unofficial > td { + opacity: 0.4; +} \ No newline at end of file diff --git a/app/controllers/contests_controller.rb b/app/controllers/contests_controller.rb index d08a58b6..0511962c 100644 --- a/app/controllers/contests_controller.rb +++ b/app/controllers/contests_controller.rb @@ -1,7 +1,7 @@ class ContestsController < ApplicationController def permitted_params @_permitted_params ||= begin - permitted_attributes = [:name, :start_time, :end_time, :duration, :problem_set_id, :startcode, :observation] + permitted_attributes = [:name, :start_time, :end_time, :duration, :problem_set_id, :startcode, :observation, :live_scoreboard, :show_unofficial_competitors] permitted_attributes << :owner_id if policy(@contest || Contest).transfer? params.require(:contest).permit(*permitted_attributes) end @@ -49,7 +49,7 @@ def browse def show @contest = Contest.find(params[:id]) if !policy(@contest).overview? - redirect_to info_contest_path(@contest) + redirect_to scoreboard_contest_path(@contest) return end @problem_associations = @contest.problem_set.problem_associations.includes(:problem) @@ -64,15 +64,6 @@ def show render :layout => 'contest' end - def info - @contest = Contest.find(params[:id]) - authorize @contest, :show? - @groups = Group.all - @contest_relation = @contest.get_relation(current_user.id) if user_signed_in? - - render :layout => 'contest' - end - def scoreboard @contest = Contest.find(params[:id]) authorize @contest, :scoreboard? diff --git a/app/views/contests/_admin.html.erb b/app/views/contests/_admin.html.erb index 67178654..7916b8b0 100644 --- a/app/views/contests/_admin.html.erb +++ b/app/views/contests/_admin.html.erb @@ -16,3 +16,7 @@ <% end %> +

+ Problem set: + <%= link_to @contest.problem_set.name, @contest.problem_set %> +

\ No newline at end of file diff --git a/app/views/contests/_form.html.erb b/app/views/contests/_form.html.erb index edc4d545..1f6a77d7 100644 --- a/app/views/contests/_form.html.erb +++ b/app/views/contests/_form.html.erb @@ -29,11 +29,18 @@
<%= f.label :duration %>
- <%= f.text_field :duration %> + <%= f.text_field :duration, :value=>3.0 %> hours
<%= f.label :observation %>
- <%= f.select :observation, Contest::OBSERVATION.entries.invert %> + <%= f.select :observation, Contest::OBSERVATION.entries.invert %>
+ Students can only join a contest if they belong to a group that the contest also belongs to. + +
<%= f.label :startcode %>
@@ -46,8 +53,16 @@ <% else %> <%= handle(@contest.owner) %> <% end %> -
+
+ <%= f.label :live_scoreboard %> - If true, individual problem scores are shown on the live scoreboard. Otherwise, only total scores are shown.
+ <%= f.check_box :live_scoreboard %> +
+
+ <%= f.label :show_unofficial_competitors %> - If true, unofficial competitors are greyed out. An offical competitor is any student enrolled in school.
+ <%= f.check_box :show_unofficial_competitors %> +
+
<%= f.submit %>
diff --git a/app/views/contests/_index.html.erb b/app/views/contests/_index.html.erb index 71e1321d..51784528 100644 --- a/app/views/contests/_index.html.erb +++ b/app/views/contests/_index.html.erb @@ -5,7 +5,6 @@ Start time End time Duration - User Score <% if policy(Contest).update? %> @@ -27,8 +26,7 @@ <%= contest.name %> <%= contest.start_time.strftime("%b %d, %H:%M") unless contest.start_time.nil? %> <%= contest.end_time.strftime("%b %d, %H:%M") unless contest.end_time.nil? %> - <%= contest.duration %> - <%= contest.owner_id %> + <%= contest.duration %> hours <%= contest.get_score(current_user.id) if user_signed_in? %> <% if contest.is_running? && (policy(contest).start?) %> diff --git a/app/views/contests/edit.html.erb b/app/views/contests/edit.html.erb index 3074094a..d1413622 100644 --- a/app/views/contests/edit.html.erb +++ b/app/views/contests/edit.html.erb @@ -3,13 +3,4 @@

<%= render 'form' %> -

-<% if false # COMMENTED %> -

- Problems: -<% @problems.each do |problem| %> - <%= link_to problem.name, problem_path(problem) %> - (<%= link_to "remove", :controller => "problem_contest", :action => "remove", :method => "post", :problem_id => problem, :contest_id => @contest %>) -<% end %> -

-<% end %> +

\ No newline at end of file diff --git a/app/views/contests/info.html.erb b/app/views/contests/info.html.erb deleted file mode 100644 index c3d77457..00000000 --- a/app/views/contests/info.html.erb +++ /dev/null @@ -1,20 +0,0 @@ -<% if !@contest.started? && !@contest.start_time.nil? %> - -<% end %> - -<% if false && !@contest_relation.nil? %> -

Contest Registration

- - Country: <%= @contest_relation.country_code %> - School: <%= @contest_relation.school.name %> -<% end %> - -

Contest Settings

-Mode: Closed book (you cannot access other problems on the site while competing)
-Judge feedback: Real-time
-Scoreboard: Live
- diff --git a/app/views/contests/scoreboard.html.erb b/app/views/contests/scoreboard.html.erb index 1b54bce2..be46dfdb 100644 --- a/app/views/contests/scoreboard.html.erb +++ b/app/views/contests/scoreboard.html.erb @@ -14,63 +14,83 @@ <% else %>

<%= @contest.finalized? ? "Final Results" : "Preliminary Results" %>

- +
- - <% @contest.problem_set.problems.each_with_index do |problem, prob_num|%> - + + + + <% if @contest.live_scoreboard %> + <% @contest.problem_set.problems.each_with_index do |problem, prob_num|%> + + <% end %> <% end %> - - - + + - <% median = @scoreboard[@scoreboard.length/2-1] %> <% rank = 1 %> + <% num_unofficial = 0 %> <% previous_record = @scoreboard.first %> <% @scoreboard.each_with_index do |record,index| %> - <% if !user_signed_in? or record.user && record.user.id != current_user.id && !policy(@contest).inspect? %> - <% next if record.score < median.score || (record.score == median.score && record.time_taken > median.time_taken) # no permission to view %> + <% is_official = true %> + <% if @contest.show_unofficial_competitors and record.user %> + <% is_official = record.user.estimated_year_level(@contest.end_time) %> <% end %> - class="emphasized"<% end %>> - + <% rank = index + 1 unless previous_record.score == record.score and previous_record.time_taken == record.time_taken%> + <% previous_record = record %> + + <% if record.user %> + + - <% link_to_submissions = user_signed_in? && (record.id == current_user.id || current_user.is_admin?) %> - <% @problems.each do |prob|%> - + + <% else %> + + + <% end %> + <% link_to_submissions = user_signed_in? && (record.id == current_user.id || current_user.is_admin?) %> + <% if @contest.live_scoreboard %> + <% @problems.each do |prob|%> + + <% end %> <% end %> - <% rank = index + 1 unless previous_record.score == record.score and previous_record.time_taken == record.time_taken %> - <% previous_record = record %> - <% end %>
User - <% if policy(@contest).show_details? %> - <%= link_to problem.name, problem_path(problem) %> - <% else %> - <% prob_num += 1 %> - Problem <% while !prob_num.zero? %><% prob_num, rem = (prob_num - 1).divmod(26) %><%= ('A'..'Z').to_a[rem] %><% end %> - <% end %> - (<%= @weighting[problem.id] %>) - # Username + <% if policy(@contest).show_details? %> + <%= link_to problem.name, problem_path(problem) %> + <% else %> + <% prob_num += 1 %> + Problem <% while !prob_num.zero? %><% prob_num, rem = (prob_num - 1).divmod(26) %><%= ('A'..'Z').to_a[rem] %><% end %> + <% end %> + (<%= @weighting[problem.id] %>) + Score Time Rank Score Time
- <% if record.user %> + <% num_unofficial = num_unofficial + 1 unless is_official %> +
<%= rank - (is_official ? num_unofficial : 0)%> + <%= flag_list(24){ flag(record.user.country_code.downcase, record.user.country_name, title: true) } if record.user.country_code %> + <%= link_to handle(record.user), record.user %> - <% else %> - <%= "Deleted User ID #{record[:user_id]}" %> - <% end %> - - - <%= record["score_#{prob.id}"].nil? ? "-":link_to_if(link_to_submissions, record["score_#{prob.id}"], submission_path(record["sub_#{prob.id}"])) %> - - - <%= raw record["score_#{prob.id}"].nil? ? " ":"#{record["attempt_#{prob.id}"].to_i.ordinalize} 
try" %> -
- - (<%= link_to_if link_to_submissions, (record["attempts_#{prob.id}"] || 0), :controller => "submissions", :by_user => record[:user_id], :by_problem => prob.id %>) -
<%= "Deleted User ID #{record[:user_id]}" %> + + <%= record["score_#{prob.id}"].nil? ? "-":link_to_if(link_to_submissions, record["score_#{prob.id}"], submission_path(record["sub_#{prob.id}"])) %> + + + <%= raw record["score_#{prob.id}"].nil? ? " ":"#{record["attempt_#{prob.id}"].to_i.ordinalize} 
try" %> +
+ + (<%= link_to_if link_to_submissions, (record["attempts_#{prob.id}"] || 0), :controller => "submissions", :by_user => record[:user_id], :by_problem => prob.id %>) + +
<%= record.score %> <%= format("%d:%02d:%02d",record.time_taken.to_i/3600,record.time_taken.to_i/60%60,record.time_taken.to_i%60) %> <%= rank %>
+
+ Key + + + + + +
Official competitor
Unofficial competitor
<% end %> diff --git a/app/views/layouts/contest.html.erb b/app/views/layouts/contest.html.erb index 7703cca2..eb132ee7 100644 --- a/app/views/layouts/contest.html.erb +++ b/app/views/layouts/contest.html.erb @@ -71,8 +71,7 @@

Start time: <%= @contest.start_time %>
End time: <%= @contest.end_time %>
- Duration: <%= @contest.duration %>
- Owner: <%= @contest.owner_id %>
+ Duration: <%= @contest.duration %> <%= @contest.duration == 1.0 ? "hour" : "hours"%>

<% if @contest.ended? and @contest.finalized_at.nil? and policy(@contest).update? %> <%= link_to "Finalize results", finalize_contest_path(@contest), :data => { :confirm => 'Are you sure?' }, :method => :put %> @@ -85,7 +84,6 @@ # SimpleNavigation::ItemContainer.new do |menu| render_navigation do |menu| menu.dom_class = :tab_menu - menu.item :info, "info", info_contest_path(@contest) if policy(@contest).show? menu.item :problems, "problems", contest_path(@contest) if policy(@contest).overview? menu.item :contestants, "contestants", contestants_contest_path(@contest) if policy(@contest).contestants? menu.item :supervisors, "supervisors", supervisors_contest_path(@contest) if policy(@contest).manage? diff --git a/db/languages.yml b/db/languages.yml index d2b41755..e27ec4b7 100644 --- a/db/languages.yml +++ b/db/languages.yml @@ -2,6 +2,9 @@ # database stores the variants and their language group # programs will reference a language variant, and will be upgraded if their behaviour is the same across multiple versions +# compiler_command is a shell command executed using bash (see Language#compile) +# interpreter_command is executed directly using 'isolate' (so the first argument must be the full path to the interpreter) + c++: :name: "C++" :lexer: c++ @@ -15,19 +18,19 @@ c++: :variants: c++03: # deprecated :name: "C++03" - :compiler: /usr/bin/g++ + :compiler: g++ :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++03 -O2 -o %{output} %{source} -lm" c++11: :name: "C++11" - :compiler: /usr/bin/g++ + :compiler: g++ :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++11 -O2 -o %{output} %{source} -lm" c++14: # Changes since C++11: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1319r0.html :name: "C++14" - :compiler: /usr/bin/g++ + :compiler: g++ :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++14 -O2 -o %{output} %{source} -lm" c++17: # Changes since C++14: https://isocpp.org/files/papers/p0636r0.html :name: "C++17" - :compiler: /usr/bin/g++ + :compiler: g++ :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++17 -O2 -o %{output} %{source} -lm" c: :name: "C" @@ -42,11 +45,11 @@ c: :variants: c99: # deprecated :name: C99 - :compiler: /usr/bin/gcc + :compiler: gcc :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu99 -O2 -o %{output} %{source} -lm" c11: # Changes since c99: https://en.wikipedia.org/wiki/C11_(C_standard_revision) :name: C11 - :compiler: /usr/bin/gcc + :compiler: gcc :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu11 -O2 -o %{output} %{source} -lm" java: @@ -62,13 +65,13 @@ java: :variants: java6: :name: Java 1.6 # deprecated (note: uses '-source 1.6', which will be removed in a future JDK release) - :compiler: /usr/bin/javac;/usr/bin/jar + :compiler: javac;jar :compiler_command: '%{compiler[0]} -version | head -n 1 1>&2 && %{compiler[0]} -O -source 1.6 -J-Xms16m -J-Xmx256m %{source} && %{compiler[1]} cfe %{output} Main -C %{source_dir} .' :interpreter: /usr/bin/java :interpreter_command: '%{interpreter} -jar %{source}' java11: :name: Java 11 - :compiler: /usr/bin/javac;/usr/bin/jar + :compiler: javac;jar :compiler_command: '%{compiler[0]} -version | head -n 1 1>&2 && %{compiler[0]} -O -source 11 -J-Xms16m -J-Xmx256m %{source} && %{compiler[1]} cfe %{output} Main -C %{source_dir} .' :interpreter: /usr/bin/java :interpreter_command: '%{interpreter} -jar %{source}' @@ -85,7 +88,7 @@ haskell: :variants: haskell2010: :name: "Haskell 2010" - :compiler: /usr/bin/ghc + :compiler: ghc :compiler_command: '%{compiler} --version 1>&2 && %{compiler} --make -O2 -o %{output} %{source} -lm' python: :name: Python @@ -168,6 +171,6 @@ csharp: :variants: csharp8: :name: "C# 8.0" - :compiler: /usr/local/bin/dotnet-csc # custom shell script (also prints SDK version number) + :compiler: dotnet-csc # custom shell script (also prints SDK version number) :compiler_command: '%{compiler} %{source} -optimize+ -out:%{output} -langversion:8.0 -nologo' :interpreter_command: '%{interpreter} %{source}' diff --git a/db/migrate/20200418113600_add_live_scoreboard_field.rb b/db/migrate/20200418113600_add_live_scoreboard_field.rb new file mode 100644 index 00000000..adbc956c --- /dev/null +++ b/db/migrate/20200418113600_add_live_scoreboard_field.rb @@ -0,0 +1,5 @@ +class AddLiveScoreboardField < ActiveRecord::Migration + def change + add_column :contests, :live_scoreboard, :boolean, :default => true + end + end \ No newline at end of file diff --git a/db/migrate/20200418113601_add_offical_competitors.rb b/db/migrate/20200418113601_add_offical_competitors.rb new file mode 100644 index 00000000..bc50d207 --- /dev/null +++ b/db/migrate/20200418113601_add_offical_competitors.rb @@ -0,0 +1,5 @@ +class AddOfficalCompetitors < ActiveRecord::Migration + def change + add_column :contests, :show_unofficial_competitors, :boolean, :default => false + end + end \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 264ca391..d4326eb8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160131000430) do +ActiveRecord::Schema.define(version: 20200418113601) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -114,9 +114,11 @@ t.integer "problem_set_id" t.datetime "finalized_at" t.string "startcode" - t.integer "observation", default: 1 - t.integer "registration", default: 0 - t.integer "affiliation", default: 0 + t.integer "observation", default: 1 + t.integer "registration", default: 0 + t.integer "affiliation", default: 0 + t.boolean "live_scoreboard", default: true + t.boolean "show_unofficial_competitors", default: false end create_table "entities", force: true do |t|