Description:
added language identification using file extension git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@363 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r166:7417e965c968 - - 4 files changed: 57 inserted, 7 deleted

@@ -0,0 +1,23
1 + class AddCommonExtToLanguages < ActiveRecord::Migration
2 + def self.up
3 + # language.common_ext is a comma-separated list of common file
4 + # extensions.
5 + add_column :languages, :common_ext, :string
6 +
7 + # updating table information
8 + Language.reset_column_information
9 + common_ext = {
10 + 'c' => 'c',
11 + 'cpp' => 'cpp,cc',
12 + 'pas' => 'pas'
13 + }
14 + Language.find(:all).each do |lang|
15 + lang.common_ext = common_ext[lang.name]
16 + lang.save
17 + end
18 + end
19 +
20 + def self.down
21 + remove_column :languages, :common_ext
22 + end
23 + end
@@ -1,2 +1,24
1 class Language < ActiveRecord::Base
1 class Language < ActiveRecord::Base
2 +
3 + @@languages_by_ext = {}
4 +
5 + def self.cache_ext_hash
6 + @@languages_by_ext = {}
7 + Language.find(:all).each do |language|
8 + language.common_ext.split(',').each do |ext|
9 + @@languages_by_ext[ext] = language
2 end
10 end
11 + end
12 + end
13 +
14 + def self.find_by_extension(ext)
15 + if @@languages_by_ext.length == 0
16 + Language.cache_ext_hash
17 + end
18 + if @@languages_by_ext.has_key? ext
19 + return @@languages_by_ext[ext]
20 + else
21 + return nil
22 + end
23 + end
24 + end
@@ -1,148 +1,152
1 class Submission < ActiveRecord::Base
1 class Submission < ActiveRecord::Base
2
2
3 belongs_to :language
3 belongs_to :language
4 belongs_to :problem
4 belongs_to :problem
5 belongs_to :user
5 belongs_to :user
6
6
7 before_validation :assign_problem
7 before_validation :assign_problem
8 before_validation :assign_language
8 before_validation :assign_language
9
9
10 validates_presence_of :source
10 validates_presence_of :source
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
11 validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
12 validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short'
13 validate :must_have_valid_problem
13 validate :must_have_valid_problem
14 validate :must_specify_language
14 validate :must_specify_language
15
15
16 before_save :assign_latest_number_if_new_recond
16 before_save :assign_latest_number_if_new_recond
17
17
18 def self.find_last_by_user_and_problem(user_id, problem_id)
18 def self.find_last_by_user_and_problem(user_id, problem_id)
19 last_sub = find(:first,
19 last_sub = find(:first,
20 :conditions => {:user_id => user_id,
20 :conditions => {:user_id => user_id,
21 :problem_id => problem_id},
21 :problem_id => problem_id},
22 :order => 'number DESC')
22 :order => 'number DESC')
23 return last_sub
23 return last_sub
24 end
24 end
25
25
26 def self.find_all_last_by_problem(problem_id)
26 def self.find_all_last_by_problem(problem_id)
27 # need to put in SQL command, maybe there's a better way
27 # need to put in SQL command, maybe there's a better way
28 Submission.find_by_sql("SELECT * FROM submissions " +
28 Submission.find_by_sql("SELECT * FROM submissions " +
29 "WHERE id = " +
29 "WHERE id = " +
30 "(SELECT MAX(id) FROM submissions AS subs " +
30 "(SELECT MAX(id) FROM submissions AS subs " +
31 "WHERE subs.user_id = submissions.user_id AND " +
31 "WHERE subs.user_id = submissions.user_id AND " +
32 "problem_id = " + problem_id.to_s + " " +
32 "problem_id = " + problem_id.to_s + " " +
33 "GROUP BY user_id) " +
33 "GROUP BY user_id) " +
34 "ORDER BY user_id")
34 "ORDER BY user_id")
35 end
35 end
36
36
37 def self.find_last_for_all_available_problems(user_id)
37 def self.find_last_for_all_available_problems(user_id)
38 submissions = Array.new
38 submissions = Array.new
39 problems = Problem.find_available_problems
39 problems = Problem.find_available_problems
40 problems.each do |problem|
40 problems.each do |problem|
41 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
41 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
42 submissions << sub if sub!=nil
42 submissions << sub if sub!=nil
43 end
43 end
44 submissions
44 submissions
45 end
45 end
46
46
47 def self.find_by_user_problem_number(user_id, problem_id, number)
47 def self.find_by_user_problem_number(user_id, problem_id, number)
48 Submission.find(:first,
48 Submission.find(:first,
49 :conditions => {
49 :conditions => {
50 :user_id => user_id,
50 :user_id => user_id,
51 :problem_id => problem_id,
51 :problem_id => problem_id,
52 :number => number
52 :number => number
53 })
53 })
54 end
54 end
55
55
56 def self.find_all_by_user_problem(user_id, problem_id)
56 def self.find_all_by_user_problem(user_id, problem_id)
57 Submission.find(:all,
57 Submission.find(:all,
58 :conditions => {
58 :conditions => {
59 :user_id => user_id,
59 :user_id => user_id,
60 :problem_id => problem_id,
60 :problem_id => problem_id,
61 })
61 })
62 end
62 end
63
63
64 protected
64 protected
65
65
66 def self.find_option_in_source(option, source)
66 def self.find_option_in_source(option, source)
67 if source==nil
67 if source==nil
68 return nil
68 return nil
69 end
69 end
70 i = 0
70 i = 0
71 source.each_line do |s|
71 source.each_line do |s|
72 if s =~ option
72 if s =~ option
73 words = s.split
73 words = s.split
74 return words[1]
74 return words[1]
75 end
75 end
76 i = i + 1
76 i = i + 1
77 if i==10
77 if i==10
78 return nil
78 return nil
79 end
79 end
80 end
80 end
81 return nil
81 return nil
82 end
82 end
83
83
84 - def self.find_language_in_source(source)
84 + def self.find_language_in_source(source, source_filename="")
85 langopt = find_option_in_source(/^LANG:/,source)
85 langopt = find_option_in_source(/^LANG:/,source)
86 - if language = Language.find_by_name(langopt)
86 + if langopt
87 - return language
87 + return (Language.find_by_name(langopt) ||
88 - elsif language = Language.find_by_pretty_name(langopt)
88 + Language.find_by_pretty_name(langopt))
89 - return language
89 + else
90 + if source_filename
91 + return Language.find_by_extension(source_filename.split('.').last)
90 else
92 else
91 return nil
93 return nil
92 end
94 end
93 end
95 end
96 + end
94
97
95 def self.find_problem_in_source(source)
98 def self.find_problem_in_source(source)
96 prob_opt = find_option_in_source(/^TASK:/,source)
99 prob_opt = find_option_in_source(/^TASK:/,source)
97 if problem = Problem.find_by_name(prob_opt)
100 if problem = Problem.find_by_name(prob_opt)
98 return problem
101 return problem
99 else
102 else
100 return nil
103 return nil
101 end
104 end
102 end
105 end
103
106
104 def assign_problem
107 def assign_problem
105 if self.problem_id!=-1
108 if self.problem_id!=-1
106 begin
109 begin
107 self.problem = Problem.find(self.problem_id)
110 self.problem = Problem.find(self.problem_id)
108 rescue ActiveRecord::RecordNotFound
111 rescue ActiveRecord::RecordNotFound
109 self.problem = nil
112 self.problem = nil
110 end
113 end
111 else
114 else
112 self.problem = Submission.find_problem_in_source(self.source)
115 self.problem = Submission.find_problem_in_source(self.source)
113 end
116 end
114 end
117 end
115
118
116 def assign_language
119 def assign_language
117 - self.language = Submission.find_language_in_source(self.source)
120 + self.language = Submission.find_language_in_source(self.source,
121 + self.source_filename)
118 end
122 end
119
123
120 # validation codes
124 # validation codes
121 def must_specify_language
125 def must_specify_language
122 return if self.source==nil
126 return if self.source==nil
123
127
124 # for output_only tasks
128 # for output_only tasks
125 return if self.problem!=nil and self.problem.output_only
129 return if self.problem!=nil and self.problem.output_only
126
130
127 if self.language==nil
131 if self.language==nil
128 errors.add('source',"must specify programming language") unless self.language!=nil
132 errors.add('source',"must specify programming language") unless self.language!=nil
129 end
133 end
130 end
134 end
131
135
132 def must_have_valid_problem
136 def must_have_valid_problem
133 return if self.source==nil
137 return if self.source==nil
134 if self.problem==nil
138 if self.problem==nil
135 errors.add('problem',"must be specified.")
139 errors.add('problem',"must be specified.")
136 elsif (!self.problem.available) and (self.new_record?)
140 elsif (!self.problem.available) and (self.new_record?)
137 errors.add('problem',"must be valid.")
141 errors.add('problem',"must be valid.")
138 end
142 end
139 end
143 end
140
144
141 # callbacks
145 # callbacks
142 def assign_latest_number_if_new_recond
146 def assign_latest_number_if_new_recond
143 return if !self.new_record?
147 return if !self.new_record?
144 latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id)
148 latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id)
145 self.number = (latest==nil) ? 1 : latest.number + 1;
149 self.number = (latest==nil) ? 1 : latest.number + 1;
146 end
150 end
147
151
148 end
152 end
@@ -1,157 +1,158
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 # please use the migrations feature of Active Record to incrementally modify your database, and
2 # please use the migrations feature of Active Record to incrementally modify your database, and
3 # then regenerate this schema definition.
3 # then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 # to create the application database on another system, you should be using db:schema:load, not running
6 # to create the application database on another system, you should be using db:schema:load, not running
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 #
9 #
10 # It's strongly recommended to check this file into your version control system.
10 # It's strongly recommended to check this file into your version control system.
11
11
12 - ActiveRecord::Schema.define(:version => 20090206145016) do
12 + ActiveRecord::Schema.define(:version => 20090416235658) do
13
13
14 create_table "announcements", :force => true do |t|
14 create_table "announcements", :force => true do |t|
15 t.string "author"
15 t.string "author"
16 t.text "body"
16 t.text "body"
17 t.boolean "published"
17 t.boolean "published"
18 t.datetime "created_at"
18 t.datetime "created_at"
19 t.datetime "updated_at"
19 t.datetime "updated_at"
20 t.boolean "frontpage", :default => false
20 t.boolean "frontpage", :default => false
21 t.boolean "contest_only", :default => false
21 t.boolean "contest_only", :default => false
22 end
22 end
23
23
24 create_table "configurations", :force => true do |t|
24 create_table "configurations", :force => true do |t|
25 t.string "key"
25 t.string "key"
26 t.string "value_type"
26 t.string "value_type"
27 t.string "value"
27 t.string "value"
28 t.datetime "created_at"
28 t.datetime "created_at"
29 t.datetime "updated_at"
29 t.datetime "updated_at"
30 end
30 end
31
31
32 create_table "countries", :force => true do |t|
32 create_table "countries", :force => true do |t|
33 t.string "name"
33 t.string "name"
34 t.datetime "created_at"
34 t.datetime "created_at"
35 t.datetime "updated_at"
35 t.datetime "updated_at"
36 end
36 end
37
37
38 create_table "descriptions", :force => true do |t|
38 create_table "descriptions", :force => true do |t|
39 t.text "body"
39 t.text "body"
40 t.boolean "markdowned"
40 t.boolean "markdowned"
41 t.datetime "created_at"
41 t.datetime "created_at"
42 t.datetime "updated_at"
42 t.datetime "updated_at"
43 end
43 end
44
44
45 create_table "grader_processes", :force => true do |t|
45 create_table "grader_processes", :force => true do |t|
46 t.string "host", :limit => 20
46 t.string "host", :limit => 20
47 t.integer "pid"
47 t.integer "pid"
48 t.string "mode"
48 t.string "mode"
49 t.boolean "active"
49 t.boolean "active"
50 t.datetime "created_at"
50 t.datetime "created_at"
51 t.datetime "updated_at"
51 t.datetime "updated_at"
52 t.integer "task_id"
52 t.integer "task_id"
53 t.string "task_type"
53 t.string "task_type"
54 end
54 end
55
55
56 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
56 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
57
57
58 create_table "languages", :force => true do |t|
58 create_table "languages", :force => true do |t|
59 t.string "name", :limit => 10
59 t.string "name", :limit => 10
60 t.string "pretty_name"
60 t.string "pretty_name"
61 t.string "ext", :limit => 10
61 t.string "ext", :limit => 10
62 + t.string "common_ext"
62 end
63 end
63
64
64 create_table "messages", :force => true do |t|
65 create_table "messages", :force => true do |t|
65 t.integer "sender_id"
66 t.integer "sender_id"
66 t.integer "receiver_id"
67 t.integer "receiver_id"
67 t.integer "replying_message_id"
68 t.integer "replying_message_id"
68 t.text "body"
69 t.text "body"
69 t.boolean "replied"
70 t.boolean "replied"
70 t.datetime "created_at"
71 t.datetime "created_at"
71 t.datetime "updated_at"
72 t.datetime "updated_at"
72 end
73 end
73
74
74 create_table "problems", :force => true do |t|
75 create_table "problems", :force => true do |t|
75 t.string "name", :limit => 30
76 t.string "name", :limit => 30
76 t.string "full_name"
77 t.string "full_name"
77 t.integer "full_score"
78 t.integer "full_score"
78 t.date "date_added"
79 t.date "date_added"
79 t.boolean "available"
80 t.boolean "available"
80 t.string "url"
81 t.string "url"
81 t.integer "description_id"
82 t.integer "description_id"
82 t.boolean "test_allowed"
83 t.boolean "test_allowed"
83 t.boolean "output_only"
84 t.boolean "output_only"
84 end
85 end
85
86
86 create_table "rights", :force => true do |t|
87 create_table "rights", :force => true do |t|
87 t.string "name"
88 t.string "name"
88 t.string "controller"
89 t.string "controller"
89 t.string "action"
90 t.string "action"
90 end
91 end
91
92
92 create_table "rights_roles", :id => false, :force => true do |t|
93 create_table "rights_roles", :id => false, :force => true do |t|
93 t.integer "right_id"
94 t.integer "right_id"
94 t.integer "role_id"
95 t.integer "role_id"
95 end
96 end
96
97
97 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
98 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
98
99
99 create_table "roles", :force => true do |t|
100 create_table "roles", :force => true do |t|
100 t.string "name"
101 t.string "name"
101 end
102 end
102
103
103 create_table "roles_users", :id => false, :force => true do |t|
104 create_table "roles_users", :id => false, :force => true do |t|
104 t.integer "role_id"
105 t.integer "role_id"
105 t.integer "user_id"
106 t.integer "user_id"
106 end
107 end
107
108
108 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
109 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
109
110
110 create_table "sessions", :force => true do |t|
111 create_table "sessions", :force => true do |t|
111 t.string "session_id"
112 t.string "session_id"
112 t.text "data"
113 t.text "data"
113 t.datetime "updated_at"
114 t.datetime "updated_at"
114 end
115 end
115
116
116 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
117 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
117 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
118 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
118
119
119 create_table "sites", :force => true do |t|
120 create_table "sites", :force => true do |t|
120 t.string "name"
121 t.string "name"
121 t.boolean "started"
122 t.boolean "started"
122 t.datetime "start_time"
123 t.datetime "start_time"
123 t.datetime "created_at"
124 t.datetime "created_at"
124 t.datetime "updated_at"
125 t.datetime "updated_at"
125 t.integer "country_id"
126 t.integer "country_id"
126 t.string "password"
127 t.string "password"
127 end
128 end
128
129
129 create_table "submissions", :force => true do |t|
130 create_table "submissions", :force => true do |t|
130 t.integer "user_id"
131 t.integer "user_id"
131 t.integer "problem_id"
132 t.integer "problem_id"
132 t.integer "language_id"
133 t.integer "language_id"
133 t.text "source"
134 t.text "source"
134 t.binary "binary"
135 t.binary "binary"
135 t.datetime "submitted_at"
136 t.datetime "submitted_at"
136 t.datetime "compiled_at"
137 t.datetime "compiled_at"
137 t.text "compiler_message"
138 t.text "compiler_message"
138 t.datetime "graded_at"
139 t.datetime "graded_at"
139 t.integer "points"
140 t.integer "points"
140 t.text "grader_comment"
141 t.text "grader_comment"
141 t.integer "number"
142 t.integer "number"
142 t.string "source_filename"
143 t.string "source_filename"
143 end
144 end
144
145
145 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
146 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
146 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
147 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
147
148
148 create_table "tasks", :force => true do |t|
149 create_table "tasks", :force => true do |t|
149 t.integer "submission_id"
150 t.integer "submission_id"
150 t.datetime "created_at"
151 t.datetime "created_at"
151 t.integer "status"
152 t.integer "status"
152 t.datetime "updated_at"
153 t.datetime "updated_at"
153 end
154 end
154
155
155 create_table "test_requests", :force => true do |t|
156 create_table "test_requests", :force => true do |t|
156 t.integer "user_id"
157 t.integer "user_id"
157 t.integer "problem_id"
158 t.integer "problem_id"
You need to be logged in to leave comments. Login now