Show More
Commit Description:
add model solution
Commit Description:
add model solution
References:
File last commit:
Show/Diff file:
Action:
app/models/submission.rb
| 170 lines
| 4.9 KiB
| text/x-ruby
| RubyLexer
|
|
r0 | class Submission < ActiveRecord::Base | ||
r855 | enum tag: {default: 0, model: 1}, _prefix: true | |||
|
r0 | belongs_to :language | ||
belongs_to :problem | ||||
|
r1 | belongs_to :user | ||
|
r0 | |||
|
r99 | before_validation :assign_problem | ||
before_validation :assign_language | ||||
|
r31 | validates_presence_of :source | ||
r712 | validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'code too long, the limit is 100,000 bytes' | |||
|
r31 | validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short' | ||
|
r99 | validate :must_have_valid_problem | ||
|
r31 | validate :must_specify_language | ||
r645 | has_one :task | |||
|
r46 | before_save :assign_latest_number_if_new_recond | ||
|
r35 | |||
def self.find_last_by_user_and_problem(user_id, problem_id) | ||||
r619 | where("user_id = ? AND problem_id = ?",user_id,problem_id).last | |||
|
r0 | end | ||
|
r35 | def self.find_all_last_by_problem(problem_id) | ||
|
r0 | # need to put in SQL command, maybe there's a better way | ||
r448 | Submission.includes(:user).find_by_sql("SELECT * FROM submissions " + | |||
r855 | "WHERE id = " + | |||
"(SELECT MAX(id) FROM submissions AS subs " + | ||||
"WHERE subs.user_id = submissions.user_id AND " + | ||||
"problem_id = " + problem_id.to_s + " " + | ||||
"GROUP BY user_id) " + | ||||
"ORDER BY user_id") | ||||
|
r0 | end | ||
r350 | def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id) | |||
records = Submission.where(problem_id: problem_id,user_id: user_id) | ||||
r696 | records = records.where('id >= ?',since_id) if since_id and since_id > 0 | |||
records = records.where('id <= ?',until_id) if until_id and until_id > 0 | ||||
r350 | records.all | |||
end | ||||
|
r36 | def self.find_last_for_all_available_problems(user_id) | ||
submissions = Array.new | ||||
r619 | problems = Problem.available_problems | |||
|
r36 | 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) | ||||
r619 | where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first | |||
|
r36 | end | ||
|
r51 | def self.find_all_by_user_problem(user_id, problem_id) | ||
r619 | where("user_id = ? AND problem_id = ?",user_id,problem_id) | |||
|
r51 | end | ||
|
r168 | def download_filename | ||
if self.problem.output_only | ||||
return self.source_filename | ||||
else | ||||
timestamp = self.submitted_at.localtime.strftime("%H%M%S") | ||||
return "#{self.problem.name}-#{timestamp}.#{self.language.ext}" | ||||
end | ||||
end | ||||
|
r35 | protected | ||
|
r0 | def self.find_option_in_source(option, source) | ||
|
r31 | if source==nil | ||
return nil | ||||
end | ||||
|
r0 | i = 0 | ||
source.each_line do |s| | ||||
if s =~ option | ||||
r855 | words = s.split | |||
return words[1] | ||||
|
r0 | end | ||
i = i + 1 | ||||
if i==10 | ||||
r855 | return nil | |||
|
r0 | end | ||
end | ||||
return nil | ||||
end | ||||
|
r166 | def self.find_language_in_source(source, source_filename="") | ||
|
r0 | langopt = find_option_in_source(/^LANG:/,source) | ||
|
r166 | if langopt | ||
return (Language.find_by_name(langopt) || | ||||
Language.find_by_pretty_name(langopt)) | ||||
|
r0 | else | ||
|
r166 | if source_filename | ||
return Language.find_by_extension(source_filename.split('.').last) | ||||
else | ||||
return nil | ||||
end | ||||
|
r0 | end | ||
end | ||||
|
r167 | def self.find_problem_in_source(source, source_filename="") | ||
|
r0 | prob_opt = find_option_in_source(/^TASK:/,source) | ||
if problem = Problem.find_by_name(prob_opt) | ||||
return problem | ||||
else | ||||
|
r167 | if source_filename | ||
return Problem.find_by_name(source_filename.split('.').first) | ||||
else | ||||
return nil | ||||
end | ||||
|
r0 | end | ||
end | ||||
|
r99 | def assign_problem | ||
if self.problem_id!=-1 | ||||
begin | ||||
self.problem = Problem.find(self.problem_id) | ||||
rescue ActiveRecord::RecordNotFound | ||||
self.problem = nil | ||||
end | ||||
else | ||||
|
r167 | self.problem = Submission.find_problem_in_source(self.source, | ||
self.source_filename) | ||||
|
r99 | end | ||
end | ||||
def assign_language | ||||
|
r773 | if self.language == nil | ||
self.language = Submission.find_language_in_source(self.source, | ||||
self.source_filename) | ||||
end | ||||
|
r99 | end | ||
|
r31 | # validation codes | ||
def must_specify_language | ||||
return if self.source==nil | ||||
|
r99 | |||
# for output_only tasks | ||||
return if self.problem!=nil and self.problem.output_only | ||||
r682 | ||||
|
r773 | if self.language == nil | ||
errors.add('source',"Cannot detect language. Did you submit a correct source file?") | ||||
|
r99 | end | ||
|
r31 | end | ||
def must_have_valid_problem | ||||
return if self.source==nil | ||||
|
r99 | if self.problem==nil | ||
|
r87 | errors.add('problem',"must be specified.") | ||
r682 | else | |||
#admin always have right | ||||
return if self.user.admin? | ||||
#check if user has the right to submit the problem | ||||
r797 | errors[:base] << "Authorization error: you have no right to submit to this problem" if (!self.user.available_problems.include?(self.problem)) and (self.new_record?) | |||
|
r31 | end | ||
end | ||||
|
r35 | # callbacks | ||
|
r46 | def assign_latest_number_if_new_recond | ||
return if !self.new_record? | ||||
|
r35 | latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id) | ||
self.number = (latest==nil) ? 1 : latest.number + 1; | ||||
end | ||||
|
r0 | end | ||