class Contest::Driver::CodeforcesDriver

Public Instance Methods

get_desc() click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 44
def get_desc
  "Codeforces (URL: http://codeforces.com/)"
end
get_opts_ext() click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 19
def get_opts_ext
  define_options do
    opt(
      :contest_id,
      "Contest ID (Ex: 100, 234, etc...)",
      :type => :string,
      :required => true,
    )
    opt(
      :problem_id,
      "Problem ID (Ex: A, B, etc...)",
      :type => :string,
      :required => true,
    )
  end
end
get_problem_id(options) click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 40
def get_problem_id(options)
  "#{options[:contest_id]}#{options[:problem_id]}"
end
get_site_name() click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 36
def get_site_name
  "Codeforces"
end
initialize_ext() click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 13
def initialize_ext
  @client = Mechanize.new {|agent|
    agent.user_agent_alias = 'Windows IE 7'
  }
end
resolve_language(label) click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 48
def resolve_language(label)
  case label
  when "clang"
    return "10"
  when "cpp"
    return "1"
  when "cpp11"
    return "16"
  when "cs"
    return "9"
  when "dlang"
    return "28"
  when "golang"
    return "32"
  when "haskell"
    return "12"
  when "java"
    return "23"
  when "ocaml"
    return "19"
  when "delphi"
    return "3"
  when "pascal"
    return "4"
  when "perl"
    return "13"
  when "php"
    return "6"
  when "python2"
    return "7"
  when "python3"
    return "31"
  when "ruby"
    return "8"
  when "scala"
    return "20"
  else
    abort "unknown languag"
  end
end
submit_ext() click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 89
def submit_ext()
  # start
  trigger 'start'
  contest_id = @options[:contest_id]
  problem_id = @options[:problem_id]

  # login
  trigger 'before_login'
  login_page = @client.get 'http://codeforces.com/enter'
  login_page.form_with(:action => '') do |form|
    form.handle = @config["user"]
    form.password = @config["password"]
  end.submit
  trigger 'after_login'

  # submit
  trigger 'before_submit', @options
  # retry once
  retries = 1
  begin
    submit_page = @client.get "http://codeforces.com/contest/#{contest_id}/submit"
    res_page = submit_page.form_with(:class => 'submit-form') do |form|
      form.submittedProblemIndex = problem_id
      form.programTypeId = @options[:language]
      form.source = File.read(@options[:source])
    end.submit
  rescue => e
    raise if retries == 0
    retries -= 1
    # may not be registered practice
    if /submittedProblemIndex/ =~ e.to_s
      contest_page = @client.get "http://codeforces.com/contest/#{contest_id}"
      contest_page.form_with(:action => "") do |form|
        flag_need_to_register = false
        form.field_with(:value => "registerForPractice") do |field|
          flag_need_to_register = true
        end
        form.click_button if flag_need_to_register
      end
      sleep 3
      retry
    end
    raise
  end
  trigger 'after_submit'

  # need to get the newest waiting submissionId
  submission_id = get_submission_id(res_page.body)
  trigger(
    'before_wait',
    {
      :submission_id => submission_id,
    }
  )

  # wait result
  status = get_status_wait(contest_id, submission_id)
  trigger(
    'after_wait',
    {
      :submission_id => submission_id,
      :status => status,
      :result => get_commit_message(status),
    }
  )

  trigger 'finish'
  get_commit_message(status)
end

Private Instance Methods

get_status(submission_id, body) click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 181
def get_status(submission_id, body)
  doc = Nokogiri::HTML(body)
  element = doc.xpath('//td[@submissionid="' + submission_id + '"]')[0]
  element.text().strip
end
get_status_wait(contest_id, submission_id) click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 160
def get_status_wait(contest_id, submission_id)
  contest_id = contest_id.to_s
  submission_id = submission_id.to_s
  # wait result
  5.times do
    sleep 3
    my_page = @client.get "http://codeforces.com/contest/#{contest_id}/my"
    status = get_status(submission_id, my_page.body)
    return status unless is_waiting(submission_id, my_page.body)
    trigger 'retry'
  end
  trigger 'timeout'
  return 'timeout'
end
get_submission_id(body) click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 187
def get_submission_id(body)
  doc = Nokogiri::HTML(body)
  # get first td.status-cell
  line = doc.xpath('//td/a[contains(./text() , "' + @config["user"] + '")]').xpath('../..')[0]
  elements = line.xpath('//td[contains(concat(" ",@class," "), " status-cell ")]')
  elements[0].attributes()["submissionid"].value.strip
end
is_waiting(submission_id, body) click to toggle source
# File lib/contest/driver/codeforces_driver.rb, line 175
def is_waiting(submission_id, body)
  doc = Nokogiri::HTML(body)
  element = doc.xpath('//td[@submissionid="' + submission_id + '"]')[0]
  element["waiting"] == "true"
end