Judge0Tsting / app /models /submission.rb
AdityaSharmaTech's picture
Upload 177 files
def1299 verified
# == Schema Information
#
# Table name: submissions
#
# id :integer not null, primary key
# source_code :text
# language_id :integer
# stdin :text
# expected_output :text
# stdout :text
# status_id :integer
# created_at :datetime
# finished_at :datetime
# time :decimal(, )
# memory :integer
# stderr :text
# token :string
# number_of_runs :integer
# cpu_time_limit :decimal(, )
# cpu_extra_time :decimal(, )
# wall_time_limit :decimal(, )
# memory_limit :integer
# stack_limit :integer
# max_processes_and_or_threads :integer
# enable_per_process_and_thread_time_limit :boolean
# enable_per_process_and_thread_memory_limit :boolean
# max_file_size :integer
# compile_output :text
# exit_code :integer
# exit_signal :integer
# message :text
# wall_time :decimal(, )
# compiler_options :string
# command_line_arguments :string
# redirect_stderr_to_stdout :boolean
# callback_url :string
# additional_files :binary
# enable_network :boolean
# started_at :datetime
# queued_at :datetime
# updated_at :datetime
# queue_host :string
# execution_host :string
#
class Submission < ApplicationRecord
validates :source_code, presence: true, unless: -> { is_project }
validates :source_code, absence: true, if: -> { is_project }
validates :additional_files, presence: true, if: -> { is_project }
validates :language_id, presence: true
validates :number_of_runs,
numericality: { greater_than: 0, less_than_or_equal_to: Config::MAX_NUMBER_OF_RUNS }
validates :cpu_time_limit,
numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: Config::MAX_CPU_TIME_LIMIT }
validates :cpu_extra_time,
numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: Config::MAX_CPU_EXTRA_TIME }
validates :wall_time_limit,
numericality: { greater_than_or_equal_to: 1, less_than_or_equal_to: Config::MAX_WALL_TIME_LIMIT }
validates :memory_limit,
numericality: { greater_than_or_equal_to: 2048, less_than_or_equal_to: Config::MAX_MEMORY_LIMIT }
validates :stack_limit,
numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: Config::MAX_STACK_LIMIT }
validates :max_processes_and_or_threads,
numericality: { greater_than: 0, less_than_or_equal_to: Config::MAX_MAX_PROCESSES_AND_OR_THREADS }
validates :enable_per_process_and_thread_time_limit,
inclusion: { in: [false], message: "this option cannot be enabled" },
unless: -> { Config::ALLOW_ENABLE_PER_PROCESS_AND_THREAD_TIME_LIMIT }
validates :enable_per_process_and_thread_memory_limit,
inclusion: { in: [false], message: "this option cannot be enabled" },
unless: -> { Config::ALLOW_ENABLE_PER_PROCESS_AND_THREAD_MEMORY_LIMIT }
validates :max_file_size,
numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: Config::MAX_MAX_FILE_SIZE }
validates :compiler_options, length: { maximum: 512 }
validates :command_line_arguments, length: { maximum: 512 }
validate :language_existence, :compiler_options_allowed,
:command_line_arguments_allowed, :callbacks_allowed,
:additional_files_allowed, :network_allowed
before_create :generate_token
before_validation :set_defaults
enumeration :status
default_scope { order(created_at: :desc) }
self.per_page = 20
def source_code
@decoded_source_code ||= Base64Service.decode(self[:source_code])
end
def source_code=(value)
super(value)
self[:source_code] = Base64Service.encode(self[:source_code])
end
def stdin
@decoded_stdin ||= Base64Service.decode(self[:stdin])
end
def stdin=(value)
super(value)
self[:stdin] = Base64Service.encode(self[:stdin])
end
def stdout
@decoded_stdout ||= Base64Service.decode(self[:stdout])
end
def stdout=(value)
super(value)
self[:stdout] = Base64Service.encode(self[:stdout])
end
def expected_output
@decoded_expected_output ||= Base64Service.decode(self[:expected_output])
end
def expected_output=(value)
super(value)
self[:expected_output] = Base64Service.encode(self[:expected_output])
end
def stderr
@decoded_stderr ||= Base64Service.decode(self[:stderr])
end
def stderr=(value)
super(value)
self[:stderr] = Base64Service.encode(self[:stderr])
end
def compile_output
@decoded_compile_output ||= Base64Service.decode(self[:compile_output])
end
def compile_output=(value)
super(value)
self[:compile_output] = Base64Service.encode(self[:compile_output])
end
def language
@language ||= Language.unscoped.find_by(id: language_id)
end
def status
Status.find_by(id: status_id)
end
def status=(status)
self.status_id = status.id
end
def is_project
language.try(:is_project) || false
end
private
def language_existence
if not language
errors.add(:language_id, "language with id #{language_id} doesn't exist")
elsif language.is_archived
errors.add(:language_id, "language with id #{language_id} is archived and cannot be used anymore")
end
end
def compiler_options_allowed
return if compiler_options.blank?
unless Config::ENABLE_COMPILER_OPTIONS
errors.add(:compiler_options, "setting compiler options is not allowed")
return
end
if language && language.compile_cmd.nil?
errors.add(:compiler_options, "setting compiler options is only allowed for compiled languages")
return
end
@@allowed_languages ||= Config::ALLOWED_LANGUAGES_FOR_COMPILER_OPTIONS.collect{ |s| s + " " }
if language && @@allowed_languages.present? && !language.name.starts_with?(*@@allowed_languages)
@@allowed_languages_message ||= @@allowed_languages.size > 1 ? @@allowed_languages[0..-2].collect{ |s| s.strip }.join(", ") + " and " + @@allowed_languages[-1].strip : @@allowed_languages[0].strip
errors.add(:compiler_options, "setting compiler options is only allowed for #{@@allowed_languages_message}")
end
end
def command_line_arguments_allowed
return if command_line_arguments.blank?
unless Config::ENABLE_COMMAND_LINE_ARGUMENTS
errors.add(:command_line_arguments, "setting command line arguments is not allowed")
end
end
def callbacks_allowed
return if callback_url.blank?
unless Config::ENABLE_CALLBACKS
errors.add(:callback_url, "setting callback is not allowed")
end
end
def additional_files_allowed
return if additional_files.blank?
unless Config::ENABLE_ADDITIONAL_FILES
errors.add(:additional_files, "setting additional files is not allowed")
end
end
def network_allowed
return if enable_network.blank?
unless Config::ALLOW_ENABLE_NETWORK
errors.add(:enable_network, "enabling network is not allowed")
end
end
def generate_token
begin
self.token = SecureRandom.uuid
end while self.class.exists?(token: token)
end
def set_defaults
self.status ||= Status.queue
self.number_of_runs ||= Config::NUMBER_OF_RUNS
self.cpu_time_limit ||= Config::CPU_TIME_LIMIT
self.cpu_extra_time ||= Config::CPU_EXTRA_TIME
self.wall_time_limit ||= Config::WALL_TIME_LIMIT
self.memory_limit ||= Config::MEMORY_LIMIT
self.stack_limit ||= Config::STACK_LIMIT
self.max_processes_and_or_threads ||= Config::MAX_PROCESSES_AND_OR_THREADS
self.enable_per_process_and_thread_time_limit = NilValue.value_or_default(
self.enable_per_process_and_thread_time_limit,
Config::ENABLE_PER_PROCESS_AND_THREAD_TIME_LIMIT
)
self.enable_per_process_and_thread_memory_limit = NilValue.value_or_default(
self.enable_per_process_and_thread_memory_limit,
Config::ENABLE_PER_PROCESS_AND_THREAD_MEMORY_LIMIT
)
self.max_file_size ||= Config::MAX_FILE_SIZE
self.redirect_stderr_to_stdout = NilValue.value_or_default(
self.redirect_stderr_to_stdout,
Config::REDIRECT_STDERR_TO_STDOUT
)
self.enable_network = NilValue.value_or_default(
self.enable_network,
Config::ENABLE_NETWORK
)
end
end