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 +4 -4
- data/README.md +14 -1
- data/atcoder_greedy.gemspec +2 -0
- data/lib/atcoder_greedy.rb +2 -0
- data/lib/atcoder_greedy/command.rb +2 -1
- data/lib/atcoder_greedy/command/config.rb +35 -4
- data/lib/atcoder_greedy/command/create.rb +19 -4
- data/lib/atcoder_greedy/command/submit.rb +48 -0
- data/lib/atcoder_greedy/lib/atcoder.rb +34 -0
- data/lib/atcoder_greedy/lib/contest.rb +34 -24
- data/lib/atcoder_greedy/lib/test_case.rb +5 -3
- data/lib/atcoder_greedy/version.rb +1 -1
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 928824c14d381c4389a42fb8ae036233b3069fe0
|
4
|
+
data.tar.gz: 4e3c5477494c91ed4baba3ce6be5bbdd8926b8ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/atcoder_greedy.gemspec
CHANGED
data/lib/atcoder_greedy.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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[:
|
25
|
-
user_options[:
|
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[:
|
19
|
-
create_templates(options[:template]) unless options[:
|
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
|
-
|
28
|
-
|
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 =
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
58
|
-
|
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
|
79
|
+
puts 'Your Output:'
|
78
80
|
puts "#{myout}\n"
|
79
|
-
puts
|
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
|
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
|
+
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-
|
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
|