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