atcoder_greedy 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c615d8f8d5392732a0823c7ca87250e7f85fb7eb
4
- data.tar.gz: 0977f4aa39c014bd11a8b7621bcc72b5c183dc23
3
+ metadata.gz: 928824c14d381c4389a42fb8ae036233b3069fe0
4
+ data.tar.gz: 4e3c5477494c91ed4baba3ce6be5bbdd8926b8ce
5
5
  SHA512:
6
- metadata.gz: d0550d84633c1740b05e459c324caec19fc15897d42066979360af402e2cf084a3f0b4d796a12cf1cc2ec98b1bccf1d51dd2c682e12fb4dbb5e31fb90d8af93b
7
- data.tar.gz: 6a92836715a6a1633ce91aea0d99589667e4574035ea7458f9f36ce244692f878bb839b58991b38667c4a1c5cc472a3e803063d1d438f10fa7fd51fef634bece
6
+ metadata.gz: 7f5dca1b5d28dfe2808f37b1126b12c293e9b09246a98910988dbe59c39d5714e6115a7959f93c1e8ae76dbd4f93fc47e404dc6ca249100163979d8c56976e1b
7
+ data.tar.gz: 428b4d2a9e8e72be9d18f2e1679749a917d0248c5b321ec872b3835d791751fc6e042c3efadac89a5fbc88b393d2af96a4ec620a8d9c34e0f2e9b0dc9c9e703d
data/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  - コンテストフォルダ, 問題ファイルの生成
7
7
  - サンプルインプット、アウトプットを用いたテストファイルの生成, テスト実行
8
8
  - ユーザーテンプレート機能
9
+ - 提出機能
9
10
  - ruby, c/c++ に対応
10
11
 
11
12
  ## Installation
@@ -63,6 +64,12 @@ $ atcoder_greedy template OPTION
63
64
  | --set-default FILE_NAME | -s | FILE_NAMEで指定されたテンプレートをその言語のデフォルトに設定します. |
64
65
  | --delete FILE_NAME | -d | FILE_NAMEで指定されたテンプレートを削除します. |
65
66
 
67
+ ### submitコマンド
68
+ 問題の提出を行います. コンテストディレクトリ内で実行してください.提出が成功した場合, 結果画面をブラウザで開きます.
69
+ ```
70
+ $ atcoder_greedy submit [SUBMIT_FILE]
71
+ ```
72
+
66
73
  ## 使用例
67
74
  ### 例1
68
75
  ARC014の場合
@@ -75,6 +82,7 @@ $ atcoder_greedy create http://arc014.contest.atcoder.jp
75
82
 
76
83
  ```
77
84
  .
85
+ ├── .contest_info.yml
78
86
  ├── A.rb
79
87
  ├── B.rb
80
88
  ├── C.rb
@@ -116,6 +124,12 @@ Correct Answer:
116
124
  Test done.
117
125
  ```
118
126
 
127
+ A問題を提出したい場合は,
128
+ ```
129
+ $ atcoder_greedy submit A.rb
130
+ Submit [A.rb] ... Done!
131
+ ```
132
+
119
133
  ### 例2
120
134
  ARC015にて, カレントディレクトリにA問題のインプットファイルのみ生成したい場合
121
135
 
@@ -125,7 +139,6 @@ ARC015にて, カレントディレクトリにA問題のインプットファ
125
139
 
126
140
  ## TODO,実装したい機能
127
141
 
128
- - 提出機能
129
142
  - 言語対応の拡大
130
143
  - gemのテスト作成
131
144
 
@@ -33,4 +33,6 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  spec.add_dependency 'nokogiri'
35
35
  spec.add_dependency 'thor'
36
+ spec.add_dependency 'mechanize'
37
+ spec.add_dependency 'launchy'
36
38
  end
@@ -2,6 +2,8 @@ require 'open-uri'
2
2
  require 'nokogiri'
3
3
  require 'fileutils'
4
4
  require 'yaml'
5
+ require 'mechanize'
6
+ require 'launchy'
5
7
 
6
8
  require "atcoder_greedy/version"
7
9
  require 'atcoder_greedy/command'
@@ -1,10 +1,11 @@
1
- require 'atcoder_greedy'
2
1
  require 'thor'
2
+ require 'atcoder_greedy'
3
3
  require 'atcoder_greedy/command/create'
4
4
  require 'atcoder_greedy/command/destroy'
5
5
  require 'atcoder_greedy/command/test'
6
6
  require 'atcoder_greedy/command/config'
7
7
  require 'atcoder_greedy/command/template'
8
+ require 'atcoder_greedy/command/submit'
8
9
 
9
10
  module AtcoderGreedy
