Description:
added codejom_status model for computing level with basic user update
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r219:95cc49d72ca8 - - 9 files changed: 79 inserted, 1 deleted
@@ -0,0 +1,15 | |||||
|
|
1 | + class CreateCodejomStatuses < ActiveRecord::Migration | ||
|
|
2 | + def self.up | ||
|
|
3 | + create_table :codejom_statuses do |t| | ||
|
|
4 | + t.integer :user_id | ||
|
|
5 | + t.boolean :alive | ||
|
|
6 | + t.integer :num_problems_passed | ||
|
|
7 | + | ||
|
|
8 | + t.timestamps | ||
|
|
9 | + end | ||
|
|
10 | + end | ||
|
|
11 | + | ||
|
|
12 | + def self.down | ||
|
|
13 | + drop_table :codejom_statuses | ||
|
|
14 | + end | ||
|
|
15 | + end |
@@ -0,0 +1,11 | |||||
|
|
1 | + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html | ||
|
|
2 | + | ||
|
|
3 | + one: | ||
|
|
4 | + user_id: 1 | ||
|
|
5 | + alive: false | ||
|
|
6 | + num_problems_passed: 1 | ||
|
|
7 | + | ||
|
|
8 | + two: | ||
|
|
9 | + user_id: 1 | ||
|
|
10 | + alive: false | ||
|
|
11 | + num_problems_passed: 1 |
@@ -0,0 +1,8 | |||||
|
|
1 | + require 'test_helper' | ||
|
|
2 | + | ||
|
|
3 | + class CodejomStatusTest < ActiveSupport::TestCase | ||
|
|
4 | + # Replace this with your real tests. | ||
|
|
5 | + test "the truth" do | ||
|
|
6 | + assert true | ||
|
|
7 | + end | ||
|
|
8 | + end |
@@ -219,48 +219,49 | |||||
|
219 | points = passed ? 100 : 0 |
|
219 | points = passed ? 100 : 0 |
|
220 | submission = Submission.new(:user => user, |
|
220 | submission = Submission.new(:user => user, |
|
221 | :problem => problem, |
|
221 | :problem => problem, |
|
222 | :source => submitted_solution, |
|
222 | :source => submitted_solution, |
|
223 | :source_filename => params['file'].original_filename, |
|
223 | :source_filename => params['file'].original_filename, |
|
224 | :language_id => 0, |
|
224 | :language_id => 0, |
|
225 | :submitted_at => Time.new.gmtime, |
|
225 | :submitted_at => Time.new.gmtime, |
|
226 | :graded_at => Time.new.gmtime, |
|
226 | :graded_at => Time.new.gmtime, |
|
227 | :points => points) |
|
227 | :points => points) |
|
228 | submission.save |
|
228 | submission.save |
|
229 | recent_assignment.submitted = true |
|
229 | recent_assignment.submitted = true |
|
230 | recent_assignment.save |
|
230 | recent_assignment.save |
|
231 |
|
231 | ||
|
232 | status = user.get_submission_status_for(problem) |
|
232 | status = user.get_submission_status_for(problem) |
|
233 | if status == nil |
|
233 | if status == nil |
|
234 | status = SubmissionStatus.new :user => user, :problem => problem, :submission_count => 0 |
|
234 | status = SubmissionStatus.new :user => user, :problem => problem, :submission_count => 0 |
|
235 | end |
|
235 | end |
|
236 |
|
236 | ||
|
237 | status.submission_count += 1 |
|
237 | status.submission_count += 1 |
|
238 | status.passed = passed |
|
238 | status.passed = passed |
|
239 | status.save |
|
239 | status.save |
|
240 |
|
240 | ||
|
241 | if passed |
|
241 | if passed |
|
242 | flash[:notice] = 'Correct solution.' |
|
242 | flash[:notice] = 'Correct solution.' |
|
|
243 | + user.update_codejom_status | ||
|
243 | else |
|
244 | else |
|
244 | flash[:notice] = 'Incorrect solution.' |
|
245 | flash[:notice] = 'Incorrect solution.' |
|
245 | end |
|
246 | end |
|
246 | redirect_to :action => 'list' |
|
247 | redirect_to :action => 'list' |
|
247 | end |
|
248 | end |
|
248 |
|
249 | ||
|
249 | protected |
|
250 | protected |
|
250 |
|
251 | ||
|
251 | def prepare_announcements(recent=nil) |
|
252 | def prepare_announcements(recent=nil) |
|
252 | if Configuration.show_tasks_to?(@user) |
|
253 | if Configuration.show_tasks_to?(@user) |
|
253 | @announcements = Announcement.find_published(true) |
|
254 | @announcements = Announcement.find_published(true) |
|
254 | else |
|
255 | else |
|
255 | @announcements = Announcement.find_published |
|
256 | @announcements = Announcement.find_published |
|
256 | end |
|
257 | end |
|
257 | if recent!=nil |
|
258 | if recent!=nil |
|
258 | recent_id = recent.to_i |
|
259 | recent_id = recent.to_i |
|
259 | @announcements = @announcements.find_all { |a| a.id > recent_id } |
|
260 | @announcements = @announcements.find_all { |a| a.id > recent_id } |
|
260 | end |
|
261 | end |
|
261 | end |
|
262 | end |
|
262 |
|
263 | ||
|
263 | def prepare_list_information |
|
264 | def prepare_list_information |
|
264 | @user = User.find(session[:user_id]) |
|
265 | @user = User.find(session[:user_id]) |
|
265 |
|
266 | ||
|
266 | all_problems = Problem.find_available_problems |
|
267 | all_problems = Problem.find_available_problems |
@@ -8,48 +8,53 | |||||
|
8 | validates_presence_of :full_name |
|
8 | validates_presence_of :full_name |
|
9 |
|
9 | ||
|
10 | DEFAULT_TIME_LIMIT = 1 |
|
10 | DEFAULT_TIME_LIMIT = 1 |
|
11 | DEFAULT_MEMORY_LIMIT = 32 |
|
11 | DEFAULT_MEMORY_LIMIT = 32 |
|
12 |
|
12 | ||
|
13 | def test_pair_count |
|
13 | def test_pair_count |
|
14 | @test_pair_count ||= test_pairs.size |
|
14 | @test_pair_count ||= test_pairs.size |
|
15 | end |
|
15 | end |
|
16 |
|
16 | ||
|
17 | def uses_random_test_pair? |
|
17 | def uses_random_test_pair? |
|
18 | test_pair_count != 0 |
|
18 | test_pair_count != 0 |
|
19 | end |
|
19 | end |
|
20 |
|
20 | ||
|
21 | def random_test_pair(forbidden_numbers=nil) |
|
21 | def random_test_pair(forbidden_numbers=nil) |
|
22 | begin |
|
22 | begin |
|
23 | test_num = 1 + rand(test_pair_count) |
|
23 | test_num = 1 + rand(test_pair_count) |
|
24 | end while forbidden_numbers!=nil and forbidden_numbers.include? test_num |
|
24 | end while forbidden_numbers!=nil and forbidden_numbers.include? test_num |
|
25 | test_pairs.find_by_number test_num |
|
25 | test_pairs.find_by_number test_num |
|
26 | end |
|
26 | end |
|
27 |
|
27 | ||
|
28 | def self.find_available_problems |
|
28 | def self.find_available_problems |
|
29 | find(:all, :conditions => {:available => true}, :order => "date_added DESC") |
|
29 | find(:all, :conditions => {:available => true}, :order => "date_added DESC") |
|
30 | end |
|
30 | end |
|
31 |
|
31 | ||
|
|
32 | + # TODO: may try to optimize this using cache | ||
|
|
33 | + def self.available_problem_count | ||
|
|
34 | + return Problem.find_available_problems.length | ||
|
|
35 | + end | ||
|
|
36 | + | ||
|
32 | def self.create_from_import_form_params(params, old_problem=nil) |
|
37 | def self.create_from_import_form_params(params, old_problem=nil) |
|
33 | problem = old_problem || Problem.new |
|
38 | problem = old_problem || Problem.new |
|
34 | import_params = Problem.extract_params_and_check(params, problem) |
|
39 | import_params = Problem.extract_params_and_check(params, problem) |
|
35 |
|
40 | ||
|
36 | if not problem.valid? |
|
41 | if not problem.valid? |
|
37 | return problem, 'Error importing' |
|
42 | return problem, 'Error importing' |
|
38 | end |
|
43 | end |
|
39 |
|
44 | ||
|
40 | problem.full_score = 100 |
|
45 | problem.full_score = 100 |
|
41 | problem.date_added = Time.new |
|
46 | problem.date_added = Time.new |
|
42 | problem.test_allowed = true |
|
47 | problem.test_allowed = true |
|
43 | problem.output_only = false |
|
48 | problem.output_only = false |
|
44 | problem.available = false |
|
49 | problem.available = false |
|
45 |
|
50 | ||
|
46 | if not problem.save |
|
51 | if not problem.save |
|
47 | return problem, 'Error importing' |
|
52 | return problem, 'Error importing' |
|
48 | end |
|
53 | end |
|
49 |
|
54 | ||
|
50 | import_to_db = params.has_key? :import_to_db |
|
55 | import_to_db = params.has_key? :import_to_db |
|
51 |
|
56 | ||
|
52 | importer = TestdataImporter.new(problem) |
|
57 | importer = TestdataImporter.new(problem) |
|
53 |
|
58 | ||
|
54 | if not importer.import_from_file(import_params[:file], |
|
59 | if not importer.import_from_file(import_params[:file], |
|
55 | import_params[:time_limit], |
|
60 | import_params[:time_limit], |
@@ -3,48 +3,51 | |||||
|
3 | class User < ActiveRecord::Base |
|
3 | class User < ActiveRecord::Base |
|
4 |
|
4 | ||
|
5 | has_and_belongs_to_many :roles |
|
5 | has_and_belongs_to_many :roles |
|
6 |
|
6 | ||
|
7 | has_many :test_requests, :order => "submitted_at DESC" |
|
7 | has_many :test_requests, :order => "submitted_at DESC" |
|
8 |
|
8 | ||
|
9 | has_many :messages, |
|
9 | has_many :messages, |
|
10 | :class_name => "Message", |
|
10 | :class_name => "Message", |
|
11 | :foreign_key => "sender_id", |
|
11 | :foreign_key => "sender_id", |
|
12 | :order => 'created_at DESC' |
|
12 | :order => 'created_at DESC' |
|
13 |
|
13 | ||
|
14 | has_many :replied_messages, |
|
14 | has_many :replied_messages, |
|
15 | :class_name => "Message", |
|
15 | :class_name => "Message", |
|
16 | :foreign_key => "receiver_id", |
|
16 | :foreign_key => "receiver_id", |
|
17 | :order => 'created_at DESC' |
|
17 | :order => 'created_at DESC' |
|
18 |
|
18 | ||
|
19 | has_many :test_pair_assignments, :dependent => :delete_all |
|
19 | has_many :test_pair_assignments, :dependent => :delete_all |
|
20 | has_many :submission_statuses |
|
20 | has_many :submission_statuses |
|
21 |
|
21 | ||
|
22 | has_one :contest_stat, :class_name => "UserContestStat" |
|
22 | has_one :contest_stat, :class_name => "UserContestStat" |
|
23 |
|
23 | ||
|
24 | belongs_to :site |
|
24 | belongs_to :site |
|
25 | belongs_to :country |
|
25 | belongs_to :country |
|
26 |
|
26 | ||
|
|
27 | + # For Code Jom | ||
|
|
28 | + has_one :codejom_status | ||
|
|
29 | + | ||
|
27 | named_scope :activated_users, :conditions => {:activated => true} |
|
30 | named_scope :activated_users, :conditions => {:activated => true} |
|
28 |
|
31 | ||
|
29 | validates_presence_of :login |
|
32 | validates_presence_of :login |
|
30 | validates_uniqueness_of :login |
|
33 | validates_uniqueness_of :login |
|
31 | validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/ |
|
34 | validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/ |
|
32 | validates_length_of :login, :within => 3..30 |
|
35 | validates_length_of :login, :within => 3..30 |
|
33 |
|
36 | ||
|
34 | validates_presence_of :full_name |
|
37 | validates_presence_of :full_name |
|
35 | validates_length_of :full_name, :minimum => 1 |
|
38 | validates_length_of :full_name, :minimum => 1 |
|
36 |
|
39 | ||
|
37 | validates_presence_of :password, :if => :password_required? |
|
40 | validates_presence_of :password, :if => :password_required? |
|
38 | validates_length_of :password, :within => 4..20, :if => :password_required? |
|
41 | validates_length_of :password, :within => 4..20, :if => :password_required? |
|
39 | validates_confirmation_of :password, :if => :password_required? |
|
42 | validates_confirmation_of :password, :if => :password_required? |
|
40 |
|
43 | ||
|
41 | validates_format_of :email, |
|
44 | validates_format_of :email, |
|
42 | :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, |
|
45 | :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, |
|
43 | :if => :email_validation? |
|
46 | :if => :email_validation? |
|
44 | validate :uniqueness_of_email_from_activated_users, |
|
47 | validate :uniqueness_of_email_from_activated_users, |
|
45 | :if => :email_validation? |
|
48 | :if => :email_validation? |
|
46 | validate :enough_time_interval_between_same_email_registrations, |
|
49 | validate :enough_time_interval_between_same_email_registrations, |
|
47 | :if => :email_validation? |
|
50 | :if => :email_validation? |
|
48 |
|
51 | ||
|
49 | # these are for ytopc |
|
52 | # these are for ytopc |
|
50 | # disable for now |
|
53 | # disable for now |
@@ -200,48 +203,66 | |||||
|
200 | def contest_finished? |
|
203 | def contest_finished? |
|
201 | if Configuration.contest_mode? |
|
204 | if Configuration.contest_mode? |
|
202 | return false if site==nil |
|
205 | return false if site==nil |
|
203 | return site.finished? |
|
206 | return site.finished? |
|
204 | elsif Configuration.indv_contest_mode? |
|
207 | elsif Configuration.indv_contest_mode? |
|
205 | time_limit = Configuration.contest_time_limit |
|
208 | time_limit = Configuration.contest_time_limit |
|
206 |
|
209 | ||
|
207 | return false if contest_stat==nil |
|
210 | return false if contest_stat==nil |
|
208 |
|
211 | ||
|
209 | return contest_time_left == 0 |
|
212 | return contest_time_left == 0 |
|
210 | else |
|
213 | else |
|
211 | return false |
|
214 | return false |
|
212 | end |
|
215 | end |
|
213 | end |
|
216 | end |
|
214 |
|
217 | ||
|
215 | def contest_started? |
|
218 | def contest_started? |
|
216 | if Configuration.contest_mode? |
|
219 | if Configuration.contest_mode? |
|
217 | return true if site==nil |
|
220 | return true if site==nil |
|
218 | return site.started |
|
221 | return site.started |
|
219 | else |
|
222 | else |
|
220 | return true |
|
223 | return true |
|
221 | end |
|
224 | end |
|
222 | end |
|
225 | end |
|
223 |
|
226 | ||
|
|
227 | + # For Code Jom | ||
|
|
228 | + def update_codejom_status | ||
|
|
229 | + status = codejom_status || CodejomStatus.new(:user => self) | ||
|
|
230 | + problem_count = Problem.available_problem_count | ||
|
|
231 | + status.num_problems_passed = (self.submission_statuses.find_all {|s| s.passed}).length | ||
|
|
232 | + status.alive = (problem_count - (status.num_problems_passed)) <= CODEJOM_MAX_ALIVE_LEVEL | ||
|
|
233 | + status.save | ||
|
|
234 | + end | ||
|
|
235 | + | ||
|
|
236 | + def codejom_level | ||
|
|
237 | + problem_count = Problem.available_problem_count | ||
|
|
238 | + if codejom_status!=nil | ||
|
|
239 | + return problem_count - codejom_status.num_problems_passed | ||
|
|
240 | + else | ||
|
|
241 | + return problem_count | ||
|
|
242 | + end | ||
|
|
243 | + end | ||
|
|
244 | + | ||
|
224 | protected |
|
245 | protected |
|
225 | def encrypt_new_password |
|
246 | def encrypt_new_password |
|
226 | return if password.blank? |
|
247 | return if password.blank? |
|
227 | self.salt = (10+rand(90)).to_s |
|
248 | self.salt = (10+rand(90)).to_s |
|
228 | self.hashed_password = User.encrypt(self.password,self.salt) |
|
249 | self.hashed_password = User.encrypt(self.password,self.salt) |
|
229 | end |
|
250 | end |
|
230 |
|
251 | ||
|
231 | def assign_default_site |
|
252 | def assign_default_site |
|
232 | # have to catch error when migrating (because self.site is not available). |
|
253 | # have to catch error when migrating (because self.site is not available). |
|
233 | begin |
|
254 | begin |
|
234 | if self.site==nil |
|
255 | if self.site==nil |
|
235 | self.site = Site.find_by_name('default') |
|
256 | self.site = Site.find_by_name('default') |
|
236 | if self.site==nil |
|
257 | if self.site==nil |
|
237 | self.site = Site.find(1) # when 'default has be renamed' |
|
258 | self.site = Site.find(1) # when 'default has be renamed' |
|
238 | end |
|
259 | end |
|
239 | end |
|
260 | end |
|
240 | rescue |
|
261 | rescue |
|
241 | end |
|
262 | end |
|
242 | end |
|
263 | end |
|
243 |
|
264 | ||
|
244 | def password_required? |
|
265 | def password_required? |
|
245 | self.hashed_password.blank? || !self.password.blank? |
|
266 | self.hashed_password.blank? || !self.password.blank? |
|
246 | end |
|
267 | end |
|
247 |
|
268 |
@@ -82,24 +82,28 | |||||
|
82 | # These are where inputs and outputs of test requests are stored |
|
82 | # These are where inputs and outputs of test requests are stored |
|
83 | TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input' |
|
83 | TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input' |
|
84 | TEST_REQUEST_OUTPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/output' |
|
84 | TEST_REQUEST_OUTPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/output' |
|
85 |
|
85 | ||
|
86 | # To use ANALYSIS MODE, provide the testcases/testruns breakdown, |
|
86 | # To use ANALYSIS MODE, provide the testcases/testruns breakdown, |
|
87 | # and the directory of the grading result (usually in judge's dir). |
|
87 | # and the directory of the grading result (usually in judge's dir). |
|
88 | TASK_GRADING_INFO_FILENAME = RAILS_ROOT + '/config/tasks.yml' |
|
88 | TASK_GRADING_INFO_FILENAME = RAILS_ROOT + '/config/tasks.yml' |
|
89 |
|
89 | ||
|
90 | # TODO: change this to where results are kept. |
|
90 | # TODO: change this to where results are kept. |
|
91 | GRADING_RESULT_DIR = 'RESULT-DIR' |
|
91 | GRADING_RESULT_DIR = 'RESULT-DIR' |
|
92 |
|
92 | ||
|
93 | # Change this to allow importing testdata into database as test-pairs. |
|
93 | # Change this to allow importing testdata into database as test-pairs. |
|
94 | # This is mainly for Code Jom contest. |
|
94 | # This is mainly for Code Jom contest. |
|
95 | ALLOW_TEST_PAIR_IMPORT = false |
|
95 | ALLOW_TEST_PAIR_IMPORT = false |
|
96 |
|
96 | ||
|
97 | # Uncomment so that the system validates user e-mails |
|
97 | # Uncomment so that the system validates user e-mails |
|
98 | # VALIDATE_USER_EMAILS = true |
|
98 | # VALIDATE_USER_EMAILS = true |
|
99 |
|
99 | ||
|
100 | # Uncomment so that Apache X-Sendfile is used when delivering files |
|
100 | # Uncomment so that Apache X-Sendfile is used when delivering files |
|
101 | # (e.g., in /tasks/view). |
|
101 | # (e.g., in /tasks/view). |
|
102 | # USE_APACHE_XSENDFILE = true |
|
102 | # USE_APACHE_XSENDFILE = true |
|
103 |
|
103 | ||
|
104 | # Uncomment so that configuration is read only once when the server is loaded |
|
104 | # Uncomment so that configuration is read only once when the server is loaded |
|
105 | # Configuration.enable_caching |
|
105 | # Configuration.enable_caching |
|
|
106 | + | ||
|
|
107 | + # OPTIONS FOR CODE JOM | ||
|
|
108 | + # -------------------- | ||
|
|
109 | + CODEJOM_MAX_ALIVE_LEVEL = 10 |
@@ -1,48 +1,56 | |||||
|
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 => 20100124 |
|
12 | + ActiveRecord::Schema.define(:version => 20100124191250) 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 | t.string "title" |
|
22 | t.string "title" |
|
23 | end |
|
23 | end |
|
24 |
|
24 | ||
|
|
25 | + create_table "codejom_statuses", :force => true do |t| | ||
|
|
26 | + t.integer "user_id" | ||
|
|
27 | + t.boolean "alive" | ||
|
|
28 | + t.integer "num_problems_passed" | ||
|
|
29 | + t.datetime "created_at" | ||
|
|
30 | + t.datetime "updated_at" | ||
|
|
31 | + end | ||
|
|
32 | + | ||
|
25 | create_table "configurations", :force => true do |t| |
|
33 | create_table "configurations", :force => true do |t| |
|
26 | t.string "key" |
|
34 | t.string "key" |
|
27 | t.string "value_type" |
|
35 | t.string "value_type" |
|
28 | t.string "value" |
|
36 | t.string "value" |
|
29 | t.datetime "created_at" |
|
37 | t.datetime "created_at" |
|
30 | t.datetime "updated_at" |
|
38 | t.datetime "updated_at" |
|
31 | t.text "description" |
|
39 | t.text "description" |
|
32 | end |
|
40 | end |
|
33 |
|
41 | ||
|
34 | create_table "countries", :force => true do |t| |
|
42 | create_table "countries", :force => true do |t| |
|
35 | t.string "name" |
|
43 | t.string "name" |
|
36 | t.datetime "created_at" |
|
44 | t.datetime "created_at" |
|
37 | t.datetime "updated_at" |
|
45 | t.datetime "updated_at" |
|
38 | end |
|
46 | end |
|
39 |
|
47 | ||
|
40 | create_table "descriptions", :force => true do |t| |
|
48 | create_table "descriptions", :force => true do |t| |
|
41 | t.text "body" |
|
49 | t.text "body" |
|
42 | t.boolean "markdowned" |
|
50 | t.boolean "markdowned" |
|
43 | t.datetime "created_at" |
|
51 | t.datetime "created_at" |
|
44 | t.datetime "updated_at" |
|
52 | t.datetime "updated_at" |
|
45 | end |
|
53 | end |
|
46 |
|
54 | ||
|
47 | create_table "grader_processes", :force => true do |t| |
|
55 | create_table "grader_processes", :force => true do |t| |
|
48 | t.string "host", :limit => 20 |
|
56 | t.string "host", :limit => 20 |
You need to be logged in to leave comments.
Login now