atcoder_greedy 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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