at_coder_friends 0.3.1 → 0.3.2
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/Gemfile.lock +30 -28
- data/README.md +2 -2
- data/at_coder_friends.gemspec +2 -0
- data/lib/at_coder_friends/format_parser.rb +3 -2
- data/lib/at_coder_friends/scraping_agent.rb +26 -14
- data/lib/at_coder_friends/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aee130f1a99a63ef7d97ca67fa85fcac10345f469fca73eaa448464432053b24
|
|
4
|
+
data.tar.gz: 1492cbe3b1a4a1cc006e6fff72c0f46eeecce71be0bc4d37b925904be8a48b9c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e9381159e0e389c9f8cb63b7bc18b2b775dfc015720a7118568562e22efbfb877a95c6eb531d3c6c4184f69c3bcb135a9796c21cc6e7f7446b8e2fdd71effb51
|
|
7
|
+
data.tar.gz: 275a4ac13b90a3e85cfd6a60eb1efb47230255ecd5d8d79fe1102a96fb3a3ce8bfb9bdbb62429d0232011d5fc5cdf4fb7bd3992be6add45032f7e0a499b10d16
|
data/Gemfile.lock
CHANGED
|
@@ -1,67 +1,69 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
at_coder_friends (0.3.
|
|
4
|
+
at_coder_friends (0.3.2)
|
|
5
5
|
mechanize (~> 2.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
addressable (2.
|
|
10
|
+
addressable (2.6.0)
|
|
11
11
|
public_suffix (>= 2.0.2, < 4.0)
|
|
12
|
+
connection_pool (2.2.2)
|
|
12
13
|
crack (0.4.3)
|
|
13
14
|
safe_yaml (~> 1.0.0)
|
|
14
15
|
diff-lcs (1.3)
|
|
15
|
-
docile (1.1
|
|
16
|
-
domain_name (0.5.
|
|
16
|
+
docile (1.3.1)
|
|
17
|
+
domain_name (0.5.20180417)
|
|
17
18
|
unf (>= 0.0.5, < 1.0.0)
|
|
18
|
-
hashdiff (0.3.
|
|
19
|
+
hashdiff (0.3.8)
|
|
19
20
|
http-cookie (1.0.3)
|
|
20
21
|
domain_name (~> 0.5)
|
|
21
22
|
json (2.1.0)
|
|
22
|
-
mechanize (2.7.
|
|
23
|
+
mechanize (2.7.6)
|
|
23
24
|
domain_name (~> 0.5, >= 0.5.1)
|
|
24
25
|
http-cookie (~> 1.0)
|
|
25
26
|
mime-types (>= 1.17.2)
|
|
26
27
|
net-http-digest_auth (~> 1.1, >= 1.1.1)
|
|
27
|
-
net-http-persistent (
|
|
28
|
+
net-http-persistent (>= 2.5.2)
|
|
28
29
|
nokogiri (~> 1.6)
|
|
29
30
|
ntlm-http (~> 0.1, >= 0.1.1)
|
|
30
31
|
webrobots (>= 0.0.9, < 0.2)
|
|
31
|
-
mime-types (3.
|
|
32
|
+
mime-types (3.2.2)
|
|
32
33
|
mime-types-data (~> 3.2015)
|
|
33
|
-
mime-types-data (3.
|
|
34
|
-
mini_portile2 (2.
|
|
34
|
+
mime-types-data (3.2018.0812)
|
|
35
|
+
mini_portile2 (2.4.0)
|
|
35
36
|
net-http-digest_auth (1.4.1)
|
|
36
|
-
net-http-persistent (
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
net-http-persistent (3.0.0)
|
|
38
|
+
connection_pool (~> 2.2)
|
|
39
|
+
nokogiri (1.10.1)
|
|
40
|
+
mini_portile2 (~> 2.4.0)
|
|
39
41
|
ntlm-http (0.1.1)
|
|
40
|
-
public_suffix (3.0.
|
|
42
|
+
public_suffix (3.0.3)
|
|
41
43
|
rake (10.5.0)
|
|
42
|
-
rspec (3.
|
|
43
|
-
rspec-core (~> 3.
|
|
44
|
-
rspec-expectations (~> 3.
|
|
45
|
-
rspec-mocks (~> 3.
|
|
46
|
-
rspec-core (3.
|
|
47
|
-
rspec-support (~> 3.
|
|
48
|
-
rspec-expectations (3.
|
|
44
|
+
rspec (3.8.0)
|
|
45
|
+
rspec-core (~> 3.8.0)
|
|
46
|
+
rspec-expectations (~> 3.8.0)
|
|
47
|
+
rspec-mocks (~> 3.8.0)
|
|
48
|
+
rspec-core (3.8.0)
|
|
49
|
+
rspec-support (~> 3.8.0)
|
|
50
|
+
rspec-expectations (3.8.2)
|
|
49
51
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
50
|
-
rspec-support (~> 3.
|
|
51
|
-
rspec-mocks (3.
|
|
52
|
+
rspec-support (~> 3.8.0)
|
|
53
|
+
rspec-mocks (3.8.0)
|
|
52
54
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
53
|
-
rspec-support (~> 3.
|
|
54
|
-
rspec-support (3.
|
|
55
|
+
rspec-support (~> 3.8.0)
|
|
56
|
+
rspec-support (3.8.0)
|
|
55
57
|
safe_yaml (1.0.4)
|
|
56
|
-
simplecov (0.
|
|
57
|
-
docile (~> 1.1
|
|
58
|
+
simplecov (0.16.1)
|
|
59
|
+
docile (~> 1.1)
|
|
58
60
|
json (>= 1.8, < 3)
|
|
59
61
|
simplecov-html (~> 0.10.0)
|
|
60
62
|
simplecov-html (0.10.2)
|
|
61
63
|
unf (0.1.4)
|
|
62
64
|
unf_ext
|
|
63
65
|
unf_ext (0.0.7.5)
|
|
64
|
-
webmock (3.
|
|
66
|
+
webmock (3.5.1)
|
|
65
67
|
addressable (>= 2.3.6)
|
|
66
68
|
crack (>= 0.3.2)
|
|
67
69
|
hashdiff
|
data/README.md
CHANGED
|
@@ -16,9 +16,10 @@ AtCoderFriends automates tasks about [AtCoder](https://atcoder.jp/) programming
|
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
|
+
<!--
|
|
19
20
|
See [Development](#Develoment).
|
|
21
|
+
-->
|
|
20
22
|
|
|
21
|
-
<!--
|
|
22
23
|
Add this line to your application's Gemfile:
|
|
23
24
|
|
|
24
25
|
```ruby
|
|
@@ -32,7 +33,6 @@ And then execute:
|
|
|
32
33
|
Or install it yourself as:
|
|
33
34
|
|
|
34
35
|
$ gem install at_coder_friends
|
|
35
|
-
-->
|
|
36
36
|
|
|
37
37
|
## Configuration
|
|
38
38
|
|
data/at_coder_friends.gemspec
CHANGED
|
@@ -28,6 +28,8 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
29
29
|
spec.require_paths = ['lib']
|
|
30
30
|
|
|
31
|
+
spec.required_ruby_version = '>= 2.3.0'
|
|
32
|
+
|
|
31
33
|
spec.add_dependency 'mechanize', '~> 2.0'
|
|
32
34
|
|
|
33
35
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
|
@@ -93,9 +93,10 @@ module AtCoderFriends
|
|
|
93
93
|
.gsub(/[+-]1/, '') # N-1, N+1 -> N
|
|
94
94
|
.gsub(%r{[-/ ]}, ' ') # a-b, a/b -> a b
|
|
95
95
|
.gsub(/\{.*?\}/) { |w| w.delete(' ') } # {1, 1} -> {1,1} shortest match
|
|
96
|
-
.gsub(/[_,'
|
|
96
|
+
.gsub(/[_,'\\(){}]/, '')
|
|
97
97
|
.gsub(/[::…‥]+/, '..')
|
|
98
|
-
.gsub(
|
|
98
|
+
.gsub(/ldots/, '..')
|
|
99
|
+
.gsub(/^[.\s]+$/, '..')
|
|
99
100
|
.split("\n")
|
|
100
101
|
.map(&:strip)
|
|
101
102
|
end
|
|
@@ -27,6 +27,7 @@ module AtCoderFriends
|
|
|
27
27
|
@contest = contest
|
|
28
28
|
@config = config
|
|
29
29
|
@agent = Mechanize.new
|
|
30
|
+
@agent.pre_connect_hooks << proc { sleep 0.1 }
|
|
30
31
|
# @agent.log = Logger.new(STDERR)
|
|
31
32
|
end
|
|
32
33
|
|
|
@@ -38,6 +39,22 @@ module AtCoderFriends
|
|
|
38
39
|
File.join(BASE_URL, 'contests', contest, path)
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
def constraints_pat
|
|
43
|
+
config['constraints_pat'] || '^制約$'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def input_fmt_pat
|
|
47
|
+
config['input_fmt_pat'] || '^入出?力$'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def input_smp_pat
|
|
51
|
+
config['input_smp_pat'] || '^入力例\s*(?<no>[\d0-9]+)$'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def output_smp_pat
|
|
55
|
+
config['output_smp_pat'] || '^出力例\s*(?<no>[\d0-9]+)$'
|
|
56
|
+
end
|
|
57
|
+
|
|
41
58
|
def fetch_all
|
|
42
59
|
puts "***** fetch_all #{@contest} *****"
|
|
43
60
|
login
|
|
@@ -57,29 +74,26 @@ module AtCoderFriends
|
|
|
57
74
|
end
|
|
58
75
|
|
|
59
76
|
def login
|
|
60
|
-
sleep 0.1
|
|
61
77
|
page = agent.get(common_url('login'))
|
|
62
78
|
form = page.forms[1]
|
|
63
79
|
form.field_with(name: 'username').value = config['user']
|
|
64
80
|
form.field_with(name: 'password').value = config['password']
|
|
65
|
-
sleep 0.1
|
|
66
81
|
form.submit
|
|
67
82
|
end
|
|
68
83
|
|
|
69
84
|
def fetch_assignments
|
|
70
85
|
url = contest_url('tasks')
|
|
71
86
|
puts "fetch list from #{url} ..."
|
|
72
|
-
sleep 0.1
|
|
73
87
|
page = agent.get(url)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
page
|
|
89
|
+
.search('//table[1]//td[1]//a')
|
|
90
|
+
.each_with_object({}) do |a, h|
|
|
91
|
+
h[a.text] = a[:href]
|
|
92
|
+
end
|
|
78
93
|
end
|
|
79
94
|
|
|
80
95
|
def fetch_problem(q, url)
|
|
81
96
|
puts "fetch problem from #{url} ..."
|
|
82
|
-
sleep 0.1
|
|
83
97
|
page = agent.get(url)
|
|
84
98
|
Problem.new(q) do |pbm|
|
|
85
99
|
pbm.html = page.body
|
|
@@ -104,14 +118,14 @@ module AtCoderFriends
|
|
|
104
118
|
text = section.content
|
|
105
119
|
code = section.search('pre')[0]&.content || ''
|
|
106
120
|
case title
|
|
107
|
-
when
|
|
121
|
+
when /#{constraints_pat}/
|
|
108
122
|
pbm.desc += text
|
|
109
|
-
when
|
|
123
|
+
when /#{input_fmt_pat}/
|
|
110
124
|
pbm.desc += text
|
|
111
125
|
pbm.fmt = code
|
|
112
|
-
when
|
|
126
|
+
when /#{input_smp_pat}/
|
|
113
127
|
pbm.add_smp($LAST_MATCH_INFO[:no], :in, code)
|
|
114
|
-
when
|
|
128
|
+
when /#{output_smp_pat}/
|
|
115
129
|
pbm.add_smp($LAST_MATCH_INFO[:no], :exp, code)
|
|
116
130
|
end
|
|
117
131
|
end
|
|
@@ -119,7 +133,6 @@ module AtCoderFriends
|
|
|
119
133
|
def post_src(q, ext, src)
|
|
120
134
|
lang_id = LANG_TBL[ext.downcase]
|
|
121
135
|
raise AppError, ".#{ext} is not available." unless lang_id
|
|
122
|
-
sleep 0.1
|
|
123
136
|
page = agent.get(contest_url('submit'))
|
|
124
137
|
form = page.forms[1]
|
|
125
138
|
form.field_with(name: 'data.TaskScreenName') do |sel|
|
|
@@ -128,7 +141,6 @@ module AtCoderFriends
|
|
|
128
141
|
end
|
|
129
142
|
form.add_field!('data.LanguageId', lang_id)
|
|
130
143
|
form.field_with(name: 'sourceCode').value = src
|
|
131
|
-
sleep 0.1
|
|
132
144
|
form.submit
|
|
133
145
|
end
|
|
134
146
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: at_coder_friends
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nejiko96
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2019-01-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: mechanize
|
|
@@ -151,7 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
151
151
|
requirements:
|
|
152
152
|
- - ">="
|
|
153
153
|
- !ruby/object:Gem::Version
|
|
154
|
-
version:
|
|
154
|
+
version: 2.3.0
|
|
155
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
156
|
requirements:
|
|
157
157
|
- - ">="
|