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 +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
|