10
11
  class Command < Thor
@@ -1,6 +1,7 @@
1
1
  require 'atcoder_greedy'
2
2
  require 'atcoder_greedy/command'
3
3
  require 'atcoder_greedy/lib/languages'
4
+
4
5
  module AtcoderGreedy
5
6
  class Command < Thor
6
7
  desc 'config', 'change settings'
@@ -9,26 +10,56 @@ module AtcoderGreedy
9
10
  languages = Languages::ALL_LANGUAGES
10
11
  config_path = Dir.home + '/.atcoder_greedy'
11
12
  if Dir.exists?(config_path)
12
- puts "Your current language is [#{AtcoderGreedy.config[:language]}]."
13
+ puts "Your current user_id is #{AtcoderGreedy.config[:user_id]} and current language is [#{AtcoderGreedy.config[:language]}]."
13
14
  else
14
15
  Dir.mkdir(config_path)
15
16
  yml_path = AtcoderGreedy.get_config_path + '/settings.yml'
16
17
  File.open(yml_path, 'w').close
17
18
  end
19
+
20
+ # user setting
21
+ agent = Mechanize.new
22
+ loop do
23
+ print 'Input your user_id: '
24
+ user_id = $stdin.gets.chomp!
25
+ print 'Input your password: '
26
+ password = $stdin.gets.chomp!
27
+ break if user_id.size == 0 || password.size == 0
28
+
29
+ print 'Doing test login ...'
30
+ response = nil
31
+ agent.get('http://abc032.contest.atcoder.jp/login') do |page|
32
+ response = page.form_with(action: '/login') do |f|
33
+ f.field_with(name: 'name').value = user_id
34
+ f.field_with(name: 'password').value = password
35
+ end.submit
36
+ end
37
+
38
+ if response.response['x-imojudge-simpleauth'] == 'Passed'
39
+ puts 'OK!'
40
+ AtcoderGreedy.configure(user_id: user_id)
41
+ AtcoderGreedy.configure(password: password)
42
+ break
43
+ else
44
+ puts 'Failed! Confirm input and try again.'
45
+ end
46
+ end
47
+
48
+ # language setting
18
49
  puts "Choose default language from: #{languages}"
19
50
  print "Input languages: "
20
51
  loop do
21
52
  s = $stdin.gets.chomp!
22
53
  if languages.include?(s)
23
54
  AtcoderGreedy.configure(language: s)
55
+ puts "Update Your default language to [#{AtcoderGreedy.config[:language]}]."
24
56
  break
25
57
  elsif s.size == 0
26
58
  break
27
- elsif puts "Invalid language. please try again:"
59
+ else
60
+ puts "Invalid language. please try again:"
28
61
  end
29
62
  end
30
-
31
- puts "Update Your default language to [#{AtcoderGreedy.config[:language]}]."
32
63
  end
33
64
  end
34
65
  end
@@ -14,18 +14,33 @@ module AtcoderGreedy
14
14
 
15
15
  def create(contest_url)
16
16
  user_options = {
17
- without: {input: false, template: false},
17
+ no: {input: false, template: false},
18
18
  problems: [],
19
19
  directory: options[:select_directory],
20
20
  language: options[:select_language],
21
21
  template: options[:select_template]
22
22
  }
23
23
 
24
- user_options[:without][:input] = true if options[:no_input]
25
- user_options[:without][:template] = true if options[:no_templates]
24
+ user_options[:no][:input] = true if options[:no_input]
25
+ user_options[:no][:template] = true if options[:no_templates]
26
26
  user_options[:problems] = options[:select_problem].split unless options[:select_problem].nil?
27
27
 
28
- Contest.new(contest_url, user_options)
28
+ contest = Contest.new(contest_url, user_options)
29
+ # TODO: contest_infoが存在したときの処理
30
+ File.open("#{contest.dir}/.contest_info.yml", 'w') do |f|
31
+ info = {
32
+ name: contest.name,
33
+ url: contest.url,
34
+ task: {}
35
+ }
36
+ contest.problems.each do |p|
37
+ info[:task][:"#{p[:name]}"] = {
38
+ id: p[:task_id]
39
+ }
40
+ end
41
+
42
+ f.puts info.to_yaml
43
+ end
29
44
  end
30
45
  end
31
46
  end
