diff --git a/app/controllers/contests/problems_controller.rb b/app/controllers/contests/problems_controller.rb index ddde8bd..31e481a 100644 --- a/app/controllers/contests/problems_controller.rb +++ b/app/controllers/contests/problems_controller.rb @@ -16,10 +16,17 @@ def load_contest # GET /contests/1/problems # GET /contests/1/problems.json def index - @problems = @contest.problems + @problems = @current_user.group.visible_problems_in(@contest) @users = User.contestants_of(@contest) @current_user.attend(@contest) unless @current_user.attended? @contest + group = @current_user.group + visible_problems = group.visible_problems_in(@contest) + solved_problems = group.solved_problems_in(@contest) + @json_nodes = build_json_nodes(@contest.problems, visible_problems, solved_problems) + + @json_edges = JSON.generate(ProblemEdge.all.map { |pe| { f: pe.from_problem_id, t: pe.to_problem_id, curve: 0 } }); + respond_to do |format| format.html # index.html.erb format.json { render json: @problems } @@ -77,4 +84,27 @@ def check_attendance redirect_to contests_path unless @current_user.attended? @contest end + def build_json_nodes(problems, visible_problems, solved_problems) + def build_node(problem) + { + id: problem.id, + title: problem.title, + text: problem.description, + x: problem.x, + y: problem.y, + } + end + + node_hash = Hash[*problems.flat_map { |p| [p.id, build_node(p)] }] + visible_problems.each do |p| + node_hash[p.id][:visible] = true + end + solved_problems.each do |p| + node_hash[p.id][:visible] = true + node_hash[p.id][:solved] = true + end + + JSON.generate(node_hash.values) + end + end diff --git a/app/models/group.rb b/app/models/group.rb index f470e71..87dda43 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -22,6 +22,18 @@ def attendances_for(contest) Attendance.where(contest_id: contest.id, user_id: user_ids) end + def solved_problems_in(contest) + att_ids = Attendance.where(user_id: user_ids).select(:id) + sbm_ids = Submission.where(solved: true, attendance_id: att_ids).select(:problem_id) + Problem.where(id: sbm_ids) + end + + def visible_problems_in(contest) + solved_problems = solved_problems_in(contest).select(:id) + edges = ProblemEdge.where(from_problem_id: solved_problems) + Problem.where(id: edges) + end + def solved_submission_for(problem, type) Submission.where( problem_id: problem.id, diff --git a/app/models/problem.rb b/app/models/problem.rb index 8a35351..d26c4b3 100644 --- a/app/models/problem.rb +++ b/app/models/problem.rb @@ -15,6 +15,11 @@ class Problem < ActiveRecord::Base belongs_to :contest has_many :submissions + has_many :edges_from, class_name: ProblemEdge, foreign_key: :to_problem_id, dependent: :destroy + has_many :edges_to, class_name: ProblemEdge, foreign_key: :from_problem_id, dependent: :destroy + has_many :from_problems, through: :edges_from, source: :from_problem + has_many :to_problems, through: :edges_to, source: :to_problem + before_save :convert_html def prefix diff --git a/app/models/problem_edge.rb b/app/models/problem_edge.rb new file mode 100644 index 0000000..06ada0c --- /dev/null +++ b/app/models/problem_edge.rb @@ -0,0 +1,6 @@ +class ProblemEdge < ActiveRecord::Base + attr_accessible :from_problem_id, :to_problem_id + + belongs_to :from_problem, class_name: Problem, foreign_key: :from_problem_id + belongs_to :to_problem, class_name: Problem, foreign_key: :to_problem_id +end diff --git a/app/views/contests/problems/index.html.erb b/app/views/contests/problems/index.html.erb index f728742..cb6acdb 100644 --- a/app/views/contests/problems/index.html.erb +++ b/app/views/contests/problems/index.html.erb @@ -6,6 +6,10 @@ b ? content_tag(:div, 'Correct!', class: 'notification alert alert-success') : content_tag(:div, 'Wrong...', class: 'notification alert alert-error') } %> +

Problem Course

+
+
+

<%= link_to 'Scoreboard', contest_score_path %>

Problem List

