Description:
- start adding testcases into database - fix download button for score report (grafted from aabe2eab4ee28760618043fc980bb5d5aaca5311)
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r658:e45cb8bba213 - - 7 files changed: 77 inserted, 6 deleted

@@ -0,0 +1,4
1 + class Testcase < ActiveRecord::Base
2 + belongs_to :problem
3 + attr_accessible :group, :input, :num, :score, :sol
4 + end
@@ -0,0 +1,15
1 + class CreateTestcases < ActiveRecord::Migration
2 + def change
3 + create_table :testcases do |t|
4 + t.references :problem
5 + t.integer :num
6 + t.integer :group
7 + t.integer :score
8 + t.text :input
9 + t.text :sol
10 +
11 + t.timestamps
12 + end
13 + add_index :testcases, :problem_id
14 + end
15 + end
@@ -0,0 +1,5
1 + require 'spec_helper'
2 +
3 + describe Testcases do
4 + pending "add some examples to (or delete) #{__FILE__}"
5 + end
@@ -1,12 +1,14
1 + require 'csv'
2 +
1 class ReportController < ApplicationController
3 class ReportController < ApplicationController
2
4
3 before_filter :authenticate
5 before_filter :authenticate
4
6
5 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
7 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score]
6
8
7 before_filter(only: [:problem_hof]) { |c|
9 before_filter(only: [:problem_hof]) { |c|
8 return false unless authenticate
10 return false unless authenticate
9
11
10 if GraderConfiguration["right.user_view_submission"]
12 if GraderConfiguration["right.user_view_submission"]
11 return true;
13 return true;
12 end
14 end
@@ -14,25 +16,25
14 admin_authorization
16 admin_authorization
15 }
17 }
16
18
17 def max_score
19 def max_score
18 end
20 end
19
21
20 def current_score
22 def current_score
21 @problems = Problem.find_available_problems
23 @problems = Problem.find_available_problems
22 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
24 @users = User.includes(:contests).includes(:contest_stat).where(enabled: true)
23 @scorearray = calculate_max_score(@problems, @users,0,0,true)
25 @scorearray = calculate_max_score(@problems, @users,0,0,true)
24
26
25 #rencer accordingly
27 #rencer accordingly
26 - if params[:commit] == 'download csv' then
28 + if params[:button] == 'download' then
27 csv = gen_csv_from_scorearray(@scorearray,@problems)
29 csv = gen_csv_from_scorearray(@scorearray,@problems)
28 send_data csv, filename: 'max_score.csv'
30 send_data csv, filename: 'max_score.csv'
29 else
31 else
30 #render template: 'user_admin/user_stat'
32 #render template: 'user_admin/user_stat'
31 render 'current_score'
33 render 'current_score'
32 end
34 end
33 end
35 end
34
36
35 def show_max_score
37 def show_max_score
36 #process parameters
38 #process parameters
37 #problems
39 #problems
38 @problems = []
40 @problems = []
@@ -48,25 +50,25
48 else
50 else
49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
51 User.includes(:contests).includes(:contest_stat).where(enabled: true)
50 end
52 end
51
53
52 #set up range from param
54 #set up range from param
53 since_id = params.fetch(:min_id, 0).to_i
55 since_id = params.fetch(:min_id, 0).to_i
54 until_id = params.fetch(:max_id, 0).to_i
56 until_id = params.fetch(:max_id, 0).to_i
55
57
56 #calculate the routine
58 #calculate the routine
57 @scorearray = calculate_max_score(@problems, @users,since_id,until_id)
59 @scorearray = calculate_max_score(@problems, @users,since_id,until_id)
58
60
59 #rencer accordingly
61 #rencer accordingly
60 - if params[:commit] == 'download csv' then
62 + if params[:button] == 'download' then
61 csv = gen_csv_from_scorearray(@scorearray,@problems)
63 csv = gen_csv_from_scorearray(@scorearray,@problems)
62 send_data csv, filename: 'max_score.csv'
64 send_data csv, filename: 'max_score.csv'
63 else
65 else
64 #render template: 'user_admin/user_stat'
66 #render template: 'user_admin/user_stat'
65 render 'max_score'
67 render 'max_score'
66 end
68 end
67
69
68 end
70 end
69
71
70 def score
72 def score
71 if params[:commit] == 'download csv'
73 if params[:commit] == 'download csv'
72 @problems = Problem.all
74 @problems = Problem.all
@@ -476,13 +478,44
476 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
478 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
477 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
479 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
478 else
480 else
479 ustat << [0,false]
481 ustat << [0,false]
480 end
482 end
481 end
483 end
482 end
484 end
483 scorearray << ustat
485 scorearray << ustat
484 end
486 end
485 return scorearray
487 return scorearray
486 end
488 end
487
489
490 + def gen_csv_from_scorearray(scorearray,problem)
491 + CSV.generate do |csv|
492 + #add header
493 + header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
494 + problem.each { |p| header << p.name }
495 + header += ['Total','Passed']
496 + csv << header
497 + #add data
498 + scorearray.each do |sc|
499 + total = num_passed = 0
500 + row = Array.new
501 + sc.each_index do |i|
502 + if i == 0
503 + row << sc[i].login
504 + row << sc[i].full_name
505 + row << sc[i].activated
506 + row << (sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no')
507 + row << sc[i].contests.collect {|c| c.name}.join(', ')
508 + else
509 + row << sc[i][0]
510 + total += sc[i][0]
511 + num_passed += 1 if sc[i][1]
512 + end
513 + end
514 + row << total
515 + row << num_passed
516 + csv << row
517 + end
518 + end
519 + end
520 +
488 end
521 end
@@ -1,17 +1,18
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 has_and_belongs_to_many :contests, :uniq => true
4 has_and_belongs_to_many :contests, :uniq => true
5 has_many :test_pairs, :dependent => :delete_all
5 has_many :test_pairs, :dependent => :delete_all
6 + has_many :testcases, :dependent => :destroy
6
7
7 validates_presence_of :name
8 validates_presence_of :name
8 validates_format_of :name, :with => /^\w+$/
9 validates_format_of :name, :with => /^\w+$/
9 validates_presence_of :full_name
10 validates_presence_of :full_name
10
11
11 scope :available, :conditions => {:available => true}
12 scope :available, :conditions => {:available => true}
12
13
13 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_MEMORY_LIMIT = 32
15 DEFAULT_MEMORY_LIMIT = 32
15
16
16 def self.find_available_problems
17 def self.find_available_problems
17 Problem.available.all(:order => "date_added DESC, name ASC")
18 Problem.available.all(:order => "date_added DESC, name ASC")
@@ -2,25 +2,25
2
2
3 = form_tag report_show_max_score_path
3 = form_tag report_show_max_score_path
4 .row
4 .row
5 .col-md-4
5 .col-md-4
6 .panel.panel-primary
6 .panel.panel-primary
7 .panel-heading
7 .panel-heading
8 Problems
8 Problems
9 .panel-body
9 .panel-body
10 %p
10 %p
11 Select problem(s) that we wish to know the score.
11 Select problem(s) that we wish to know the score.
12 = label_tag :problem_id, "Problems"
12 = label_tag :problem_id, "Problems"
13 = select_tag 'problem_id[]',
13 = select_tag 'problem_id[]',
14 - options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}),
14 + options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
15 { class: 'select2 form-control', multiple: "true" }
15 { class: 'select2 form-control', multiple: "true" }
16 .col-md-4
16 .col-md-4
17 .panel.panel-primary
17 .panel.panel-primary
18 .panel-heading
18 .panel-heading
19 Submission range
19 Submission range
20 .panel-body
20 .panel-body
21 %p
21 %p
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
23 .form-group
23 .form-group
24 = label_tag :from, "Min"
24 = label_tag :from, "Min"
25 = text_field_tag 'from_id', nil, class: "form-control"
25 = text_field_tag 'from_id', nil, class: "form-control"
26 .form-group
26 .form-group
@@ -32,18 +32,18
32 Users
32 Users
33 .panel-body
33 .panel-body
34 .radio
34 .radio
35 %label
35 %label
36 = radio_button_tag 'users', 'all', true
36 = radio_button_tag 'users', 'all', true
37 All users
37 All users
38 .radio
38 .radio
39 %label
39 %label
40 = radio_button_tag 'users', 'enabled'
40 = radio_button_tag 'users', 'enabled'
41 Only enabled users
41 Only enabled users
42 .row
42 .row
43 .col-md-12
43 .col-md-12
44 - = button_tag 'Show', class: "btn btn-primary btn-large"
44 + = button_tag 'Show', class: "btn btn-primary btn-large", value: "show"
45 - = button_tag 'Download CSV', class: "btn btn-primary btn-large"
45 + = button_tag 'Download CSV', class: "btn btn-primary btn-large", value: "download"
46
46
47 - if @scorearray
47 - if @scorearray
48 %h2 Result
48 %h2 Result
49 =render "score_table"
49 =render "score_table"
@@ -2,25 +2,25
2 # This file is auto-generated from the current state of the database. Instead
2 # This file is auto-generated from the current state of the database. Instead
3 # of editing this file, please use the migrations feature of Active Record to
3 # of editing this file, please use the migrations feature of Active Record to
4 # incrementally modify your database, and then regenerate this schema definition.
4 # incrementally modify your database, and then regenerate this schema definition.
5 #
5 #
6 # Note that this schema.rb definition is the authoritative source for your
6 # Note that this schema.rb definition is the authoritative source for your
7 # database schema. If you need to create the application database on another
7 # database schema. If you need to create the application database on another
8 # system, you should be using db:schema:load, not running all the migrations
8 # system, you should be using db:schema:load, not running all the migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
11 #
11 #
12 # It's strongly recommended to check this file into your version control system.
12 # It's strongly recommended to check this file into your version control system.
13
13
14 - ActiveRecord::Schema.define(:version => 20161008050135) do
14 + ActiveRecord::Schema.define(:version => 20161014091417) do
15
15
16 create_table "announcements", :force => true do |t|
16 create_table "announcements", :force => true do |t|
17 t.string "author"
17 t.string "author"
18 t.text "body"
18 t.text "body"
19 t.boolean "published"
19 t.boolean "published"
20 t.datetime "created_at", :null => false
20 t.datetime "created_at", :null => false
21 t.datetime "updated_at", :null => false
21 t.datetime "updated_at", :null => false
22 t.boolean "frontpage", :default => false
22 t.boolean "frontpage", :default => false
23 t.boolean "contest_only", :default => false
23 t.boolean "contest_only", :default => false
24 t.string "title"
24 t.string "title"
25 t.string "notes"
25 t.string "notes"
26 end
26 end
@@ -227,24 +227,37
227 t.datetime "compiled_at"
227 t.datetime "compiled_at"
228 t.text "compiler_message"
228 t.text "compiler_message"
229 t.datetime "graded_at"
229 t.datetime "graded_at"
230 t.string "grader_comment"
230 t.string "grader_comment"
231 t.datetime "created_at", :null => false
231 t.datetime "created_at", :null => false
232 t.float "running_time"
232 t.float "running_time"
233 t.string "exit_status"
233 t.string "exit_status"
234 t.integer "memory_usage"
234 t.integer "memory_usage"
235 end
235 end
236
236
237 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
237 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
238
238
239 + create_table "testcases", :force => true do |t|
240 + t.integer "problem_id"
241 + t.integer "num"
242 + t.integer "group"
243 + t.integer "score"
244 + t.text "input"
245 + t.text "sol"
246 + t.datetime "created_at", :null => false
247 + t.datetime "updated_at", :null => false
248 + end
249 +
250 + add_index "testcases", ["problem_id"], :name => "index_testcases_on_problem_id"
251 +
239 create_table "user_contest_stats", :force => true do |t|
252 create_table "user_contest_stats", :force => true do |t|
240 t.integer "user_id"
253 t.integer "user_id"
241 t.datetime "started_at"
254 t.datetime "started_at"
242 t.datetime "created_at", :null => false
255 t.datetime "created_at", :null => false
243 t.datetime "updated_at", :null => false
256 t.datetime "updated_at", :null => false
244 t.boolean "forced_logout"
257 t.boolean "forced_logout"
245 end
258 end
246
259
247 create_table "users", :force => true do |t|
260 create_table "users", :force => true do |t|
248 t.string "login", :limit => 50
261 t.string "login", :limit => 50
249 t.string "full_name"
262 t.string "full_name"
250 t.string "hashed_password"
263 t.string "hashed_password"
You need to be logged in to leave comments. Login now