@@ -0,0 +1,48 @@
1
+ require 'atcoder_greedy'
2
+ require 'atcoder_greedy/command'
3
+ require 'atcoder_greedy/lib/atcoder'
4
+
5
+ def get_language_id(extname)
6
+ case extname
7
+ when '.rb'
8
+ 2010
9
+ when '.cpp'
10
+ 2003
11
+ when '.c'
12
+ 2001
13
+ else
14
+ raise "Unknown extname: #{extname}"
15
+ end
16
+ end
17
+
18
+ module AtcoderGreedy
19
+ class Command < Thor
20
+ desc 'submit [SUBMIT_FILE]', 'submit your solution'
21
+
22
+ # TODO: 提出言語のオプション
23
+ def submit(submit_file)
24
+ print "Submit [#{submit_file}] ... "
25
+ contest_info = YAML.load_file("./.contest_info.yml")
26
+ problem = File.basename(submit_file, '.*')
27
+ if contest_info[:task].include?(:"#{problem}")
28
+ task_id = contest_info[:task][:"#{problem}"][:id]
29
+ else
30
+ raise "Unknown problem: #{problem}"
31
+ end
32
+
33
+ atcoder = Atcoder.new
34
+ atcoder.login(contest_info[:url])
35
+
36
+ submit_url = contest_info[:url] + "/submit?task_id=#{task_id}"
37
+ atcoder.agent.get(submit_url) do |page|
38
+ p = page.form_with(action: "/submit?task_id=#{task_id}") do |f|
39
+ f.field_with(name: 'source_code').value = File.open(submit_file).read
40
+ f.field_with(name: 'task_id').value = task_id
41
+ f.field_with(name: "language_id_#{task_id}").value = get_language_id(File.extname(submit_file))
42
+ end.submit
43
+ puts 'Done!'
44
+ Launchy.open p.uri
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,34 @@
1
+ require 'mechanize'
2
+ require 'atcoder_greedy'
3
+
4
+ class Atcoder
5
+ attr_accessor :agent
6
+ def initialize
7
+ @agent = Mechanize.new
8
+ end
9
+
10
+ def login(url)
11
+ print 'Login ... '
12
+ if AtcoderGreedy.config[:user_id].nil? || AtcoderGreedy.config[:user_id].size == 0
13
+ puts 'You still not set account info.'
14
+ print 'Input User id: '
15
+ user_id = $stdin.gets.chomp!
16
+ print 'Input password: '
17
+ password = $stdin.gets.chomp!
18
+ else
19
+ user_id = AtcoderGreedy.config[:user_id]
20
+ password = AtcoderGreedy.config[:password]
21
+ end
22
+
23
+ response = nil
24
+ @agent.get(url + '/login') do |page|
25
+ response = page.form_with(action: '/login') do |f|
26
+ f.field_with(name: 'name').value = user_id
27
+ f.field_with(name: 'password').value = password
28
+ end.submit
29
+ raise 'Login error' unless response.response['x-imojudge-simpleauth'] == 'Passed'
30
+ end
31
+ puts 'Done!'
32
+ response
33
+ end
34
+ end
@@ -1,9 +1,11 @@
1
1
  require 'uri'
2
+ require 'cgi'
3
+ require 'atcoder_greedy/lib/atcoder'
2
4
  require 'atcoder_greedy'
3
5
  require 'atcoder_greedy/lib/greedy_template'
4
6
 
5
7
  class Contest
6
- attr_accessor :name, :url
8
+ attr_accessor :name, :url, :dir, :problems
7
9
 
8
10
  def initialize(url, **options)
9
11
  if options[:language] != ''
@@ -12,39 +14,51 @@ class Contest
12
14
  @language = AtcoderGreedy.config[:language]
13
15
  end
14
16
  @url = url
17
+
18
+ set_agent
15
19
  set_contest_info(options[:problems])
16
20
  set_directories(options[:directory])
17
21
 
18
- create_inputs unless options[:without][:input]
19
- create_templates(options[:template]) unless options[:without][:template]
22
+ create_inputs unless options[:no][:input]
23
+ create_templates(options[:template]) unless options[:no][:template]
20
24
 
21
25
  puts 'Set up done. Go for it!'
22
26
  end
23
27
 
28
+ def set_agent
29
+ atcoder = Atcoder.new
30
+ atcoder.login(@url)
31
+ @agent = atcoder.agent
32
+ end
33
+
24
34
  def set_contest_info(option_problems)
25
35
  print 'Set contest info ... '
26
36
  @name = URI.parse(@url).host.split('.').first
27
- charset = nil
28
- html = open(@url + '/assignments') do |f|
29
- charset = f.charset
30
- f.read
31
- end
32
- doc = Nokogiri::HTML.parse(html, nil, charset)
37
+ html = @agent.get(@url + '/assignments').content.toutf8
38
+ doc = Nokogiri::HTML.parse(html, nil, 'utf8')
33
39
 
34
- all_problems = nil
40
+ all_problems = []
41
+ task_ids = []
35
42
  doc.xpath('//tbody').each do |tbody|
