diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb
--- a/app/controllers/main_controller.rb
+++ b/app/controllers/main_controller.rb
@@ -51,6 +51,23 @@
end
end
+ def test
+ @user = User.find(session[:user_id])
+ @submissions = Submission.find_last_for_all_available_problems(@user.id)
+ @problems = @submissions.collect { |submission| submission.problem }
+ end
+
+ def test_submit
+ @user = User.find(session[:user_id])
+ test_request = TestRequest.new_from_form_params(@user,params[:test_request])
+ if test_request.save
+ redirect_to :action => 'test'
+ else
+ flash[:notice] = 'Error saving your test submission'
+ render :action => 'test'
+ end
+ end
+
protected
def prepare_list_information
@problems = Problem.find_available_problems
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -2,34 +2,32 @@
module ApplicationHelper
def user_header
- options = ''
+ menu_items = ''
user = User.find(session[:user_id])
# main page
- options += link_to_unless_current '[Main]',
- :controller => 'main', :action => 'list'
- options += ' '
+ append_to menu_items, '[Main]', 'main', 'list'
+ append_to menu_items, '[Test]', 'main', 'test'
# admin menu
if (user!=nil) and (user.admin?)
- options +=
- (link_to_unless_current '[Problem admin]',
- :controller => 'problems', :action => 'index') + ' '
- options +=
- (link_to_unless_current '[User admin]',
- :controller => 'user_admin', :action => 'index') + ' '
- options +=
- (link_to_unless_current '[User stat]',
- :controller => 'user_admin', :action => 'user_stat') + ' '
+ append_to menu_items, '[Problem admin]', 'problems', 'index'
+ append_to menu_items, '[User admin]', 'user_admin', 'index'
+ append_to menu_items, '[User stat]', 'user_admin', 'user_stat'
end
# general options
- options += link_to_unless_current '[Settings]',
- :controller => 'users', :action => 'index'
- options += ' '
- options +=
- link_to('[Log out]', {:controller => 'main', :action => 'login'})
- options
+ append_to menu_items, '[Settings]', 'users', 'index'
+ append_to menu_items, '[Log out]', 'main', 'login'
+
+ menu_items
+ end
+
+ def append_to(option,label, controller, action)
+ option << ' ' if option!=''
+ option << link_to_unless_current(label,
+ :controller => controller,
+ :action => action)
end
end
diff --git a/app/models/submission.rb b/app/models/submission.rb
--- a/app/models/submission.rb
+++ b/app/models/submission.rb
@@ -30,6 +30,25 @@
"GROUP BY user_id)")
end
+ def self.find_last_for_all_available_problems(user_id)
+ submissions = Array.new
+ problems = Problem.find_available_problems
+ problems.each do |problem|
+ sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
+ submissions << sub if sub!=nil
+ end
+ submissions
+ end
+
+ def self.find_by_user_problem_number(user_id, problem_id, number)
+ Submission.find(:first,
+ :conditions => {
+ :user_id => user_id,
+ :problem_id => problem_id,
+ :number => number
+ })
+ end
+
protected
def self.find_option_in_source(option, source)
diff --git a/app/models/task.rb b/app/models/task.rb
--- a/app/models/task.rb
+++ b/app/models/task.rb
@@ -31,6 +31,17 @@
self.save
end
+ def status_str
+ case self.status
+ when Task::STATUS_INQUEUE
+ "inqueue"
+ when Task::STATUS_GRADING
+ "grading"
+ when Task::STATUS_COMPLETE
+ "complete"
+ end
+ end
+
def self.get_inqueue_and_change_status(status)
task = nil
begin
diff --git a/app/models/test_request.rb b/app/models/test_request.rb
new file mode 100644
--- /dev/null
+++ b/app/models/test_request.rb
@@ -0,0 +1,64 @@
+require 'fileutils'
+
+class TestRequest < Task
+
+ set_table_name "test_requests"
+
+ belongs_to :user
+ belongs_to :problem
+ belongs_to :submission
+
+ def self.get_inqueue_and_change_status(status)
+ # since there will be only one grader grading TestRequest
+ # we do not need locking (hopefully)
+
+ task = Task.find(:first,
+ :order => "created_at",
+ :conditions => {:status=> Task::STATUS_INQUEUE})
+ if task!=nil
+ task.status = status
+ task.save!
+ end
+
+ task
+ end
+
+ # interfacing with form
+ def self.new_from_form_params(user,params)
+ test_request = TestRequest.new
+ test_request.user = user
+ problem = Problem.find(params[:problem_id])
+ test_request.problem = problem
+ test_request.submission =
+ Submission.find_by_user_problem_number(user.id,
+ problem.id,
+ params[:submission_number])
+ test_request.input_file_name = save_input_file(params[:input_file], user, problem)
+ test_request.submitted_at = Time.new
+ test_request.status_inqueue
+ test_request
+ end
+
+ protected
+ def self.input_file_name(user,problem)
+ begin
+ tmpname = UPLOADED_INPUT_FILE_DIR + "/#{user.login}/#{problem.name}/#{rand(10000)}"
+ end while File.exists?(tmpname)
+ tmpname
+ end
+
+ def self.save_input_file(tempfile, user, problem)
+ new_file_name = input_file_name(user,problem)
+ dirname = File.dirname(new_file_name)
+ FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
+ if tempfile.instance_of?(Tempfile)
+ tempfile.close
+ FileUtils.move(tempfile.path,new_file_name)
+ else
+ File.open(new_file_name, "wb") do |f|
+ f.write(tempfile.read)
+ end
+ end
+ new_file_name
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -4,6 +4,8 @@
has_and_belongs_to_many :roles
+ has_many :test_requests, :order => "problem_id"
+
validates_presence_of :login
validates_presence_of :full_name
validates_length_of :full_name, :minimum => 1
diff --git a/app/views/main/_test_request.html.haml b/app/views/main/_test_request.html.haml
new file mode 100644
--- /dev/null
+++ b/app/views/main/_test_request.html.haml
@@ -0,0 +1,5 @@
+%tr.test-request
+ %td= test_request_counter +1
+ %td= test_request.problem.full_name
+ %td= test_request.submission_id
+ %td= test_request.status_str
diff --git a/app/views/main/test.html.erb b/app/views/main/test.html.erb
new file mode 100644
--- /dev/null
+++ b/app/views/main/test.html.erb
@@ -0,0 +1,67 @@
+
Test Interface
+
+<% if @problems.length==0 %>
+ "There is no submission"
+ <% return %>
+<% end %>
+
+
+
+<% form_for :test_request, nil,
+ :url => { :action => 'test_submit'},
+ :html => { :multipart => true } do |f| %>
+
+
+ Task: |
+
+ <%= select(:test_request,
+ :problem_id,
+ @problems.collect {|p| [p.name, p.id]}, {},
+ { :onclick => "updateSubmissionList();" }) %>
+ |
+
+
+ Submission: |
+
+ <%= select(:test_request,
+ :submission_number,
+ (1..@submissions[0].number).collect {|n| [n,n]}) %>
+ |
+
+
+ Input data: |
+ <%= f.file_field :input_file %> |
+
+
+ <%= submit_tag 'submit' %>
+ |
+
+
+<% end %>
+
+Previous requests
+
+
+
+
+ | problem |
+ # |
+ status |
+
+<%= render :partial => 'test_request', :collection => @user.test_requests %>
+
diff --git a/config/environment.rb b/config/environment.rb
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -58,3 +58,5 @@
# Mime::Type.register "application/x-mobile", :mobile
# Include your application configuration below
+
+UPLOADED_INPUT_FILE_DIR = '/home/jittat/web_grader/upload/'
diff --git a/db/migrate/019_create_test_requests.rb b/db/migrate/019_create_test_requests.rb
new file mode 100644
--- /dev/null
+++ b/db/migrate/019_create_test_requests.rb
@@ -0,0 +1,30 @@
+class CreateTestRequests < ActiveRecord::Migration
+ def self.up
+ create_table :test_requests do |t|
+ t.column :user_id, :integer
+ t.column :problem_id, :integer
+ t.column :submission_id, :integer
+ t.column :input_file_name, :string
+ t.column :output_file_name, :string
+ t.column :running_stat, :string
+
+ # these are similar to tasks
+ t.column :status, :integer
+ t.column :updated_at, :datetime
+
+ # these are intentionally similar to submissions
+ t.column :submitted_at, :datetime
+ t.column :compiled_at, :datetime
+ t.column :compiler_message, :string
+ t.column :graded_at, :datetime
+ t.column :grader_comment, :string
+ t.timestamps
+ end
+ add_index :test_requests, [:user_id, :problem_id]
+ end
+
+ def self.down
+ remove_index :test_requests, :column => [:user_id, :problem_id]
+ drop_table :test_requests
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -9,7 +9,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 18) do
+ActiveRecord::Schema.define(:version => 19) do
create_table "grader_processes", :force => true do |t|
t.string "host", :limit => 20
@@ -96,6 +96,25 @@
t.datetime "updated_at"
end
+ create_table "test_requests", :force => true do |t|
+ t.integer "user_id"
+ t.integer "problem_id"
+ t.integer "submission_id"
+ t.string "input_file_name"
+ t.string "output_file_name"
+ t.string "running_stat"
+ t.integer "status"
+ t.datetime "updated_at"
+ t.datetime "submitted_at"
+ t.datetime "compiled_at"
+ t.string "compiler_message"
+ t.datetime "graded_at"
+ t.string "grader_comment"
+ t.datetime "created_at"
+ end
+
+ add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
+
create_table "users", :force => true do |t|
t.string "login", :limit => 10
t.string "full_name"
diff --git a/test/fixtures/test_requests.yml b/test/fixtures/test_requests.yml
new file mode 100644
--- /dev/null
+++ b/test/fixtures/test_requests.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+# one:
+# column: value
+#
+# two:
+# column: value
diff --git a/test/unit/test_request_test.rb b/test/unit/test_request_test.rb
new file mode 100644
--- /dev/null
+++ b/test/unit/test_request_test.rb
@@ -0,0 +1,8 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class TestRequestTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ def test_truth
+ assert true
+ end
+end