@@ -17,7 +21,7 @@ Solved Time - <% @problems.order(:title).each do |problem| %> + <% @problems.each do |problem| %> <%= link_to problem.title, contest_problem_path(problem.contest, problem) %> Small
Large @@ -71,3 +75,175 @@ <% end %> + + + diff --git a/db/migrate/20140412105531_create_problem_edges.rb b/db/migrate/20140412105531_create_problem_edges.rb new file mode 100644 index 0000000..f769ee8 --- /dev/null +++ b/db/migrate/20140412105531_create_problem_edges.rb @@ -0,0 +1,10 @@ +class CreateProblemEdges < ActiveRecord::Migration + def change + create_table :problem_edges do |t| + t.integer :from_problem_id, null: false + t.integer :to_problem_id, null: false + + t.timestamps + end + end +end diff --git a/db/migrate/20140412131533_add_column_x_and_y_to_problem.rb b/db/migrate/20140412131533_add_column_x_and_y_to_problem.rb new file mode 100644 index 0000000..d2fe336 --- /dev/null +++ b/db/migrate/20140412131533_add_column_x_and_y_to_problem.rb @@ -0,0 +1,8 @@ +class AddColumnXAndYToProblem < ActiveRecord::Migration + def up + change_table :problems do |t| + t.integer :x + t.integer :y + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 6051c01..e2c8e5b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20131031122342) do +ActiveRecord::Schema.define(:version => 20140412131533) do create_table "attendances", :force => true do |t| t.integer "user_id", :null => false @@ -40,6 +40,13 @@ t.text "output" end + create_table "problem_edges", :force => true do |t| + t.integer "from_problem_id", :null => false + t.integer "to_problem_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "problems", :force => true do |t| t.string "title" t.text "description" @@ -54,6 +61,8 @@ t.integer "contest_id" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false + t.integer "x" + t.integer "y" end create_table "submissions", :force => true do |t| diff --git a/spec/factories/factory.rb b/spec/factories/factory.rb index 1edb591..ca43082 100644 --- a/spec/factories/factory.rb +++ b/spec/factories/factory.rb @@ -38,9 +38,38 @@ introduction 'Waseda University Programming Contest' start_time Time.now end_time Time.new(2114, 6, 2, 16, 0, 0) - problems { |c| c.problems = FactoryGirl.create_list(:problem, 15) } + problems { |c| c.problems = FactoryGirl.create_list(:problem, 22) } after(:create) do |c, evaluator| c.problems.each { |p| p.save } if evaluator.save_problems + # FIXME: (>_<) + edges = [ + [1,3,6], + [2], + [9], + [4], + [7,5], + [9], + [7], + [8], + [9], + [10,12,15], + [11], + [21], + [13,18], + [14], + [21], + [16], + [17], + [18], + [19], + [20], + [21], + [] + ] + + edges.each_with_index do |es,i| + es.each { |e| ProblemEdge.create(from_problem_id: i+1, to_problem_id: e+1).save! } + end end end @@ -53,6 +82,8 @@ sequence(:large_output) {|n| (100+n).to_s } small_score 3 large_score 1020 + sequence(:x) {|n| [nil, 45, 210, 430, 153, 261, 369, 261, 369, 477, 585, 800, 1017, 750, 909, 1080, 680, 780, 880, 950, 1050, 1150, 1233][n] } + sequence(:y) {|n| [nil, 295, 127, 127, 295, 252, 252, 414, 414, 393, 252, 60, 60, 252, 184, 184, 420, 440, 420, 330, 330, 300, 184][n] } end factory :image diff --git a/spec/factories/problem_edges.rb b/spec/factories/problem_edges.rb new file mode 100644 index 0000000..a9f73a2 --- /dev/null +++ b/spec/factories/problem_edges.rb @@ -0,0 +1,8 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :problem_edge do + from_problem_id 1 + to_problem_id 1 + end +end diff --git a/spec/models/problem_edge_spec.rb b/spec/models/problem_edge_spec.rb new file mode 100644 index 0000000..4e05798 --- /dev/null +++ b/spec/models/problem_edge_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe ProblemEdge do + pending "add some examples to (or delete) #{__FILE__}" +end