43
+ tbody.xpath('.//a[starts-with(@href,"/submit")]').each do |a|
44
+ task_ids.push(CGI.parse(URI.parse(a.attributes['href'].value).query)['task_id'].first)
45
+ end
36
46
  all_problems = tbody.xpath('.//a[@class="linkwrapper"]')
37
47
  end
38
48
 
39
49
  @problems = []
40
- until all_problems.empty?
41
- path = all_problems[0].attributes['href'].value
42
- pro = all_problems.select { |l| l.attributes['href'].value == path }
43
- all_problems = all_problems.reject { |l| l.attributes['href'].value == path }
44
- name = pro[0].inner_text
45
- if option_problems.empty? || (!option_problems.empty? && option_problems.include?(name))
46
- @problems.push(name: pro[0].inner_text, path: path)
47
- print "#{name} "
50
+ if all_problems.nil?
51
+ raise 'Failed to get info. Do you participate this contest?'
52
+ else
53
+ until all_problems.empty?
54
+ path = all_problems[0].attributes['href'].value
55
+ pro = all_problems.select { |l| l.attributes['href'].value == path }
56
+ all_problems = all_problems.reject { |l| l.attributes['href'].value == path }
57
+ name = pro[0].inner_text
58
+ if option_problems.empty? || (!option_problems.empty? && option_problems.include?(name))
59
+ @problems.push(name: pro[0].inner_text, path: path, task_id: task_ids.shift)
60
+ print "#{name} "
61
+ end
48
62
  end
49
63
  end
50
64
  puts 'Done!'
@@ -54,12 +68,8 @@ class Contest
54
68
  print 'Create inputs ... '
55
69
  @problems.each do |problem|
56
70
  # take input and output params from url and save to file
57
- charset = nil
58
- html = open(@url + problem[:path]) do |f|
59
- charset = f.charset
60
- f.read
61
- end
62
- doc = Nokogiri::HTML.parse(html, nil, charset)
71
+ html = @agent.get(@url + problem[:path]).content.toutf8
72
+ doc = Nokogiri::HTML.parse(html, nil, 'utf8')
63
73
  in_file = File.new(@dir + "/input_#{problem[:name]}.txt", 'w')
64
74
 
65
75
  params = doc.xpath('//pre')
@@ -48,6 +48,7 @@ class TestCase
48
48
 
49
49
  def validate
50
50
  my_solve = get_solve(@exec_file)
51
+ passed = 0
51
52
  begin
52
53
  if my_solve.compile(@problem_name)
53
54
  puts '-------------------- Compile Done --------------------'
@@ -71,16 +72,17 @@ class TestCase
71
72
  correct = File.open("#{@output[j].path}").read
72
73
  diffs = Diff::LCS.diff(myout, correct)
73
74
  if diffs.size == 0
75
+ passed += 1
74
76
  puts "-------------------- Testcase ##{j} -------------------- PASSED! Time: #{sprintf("%.5f", result)}s"
75
77
  else
76
78
  puts "-------------------- Testcase ##{j} -------------------- FAILED! Time: #{sprintf("%.5f", result)}s"
77
- puts "Your Output:"
79
+ puts 'Your Output:'
78
80
  puts "#{myout}\n"
79
- puts "Correct Answer:"
81
+ puts 'Correct Answer:'
80
82
  puts "#{correct}\n"
81
83
  end
82
84
  end
83
- puts "Test done."
85
+ puts "Test done. #{passed}/#{@input.size} passed."
84
86
  rescue => e
85
87
  puts e
86
88
  end
@@ -1,3 +1,3 @@
1
1
  module AtcoderGreedy
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atcoder_greedy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - keigo-brook
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-22 00:00:00.000000000 Z
11
+ date: 2016-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,34 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mechanize
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: launchy
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  description: By using this plugin, You can create atcoder-contest templates.
84
112
  email:
85
113
  - goog@brookbach.com
@@ -104,8 +132,10 @@ files:
104
132
  - lib/atcoder_greedy/command/config.rb
105
133
  - lib/atcoder_greedy/command/create.rb
106
134
  - lib/atcoder_greedy/command/destroy.rb
135
+ - lib/atcoder_greedy/command/submit.rb
107
136
  - lib/atcoder_greedy/command/template.rb
108
137
  - lib/atcoder_greedy/command/test.rb
138
+ - lib/atcoder_greedy/lib/atcoder.rb
109
139
  - lib/atcoder_greedy/lib/contest.rb
110
140
  - lib/atcoder_greedy/lib/greedy_template.rb
111
141
  - lib/atcoder_greedy/lib/languages.rb