at_coder_friends 0.3.3 → 0.4.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 +5 -5
- data/.rubocop.yml +4 -0
- data/.travis.yml +15 -2
- data/Gemfile.lock +15 -15
- data/README.md +60 -8
- data/at_coder_friends.gemspec +4 -4
- data/config/default.yml +88 -0
- data/docs/CONFIGURATION.md +239 -0
- data/lib/at_coder_friends/cli.rb +8 -4
- data/lib/at_coder_friends/config_loader.rb +34 -4
- data/lib/at_coder_friends/cxx_generator.rb +0 -4
- data/lib/at_coder_friends/format_parser.rb +2 -0
- data/lib/at_coder_friends/judge_test_runner.rb +2 -2
- data/lib/at_coder_friends/sample_test_runner.rb +2 -2
- data/lib/at_coder_friends/scraping_agent.rb +72 -10
- data/lib/at_coder_friends/test_runner.rb +45 -27
- data/lib/at_coder_friends/verifier.rb +3 -0
- data/lib/at_coder_friends/version.rb +1 -1
- metadata +16 -14
- data/config/.at_coder_friends.yml.sample +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: f97a6bf516dc7443c791b4e2ace991b34eaa47d5
|
|
4
|
+
data.tar.gz: d48834719bdceceb66cd4f1476c54e7b1c5602af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b4ef816ece17840560b7b9bd39ac4ef56ae346fd859a3b1d737dd9a759faecf77a80244fdd56c97a7aa4542f3bdb65e4346f10239c1cd63e7163038cebc95271
|
|
7
|
+
data.tar.gz: 044e53c76ac9789c2a049a3476141e0d81d103b0d66599bb18e13c0c0b66ec64c65b7fb6062e7ec761d6ba0c536f00d234aa060514eb833e69fc6b922692401e
|
data/.rubocop.yml
CHANGED
|
@@ -17,6 +17,7 @@ Metrics/BlockLength:
|
|
|
17
17
|
- 'Rakefile'
|
|
18
18
|
- '**/*.rake'
|
|
19
19
|
- 'spec/**/*.rb'
|
|
20
|
+
- '**/*.gemspec'
|
|
20
21
|
|
|
21
22
|
Metrics/MethodLength:
|
|
22
23
|
Exclude:
|
|
@@ -25,3 +26,6 @@ Metrics/MethodLength:
|
|
|
25
26
|
Metrics/ModuleLength:
|
|
26
27
|
Exclude:
|
|
27
28
|
- 'spec/**/*.rb'
|
|
29
|
+
|
|
30
|
+
Naming/UncommunicativeMethodParamName:
|
|
31
|
+
MinNameLength: 1
|
data/.travis.yml
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
sudo: false
|
|
2
2
|
language: ruby
|
|
3
3
|
rvm:
|
|
4
|
-
- 2.3.
|
|
5
|
-
|
|
4
|
+
- 2.3.8
|
|
5
|
+
env:
|
|
6
|
+
global:
|
|
7
|
+
- CC_TEST_REPORTER_ID=cb942bcc168feb78c43c506364d5344c5ec9a46a0b68dc66acb581e77c981ff1
|
|
8
|
+
- COVERAGE=true
|
|
9
|
+
before_install:
|
|
10
|
+
- gem install bundler -v '2.0.2'
|
|
11
|
+
before_script:
|
|
12
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
|
13
|
+
- chmod +x ./cc-test-reporter
|
|
14
|
+
- ./cc-test-reporter before-build
|
|
15
|
+
script:
|
|
16
|
+
- bundle exec rake spec
|
|
17
|
+
after_script:
|
|
18
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/Gemfile.lock
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
at_coder_friends (0.
|
|
4
|
+
at_coder_friends (0.4.0)
|
|
5
5
|
launchy (~> 2.4.3)
|
|
6
6
|
mechanize (~> 2.0)
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
addressable (2.
|
|
12
|
-
public_suffix (>= 2.0.2, <
|
|
11
|
+
addressable (2.7.0)
|
|
12
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
13
13
|
connection_pool (2.2.2)
|
|
14
14
|
crack (0.4.3)
|
|
15
15
|
safe_yaml (~> 1.0.0)
|
|
16
16
|
diff-lcs (1.3)
|
|
17
|
-
docile (1.3.
|
|
17
|
+
docile (1.3.2)
|
|
18
18
|
domain_name (0.5.20190701)
|
|
19
19
|
unf (>= 0.0.5, < 1.0.0)
|
|
20
|
-
hashdiff (0.
|
|
20
|
+
hashdiff (1.0.0)
|
|
21
21
|
http-cookie (1.0.3)
|
|
22
22
|
domain_name (~> 0.5)
|
|
23
|
-
json (2.
|
|
23
|
+
json (2.2.0)
|
|
24
24
|
launchy (2.4.3)
|
|
25
25
|
addressable (~> 2.3)
|
|
26
26
|
mechanize (2.7.6)
|
|
@@ -42,8 +42,8 @@ GEM
|
|
|
42
42
|
nokogiri (1.10.4)
|
|
43
43
|
mini_portile2 (~> 2.4.0)
|
|
44
44
|
ntlm-http (0.1.1)
|
|
45
|
-
public_suffix (
|
|
46
|
-
rake (
|
|
45
|
+
public_suffix (4.0.1)
|
|
46
|
+
rake (12.3.3)
|
|
47
47
|
rspec (3.8.0)
|
|
48
48
|
rspec-core (~> 3.8.0)
|
|
49
49
|
rspec-expectations (~> 3.8.0)
|
|
@@ -57,8 +57,8 @@ GEM
|
|
|
57
57
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
58
58
|
rspec-support (~> 3.8.0)
|
|
59
59
|
rspec-support (3.8.0)
|
|
60
|
-
safe_yaml (1.0.
|
|
61
|
-
simplecov (0.
|
|
60
|
+
safe_yaml (1.0.5)
|
|
61
|
+
simplecov (0.17.0)
|
|
62
62
|
docile (~> 1.1)
|
|
63
63
|
json (>= 1.8, < 3)
|
|
64
64
|
simplecov-html (~> 0.10.0)
|
|
@@ -66,10 +66,10 @@ GEM
|
|
|
66
66
|
unf (0.1.4)
|
|
67
67
|
unf_ext
|
|
68
68
|
unf_ext (0.0.7.6)
|
|
69
|
-
webmock (3.
|
|
69
|
+
webmock (3.7.3)
|
|
70
70
|
addressable (>= 2.3.6)
|
|
71
71
|
crack (>= 0.3.2)
|
|
72
|
-
hashdiff
|
|
72
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
73
73
|
webrobots (0.1.2)
|
|
74
74
|
|
|
75
75
|
PLATFORMS
|
|
@@ -78,11 +78,11 @@ PLATFORMS
|
|
|
78
78
|
|
|
79
79
|
DEPENDENCIES
|
|
80
80
|
at_coder_friends!
|
|
81
|
-
bundler (~>
|
|
82
|
-
rake (~>
|
|
81
|
+
bundler (~> 2.0)
|
|
82
|
+
rake (~> 12.3)
|
|
83
83
|
rspec (~> 3.0)
|
|
84
84
|
simplecov (~> 0.10)
|
|
85
85
|
webmock (~> 3.0)
|
|
86
86
|
|
|
87
87
|
BUNDLED WITH
|
|
88
|
-
|
|
88
|
+
2.0.2
|
data/README.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/at_coder_friends)
|
|
2
|
+
[](https://travis-ci.org/nejiko96/at_coder_friends)
|
|
3
|
+
[](https://codeclimate.com/github/nejiko96/at_coder_friends/maintainability)
|
|
4
|
+
[](https://codeclimate.com/github/nejiko96/at_coder_friends/test_coverage)
|
|
5
|
+
|
|
1
6
|
# AtCoderFriends
|
|
2
7
|
|
|
3
8
|
## Description
|
|
@@ -39,6 +44,8 @@ user: <user>
|
|
|
39
44
|
password: <password>
|
|
40
45
|
```
|
|
41
46
|
|
|
47
|
+
See [CONFIGURATION.md](docs/CONFIGURATION.md) for details.
|
|
48
|
+
|
|
42
49
|
## Usage
|
|
43
50
|
|
|
44
51
|
### Setup
|
|
@@ -49,7 +56,7 @@ at_coder_friends setup /path/to/contest
|
|
|
49
56
|
|
|
50
57
|
Creates contest folder, and generates example data and source skeletons into the folder.
|
|
51
58
|
|
|
52
|
-
### Open
|
|
59
|
+
### Open contest page
|
|
53
60
|
|
|
54
61
|
```
|
|
55
62
|
at_coder_friends open-contest /path/to/contest/source_file
|
|
@@ -75,26 +82,71 @@ at_coder_friends test-all /path/to/contest/source_file
|
|
|
75
82
|
at_coder_friends submit /path/to/contest/source_file
|
|
76
83
|
```
|
|
77
84
|
|
|
78
|
-
### Naming
|
|
85
|
+
### Naming convention
|
|
79
86
|
|
|
80
|
-
- Contest folder name will be used in the contest site URL.
|
|
87
|
+
- Contest folder name will be used in the contest site URL.
|
|
81
88
|
For example, if ```arc001``` folder is specified, AtCoderFriends will use ```https://atcoder.jp/contests/arc001/```.
|
|
82
|
-
- Source file should be named ```[problem ID].[language specific extension]```(e.g. ```A.rb```),
|
|
89
|
+
- Source file should be named ```[problem ID].[language specific extension]```(e.g. ```A.rb```),
|
|
83
90
|
in order to let AtCoderFriends find test cases or fill the submission form.
|
|
84
|
-
- Suffixes (start with underscore) may be added to the file name (e.g. ```A_v2.rb```),
|
|
91
|
+
- Suffixes (start with underscore) may be added to the file name (e.g. ```A_v2.rb```),
|
|
85
92
|
so that you can try multiple codes for one problem.
|
|
86
93
|
|
|
87
94
|
### Notes
|
|
88
95
|
|
|
89
96
|
- Compilation is not supported.
|
|
90
|
-
- Source generator
|
|
97
|
+
- Source generator supports only ruby and C++.
|
|
91
98
|
|
|
92
|
-
## For Sublime Text
|
|
99
|
+
## For Sublime Text user
|
|
93
100
|
|
|
94
101
|
It is convenient to use AtCoderFriends from Sublime Text plugin.
|
|
95
102
|
|
|
96
103
|
- [sublime_at_coder_friends](https://github.com/nejiko96/sublime_at_coder_friends)
|
|
97
104
|
|
|
105
|
+
## For Visual Studio Code user
|
|
106
|
+
|
|
107
|
+
- Run **Configure Tasks** from the global Terminal menu.
|
|
108
|
+
- Select the **Create tasks.json file from template** entry.
|
|
109
|
+
- Select **Others** from the list.
|
|
110
|
+
- Add following tasks to ```tasks.json```.
|
|
111
|
+
|
|
112
|
+
```JSON
|
|
113
|
+
{
|
|
114
|
+
"version": "2.0.0",
|
|
115
|
+
"tasks": [
|
|
116
|
+
{
|
|
117
|
+
"label": "af test-one",
|
|
118
|
+
"type": "shell",
|
|
119
|
+
"command": "at_coder_friends",
|
|
120
|
+
"args": [
|
|
121
|
+
"test-one",
|
|
122
|
+
"${file}"
|
|
123
|
+
],
|
|
124
|
+
"group": "none",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"label": "af test-all",
|
|
128
|
+
"type": "shell",
|
|
129
|
+
"command": "at_coder_friends",
|
|
130
|
+
"args": [
|
|
131
|
+
"test-all",
|
|
132
|
+
"${file}"
|
|
133
|
+
],
|
|
134
|
+
"group": "none"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"label": "af submit",
|
|
138
|
+
"type": "shell",
|
|
139
|
+
"command": "at_coder_friends",
|
|
140
|
+
"args": [
|
|
141
|
+
"submit",
|
|
142
|
+
"${file}"
|
|
143
|
+
],
|
|
144
|
+
"group": "none",
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
98
150
|
## Development
|
|
99
151
|
|
|
100
152
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -102,7 +154,7 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
|
102
154
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
103
155
|
|
|
104
156
|
<!--
|
|
105
|
-
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
157
|
+
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
106
158
|
-->
|
|
107
159
|
|
|
108
160
|
## Contributing
|
data/at_coder_friends.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
lib = File.expand_path('
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'at_coder_friends/version'
|
|
6
6
|
|
|
@@ -30,11 +30,11 @@ Gem::Specification.new do |spec|
|
|
|
30
30
|
|
|
31
31
|
spec.required_ruby_version = '>= 2.3.0'
|
|
32
32
|
|
|
33
|
-
spec.add_dependency 'mechanize', '~> 2.0'
|
|
34
33
|
spec.add_dependency 'launchy', '~> 2.4.3'
|
|
34
|
+
spec.add_dependency 'mechanize', '~> 2.0'
|
|
35
35
|
|
|
36
|
-
spec.add_development_dependency 'bundler', '~>
|
|
37
|
-
spec.add_development_dependency 'rake', '~>
|
|
36
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
37
|
+
spec.add_development_dependency 'rake', '~> 12.3'
|
|
38
38
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
39
39
|
spec.add_development_dependency 'simplecov', '~> 0.10'
|
|
40
40
|
spec.add_development_dependency 'webmock', '~> 3.0'
|
data/config/default.yml
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
user: ~
|
|
2
|
+
password: ~
|
|
3
|
+
ext_settings:
|
|
4
|
+
'awk':
|
|
5
|
+
submit_lang: '3506' # Awk (mawk)
|
|
6
|
+
'bf':
|
|
7
|
+
submit_lang: '3507' # Brainfuck
|
|
8
|
+
'c':
|
|
9
|
+
submit_lang: '3002' # C (GCC)
|
|
10
|
+
test_cmd:
|
|
11
|
+
default: '"{dir}/{base}"'
|
|
12
|
+
windows: '"{dir}/{base}.exe"'
|
|
13
|
+
'cbl':
|
|
14
|
+
submit_lang: '3526' # COBOL - Free
|
|
15
|
+
'clj':
|
|
16
|
+
submit_lang: '3007' # Clojure
|
|
17
|
+
'cr':
|
|
18
|
+
submit_lang: '3511' # Crystal
|
|
19
|
+
'cs':
|
|
20
|
+
submit_lang: '3006' # C# (Mono)
|
|
21
|
+
test_cmd:
|
|
22
|
+
default: 'mono "{dir}/{base}.exe"'
|
|
23
|
+
windows: '"{dir}/{base}.exe"'
|
|
24
|
+
'cxx':
|
|
25
|
+
submit_lang: '3003' # C++14 (GCC)
|
|
26
|
+
test_cmd:
|
|
27
|
+
default: '"{dir}/{base}"'
|
|
28
|
+
windows: '"{dir}/{base}.exe"'
|
|
29
|
+
'd':
|
|
30
|
+
submit_lang: '3009' # D (DMD64)
|
|
31
|
+
'f90':
|
|
32
|
+
submit_lang: '3012' # Fortran (gfortran)
|
|
33
|
+
'fs':
|
|
34
|
+
submit_lang: '3512' # F# (Mono)
|
|
35
|
+
'go':
|
|
36
|
+
submit_lang: '3013' # Go
|
|
37
|
+
'hs':
|
|
38
|
+
submit_lang: '3014' # Haskell (GHC)
|
|
39
|
+
'java':
|
|
40
|
+
submit_lang: '3016' # Java8 (OpenJDK)
|
|
41
|
+
test_cmd:
|
|
42
|
+
default: 'java -cp "{dir}" Main'
|
|
43
|
+
'jl':
|
|
44
|
+
submit_lang: '3518' # Julia
|
|
45
|
+
'js':
|
|
46
|
+
submit_lang: '3017' # JavaScript (node.js)
|
|
47
|
+
'kt':
|
|
48
|
+
submit_lang: '3523' # Kotlin
|
|
49
|
+
'lisp':
|
|
50
|
+
submit_lang: '3008' # Common Lisp
|
|
51
|
+
'lua':
|
|
52
|
+
submit_lang: '3515' # LuaJIT
|
|
53
|
+
'm':
|
|
54
|
+
submit_lang: '3519' # Octave
|
|
55
|
+
'ml':
|
|
56
|
+
submit_lang: '3018' # OCaml
|
|
57
|
+
'nim':
|
|
58
|
+
submit_lang: '3520' # Nim
|
|
59
|
+
'pas':
|
|
60
|
+
submit_lang: '3019' # Pascal (FPC)
|
|
61
|
+
'php':
|
|
62
|
+
submit_lang: '3524' # PHP7
|
|
63
|
+
'pl':
|
|
64
|
+
submit_lang: '3020' # Perl
|
|
65
|
+
'py':
|
|
66
|
+
submit_lang: '3023' # Python3
|
|
67
|
+
'rb':
|
|
68
|
+
submit_lang: '3024' # Ruby
|
|
69
|
+
test_cmd:
|
|
70
|
+
default: 'ruby "{dir}/{base}.rb"'
|
|
71
|
+
'rs':
|
|
72
|
+
submit_lang: '3504' # Rust
|
|
73
|
+
'scala':
|
|
74
|
+
submit_lang: '3025' # Scala
|
|
75
|
+
'scm':
|
|
76
|
+
submit_lang: '3026' # Scheme (Gauche)
|
|
77
|
+
'sed':
|
|
78
|
+
submit_lang: '3505' # Sed (GNU sed)
|
|
79
|
+
'sh':
|
|
80
|
+
submit_lang: '3001' # Bash (GNU bash)
|
|
81
|
+
'swift':
|
|
82
|
+
submit_lang: '3503' # Swift
|
|
83
|
+
'ts':
|
|
84
|
+
submit_lang: '3521' # TypeScript
|
|
85
|
+
'txt':
|
|
86
|
+
submit_lang: '3027' # Text (cat)
|
|
87
|
+
'vb':
|
|
88
|
+
submit_lang: '3028' # Visual Basic (Mono)
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Configuration details
|
|
2
|
+
|
|
3
|
+
## Configuration file
|
|
4
|
+
|
|
5
|
+
AtCoderFriends の動作に関する設定は
|
|
6
|
+
設定ファイル 「.at_coder_friends.yml」 に記述します。
|
|
7
|
+
このファイルは作業ディレクトリ(またはその上位ディレクトリ)に配置します。
|
|
8
|
+
|
|
9
|
+
## Default settings
|
|
10
|
+
|
|
11
|
+
デフォルトは以下のような設定になっています。
|
|
12
|
+
「.at_coder_friends.yml」が見つかると、その内容がデフォルト設定にマージされるので、
|
|
13
|
+
新しい設定項目の追加や、既存の設定項目の上書きが可能です。
|
|
14
|
+
|
|
15
|
+
```YAML
|
|
16
|
+
user: ~
|
|
17
|
+
password: ~
|
|
18
|
+
ext_settings:
|
|
19
|
+
'awk':
|
|
20
|
+
submit_lang: '3506' # Awk (mawk)
|
|
21
|
+
'bf':
|
|
22
|
+
submit_lang: '3507' # Brainfuck
|
|
23
|
+
'c':
|
|
24
|
+
submit_lang: '3002' # C (GCC)
|
|
25
|
+
test_cmd:
|
|
26
|
+
default: '"{dir}/{base}"'
|
|
27
|
+
windows: '"{dir}/{base}.exe"'
|
|
28
|
+
'cbl':
|
|
29
|
+
submit_lang: '3526' # COBOL - Free
|
|
30
|
+
'clj':
|
|
31
|
+
submit_lang: '3007' # Clojure
|
|
32
|
+
'cr':
|
|
33
|
+
submit_lang: '3511' # Crystal
|
|
34
|
+
'cs':
|
|
35
|
+
submit_lang: '3006' # C# (Mono)
|
|
36
|
+
test_cmd:
|
|
37
|
+
default: 'mono "{dir}/{base}.exe"'
|
|
38
|
+
windows: '"{dir}/{base}.exe"'
|
|
39
|
+
'cxx':
|
|
40
|
+
submit_lang: '3003' # C++14 (GCC)
|
|
41
|
+
test_cmd:
|
|
42
|
+
default: '"{dir}/{base}"'
|
|
43
|
+
windows: '"{dir}/{base}.exe"'
|
|
44
|
+
'd':
|
|
45
|
+
submit_lang: '3009' # D (DMD64)
|
|
46
|
+
'f90':
|
|
47
|
+
submit_lang: '3012' # Fortran (gfortran)
|
|
48
|
+
'fs':
|
|
49
|
+
submit_lang: '3512' # F# (Mono)
|
|
50
|
+
'go':
|
|
51
|
+
submit_lang: '3013' # Go
|
|
52
|
+
'hs':
|
|
53
|
+
submit_lang: '3014' # Haskell (GHC)
|
|
54
|
+
'java':
|
|
55
|
+
submit_lang: '3016' # Java8 (OpenJDK)
|
|
56
|
+
test_cmd:
|
|
57
|
+
default: 'java -cp "{dir}" Main'
|
|
58
|
+
'jl':
|
|
59
|
+
submit_lang: '3518' # Julia
|
|
60
|
+
'js':
|
|
61
|
+
submit_lang: '3017' # JavaScript (node.js)
|
|
62
|
+
'kt':
|
|
63
|
+
submit_lang: '3523' # Kotlin
|
|
64
|
+
'lisp':
|
|
65
|
+
submit_lang: '3008' # Common Lisp
|
|
66
|
+
'lua':
|
|
67
|
+
submit_lang: '3515' # LuaJIT
|
|
68
|
+
'm':
|
|
69
|
+
submit_lang: '3519' # Octave
|
|
70
|
+
'ml':
|
|
71
|
+
submit_lang: '3018' # OCaml
|
|
72
|
+
'nim':
|
|
73
|
+
submit_lang: '3520' # Nim
|
|
74
|
+
'pas':
|
|
75
|
+
submit_lang: '3019' # Pascal (FPC)
|
|
76
|
+
'php':
|
|
77
|
+
submit_lang: '3524' # PHP7
|
|
78
|
+
'pl':
|
|
79
|
+
submit_lang: '3020' # Perl
|
|
80
|
+
'py':
|
|
81
|
+
submit_lang: '3023' # Python3
|
|
82
|
+
'rb':
|
|
83
|
+
submit_lang: '3024' # Ruby
|
|
84
|
+
test_cmd:
|
|
85
|
+
default: 'ruby "{dir}/{base}.rb"'
|
|
86
|
+
'rs':
|
|
87
|
+
submit_lang: '3504' # Rust
|
|
88
|
+
'scala':
|
|
89
|
+
submit_lang: '3025' # Scala
|
|
90
|
+
'scm':
|
|
91
|
+
submit_lang: '3026' # Scheme (Gauche)
|
|
92
|
+
'sed':
|
|
93
|
+
submit_lang: '3505' # Sed (GNU sed)
|
|
94
|
+
'sh':
|
|
95
|
+
submit_lang: '3001' # Bash (GNU bash)
|
|
96
|
+
'swift':
|
|
97
|
+
submit_lang: '3503' # Swift
|
|
98
|
+
'ts':
|
|
99
|
+
submit_lang: '3521' # TypeScript
|
|
100
|
+
'txt':
|
|
101
|
+
submit_lang: '3027' # Text (cat)
|
|
102
|
+
'vb':
|
|
103
|
+
submit_lang: '3028' # Visual Basic (Mono)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Configuration options
|
|
107
|
+
|
|
108
|
+
- user
|
|
109
|
+
AtCoderのログインユーザーID
|
|
110
|
+
|
|
111
|
+
- password
|
|
112
|
+
AtCoderのログインパスワード
|
|
113
|
+
|
|
114
|
+
- ext_settings
|
|
115
|
+
拡張子ごとの設定
|
|
116
|
+
|
|
117
|
+
- _'ext'_
|
|
118
|
+
対象となる拡張子
|
|
119
|
+
|
|
120
|
+
- submit_lang
|
|
121
|
+
提出言語の言語ID
|
|
122
|
+
|
|
123
|
+
- test_cmd
|
|
124
|
+
テストで使用する実行コマンドの設定
|
|
125
|
+
未設定の場合はAtCoderの「コードテスト」ページでテストをします
|
|
126
|
+
|
|
127
|
+
- default
|
|
128
|
+
デフォルトの実行コマンド
|
|
129
|
+
|
|
130
|
+
- wndows
|
|
131
|
+
Windows専用実行コマンド(あれば設定)
|
|
132
|
+
|
|
133
|
+
- macosx
|
|
134
|
+
MacOS専用実行コマンド(あれば設定)
|
|
135
|
+
|
|
136
|
+
- linux
|
|
137
|
+
Linux専用実行コマンド(あれば設定)
|
|
138
|
+
|
|
139
|
+
### Language ID list (2019/09/16)
|
|
140
|
+
|
|
141
|
+
| Language ID | Description |
|
|
142
|
+
|---|---|
|
|
143
|
+
|3003|C++14 (GCC 5.4.1)|
|
|
144
|
+
|3001|Bash (GNU bash v4.3.11)|
|
|
145
|
+
|3002|C (GCC 5.4.1)|
|
|
146
|
+
|3004|C (Clang 3.8.0)|
|
|
147
|
+
|3005|C++14 (Clang 3.8.0)|
|
|
148
|
+
|3006|C# (Mono 4.6.2.0)|
|
|
149
|
+
|3007|Clojure (1.8.0)|
|
|
150
|
+
|3008|Common Lisp (SBCL 1.1.14)|
|
|
151
|
+
|3009|D (DMD64 v2.070.1)|
|
|
152
|
+
|3010|D (LDC 0.17.0)|
|
|
153
|
+
|3011|D (GDC 4.9.4)|
|
|
154
|
+
|3012|Fortran (gfortran v4.8.4)|
|
|
155
|
+
|3013|Go (1.6)|
|
|
156
|
+
|3014|Haskell (GHC 7.10.3)|
|
|
157
|
+
|3015|Java7 (OpenJDK 1.7.0)|
|
|
158
|
+
|3016|Java8 (OpenJDK 1.8.0)|
|
|
159
|
+
|3017|JavaScript (node.js v5.12)|
|
|
160
|
+
|3018|OCaml (4.02.3)|
|
|
161
|
+
|3019|Pascal (FPC 2.6.2)|
|
|
162
|
+
|3020|Perl (v5.18.2)|
|
|
163
|
+
|3021|PHP (5.6.30)|
|
|
164
|
+
|3022|Python2 (2.7.6)|
|
|
165
|
+
|3023|Python3 (3.4.3)|
|
|
166
|
+
|3024|Ruby (2.3.3)|
|
|
167
|
+
|3025|Scala (2.11.7)|
|
|
168
|
+
|3026|Scheme (Gauche 0.9.3.3)|
|
|
169
|
+
|3027|Text (cat)|
|
|
170
|
+
|3028|Visual Basic (Mono 4.0.1)|
|
|
171
|
+
|3029|C++ (GCC 5.4.1)|
|
|
172
|
+
|3030|C++ (Clang 3.8.0)|
|
|
173
|
+
|3501|Objective-C (GCC 5.3.0)|
|
|
174
|
+
|3502|Objective-C (Clang3.8.0)|
|
|
175
|
+
|3503|Swift (swift-2.2-RELEASE)|
|
|
176
|
+
|3504|Rust (1.15.1)|
|
|
177
|
+
|3505|Sed (GNU sed 4.2.2)|
|
|
178
|
+
|3506|Awk (mawk 1.3.3)|
|
|
179
|
+
|3507|Brainfuck (bf 20041219)|
|
|
180
|
+
|3508|Standard ML (MLton 20100608)|
|
|
181
|
+
|3509|PyPy2 (5.6.0)|
|
|
182
|
+
|3510|PyPy3 (2.4.0)|
|
|
183
|
+
|3511|Crystal (0.20.5)|
|
|
184
|
+
|3512|F# (Mono 4.0)|
|
|
185
|
+
|3513|Unlambda (0.1.3)|
|
|
186
|
+
|3514|Lua (5.3.2)|
|
|
187
|
+
|3515|LuaJIT (2.0.4)|
|
|
188
|
+
|3516|MoonScript (0.5.0)|
|
|
189
|
+
|3517|Ceylon (1.2.1)|
|
|
190
|
+
|3518|Julia (0.5.0)|
|
|
191
|
+
|3519|Octave (4.0.2)|
|
|
192
|
+
|3520|Nim (0.13.0)|
|
|
193
|
+
|3521|TypeScript (2.1.6)|
|
|
194
|
+
|3522|Perl6 (rakudo-star 2016.01)|
|
|
195
|
+
|3523|Kotlin (1.0.0)|
|
|
196
|
+
|3524|PHP7 (7.0.15)|
|
|
197
|
+
|3525|COBOL - Fixed (OpenCOBOL 1.1.0)|
|
|
198
|
+
|3526|COBOL - Free (OpenCOBOL 1.1.0)|
|
|
199
|
+
|
|
200
|
+
### Variables available in test_cmd
|
|
201
|
+
|
|
202
|
+
test_cmd の文字列中の以下のパターンは、
|
|
203
|
+
テスト対象のソースファイルの情報に置換された後、実行されます。
|
|
204
|
+
|
|
205
|
+
|パターン|設定値|
|
|
206
|
+
|---|---|
|
|
207
|
+
|{dir}|ソースファイルの置かれているディレクトリ|
|
|
208
|
+
|{base}|ソースファイルの拡張子を除いたファイル名|
|
|
209
|
+
|
|
210
|
+
## Examples of overwriting settings
|
|
211
|
+
|
|
212
|
+
- .pyをローカル環境のPythonでテスト
|
|
213
|
+
```YAML
|
|
214
|
+
ext_settings:
|
|
215
|
+
'py':
|
|
216
|
+
test_cmd:
|
|
217
|
+
default: 'python "{dir}/{base}.py"'
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- .rb を「コードテスト」ページでテスト
|
|
221
|
+
```YAML
|
|
222
|
+
ext_settings:
|
|
223
|
+
'rb':
|
|
224
|
+
test_cmd: ~
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- .pl6(Perl6)の設定を追加
|
|
228
|
+
```YAML
|
|
229
|
+
ext_settings:
|
|
230
|
+
'pl6':
|
|
231
|
+
submit_lang: '3522' # Perl6
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
- .cxxの提出言語をC++14(Clang)に変更
|
|
235
|
+
```YAML
|
|
236
|
+
ext_settings:
|
|
237
|
+
'cxx':
|
|
238
|
+
submit_lang: '3005' # C++14(Clang)
|
|
239
|
+
```
|
data/lib/at_coder_friends/cli.rb
CHANGED
|
@@ -25,6 +25,7 @@ module AtCoderFriends
|
|
|
25
25
|
parse_options!(args)
|
|
26
26
|
handle_exiting_option
|
|
27
27
|
raise ParamError, 'command or path is not specified.' if args.size < 2
|
|
28
|
+
|
|
28
29
|
@config = ConfigLoader.load_config(args[1])
|
|
29
30
|
exec_command(*args)
|
|
30
31
|
STATUS_SUCCESS
|
|
@@ -55,6 +56,7 @@ module AtCoderFriends
|
|
|
55
56
|
|
|
56
57
|
def handle_exiting_option
|
|
57
58
|
return unless EXITING_OPTIONS.any? { |o| @options.key? o }
|
|
59
|
+
|
|
58
60
|
puts AtCoderFriends::VERSION if @options[:version]
|
|
59
61
|
exit STATUS_SUCCESS
|
|
60
62
|
end
|
|
@@ -83,6 +85,7 @@ module AtCoderFriends
|
|
|
83
85
|
def setup(path)
|
|
84
86
|
raise AppError, "#{path} is not empty." \
|
|
85
87
|
if Dir.exist?(path) && !Dir["#{path}/*"].empty?
|
|
88
|
+
|
|
86
89
|
agent = ScrapingAgent.new(contest_name(path), @config)
|
|
87
90
|
parser = FormatParser.new
|
|
88
91
|
rb_gen = RubyGenerator.new
|
|
@@ -98,28 +101,29 @@ module AtCoderFriends
|
|
|
98
101
|
|
|
99
102
|
def test_one(path, id)
|
|
100
103
|
id ||= 1
|
|
101
|
-
SampleTestRunner.new(path).test_one(id)
|
|
104
|
+
SampleTestRunner.new(path, @config).test_one(id)
|
|
102
105
|
end
|
|
103
106
|
|
|
104
107
|
def test_all(path)
|
|
105
|
-
SampleTestRunner.new(path).test_all
|
|
108
|
+
SampleTestRunner.new(path, @config).test_all
|
|
106
109
|
Verifier.new(path).verify
|
|
107
110
|
end
|
|
108
111
|
|
|
109
112
|
def submit(path)
|
|
110
113
|
vf = Verifier.new(path)
|
|
111
114
|
raise AppError, "#{vf.file} has not been tested." unless vf.verified?
|
|
115
|
+
|
|
112
116
|
ScrapingAgent.new(contest_name(path), @config).submit(path)
|
|
113
117
|
vf.unverify
|
|
114
118
|
end
|
|
115
119
|
|
|
116
120
|
def judge_one(path, id)
|
|
117
121
|
id ||= ''
|
|
118
|
-
JudgeTestRunner.new(path).judge_one(id)
|
|
122
|
+
JudgeTestRunner.new(path, @config).judge_one(id)
|
|
119
123
|
end
|
|
120
124
|
|
|
121
125
|
def judge_all(path)
|
|
122
|
-
JudgeTestRunner.new(path).judge_all
|
|
126
|
+
JudgeTestRunner.new(path, @config).judge_all
|
|
123
127
|
end
|
|
124
128
|
|
|
125
129
|
def open_contest(path)
|
|
@@ -7,11 +7,24 @@ module AtCoderFriends
|
|
|
7
7
|
# loads configuration file from the specified directory.
|
|
8
8
|
class ConfigLoader
|
|
9
9
|
DOTFILE = '.at_coder_friends.yml'
|
|
10
|
+
ACF_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
|
|
11
|
+
DEFAULT_FILE = File.join(ACF_HOME, 'config', 'default.yml')
|
|
10
12
|
|
|
11
13
|
class << self
|
|
12
14
|
def load_config(target_dir)
|
|
13
|
-
path =
|
|
14
|
-
load_yaml(path)
|
|
15
|
+
path = config_file_for(target_dir)
|
|
16
|
+
config = load_yaml(path)
|
|
17
|
+
return config if path == DEFAULT_FILE
|
|
18
|
+
|
|
19
|
+
merge_with_default(config)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def config_file_for(target_dir)
|
|
23
|
+
find_project_dotfile(target_dir) || DEFAULT_FILE
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def find_project_dotfile(target_dir)
|
|
27
|
+
find_file_upwards(DOTFILE, target_dir)
|
|
15
28
|
end
|
|
16
29
|
|
|
17
30
|
def find_file_upwards(filename, start_dir)
|
|
@@ -19,8 +32,25 @@ module AtCoderFriends
|
|
|
19
32
|
file = dir + filename
|
|
20
33
|
return file.to_s if file.exist?
|
|
21
34
|
end
|
|
22
|
-
|
|
23
|
-
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def merge_with_default(config)
|
|
38
|
+
merge(default_config, config)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def default_config
|
|
42
|
+
load_yaml(DEFAULT_FILE)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def merge(base_hash, derived_hash)
|
|
46
|
+
res = base_hash.merge(derived_hash) do |_, base_val, derived_val|
|
|
47
|
+
if base_val.is_a?(Hash) && derived_val.is_a?(Hash)
|
|
48
|
+
merge(base_val, derived_val)
|
|
49
|
+
else
|
|
50
|
+
derived_val
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
res
|
|
24
54
|
end
|
|
25
55
|
|
|
26
56
|
def load_yaml(path)
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
module AtCoderFriends
|
|
4
4
|
# generates C++ source code from definition
|
|
5
5
|
class CxxGenerator
|
|
6
|
-
# rubocop:disable Style/FormatStringToken
|
|
7
6
|
TEMPLATE = <<~TEXT
|
|
8
7
|
#include <cstdio>
|
|
9
8
|
|
|
@@ -31,7 +30,6 @@ module AtCoderFriends
|
|
|
31
30
|
return 0;
|
|
32
31
|
}
|
|
33
32
|
TEXT
|
|
34
|
-
# rubocop:enable Style/FormatStringToken
|
|
35
33
|
|
|
36
34
|
SCANF_FMTS = [
|
|
37
35
|
'scanf("%<fmt>s", %<addr>s);',
|
|
@@ -39,9 +37,7 @@ module AtCoderFriends
|
|
|
39
37
|
'REP(i, %<sz1>s) REP(j, %<sz2>s) scanf("%<fmt>s", %<addr>s);'
|
|
40
38
|
].freeze
|
|
41
39
|
|
|
42
|
-
# rubocop:disable Style/FormatStringToken
|
|
43
40
|
FMT_FMTS = { number: '%d', string: '%s', char: '%s' }.freeze
|
|
44
|
-
# rubocop:enable Style/FormatStringToken
|
|
45
41
|
|
|
46
42
|
ADDR_FMTS = {
|
|
47
43
|
single: {
|
|
@@ -85,6 +85,7 @@ module AtCoderFriends
|
|
|
85
85
|
defs = parse_fmt(lines)
|
|
86
86
|
smpx = max_smp(smps)
|
|
87
87
|
return defs unless smpx
|
|
88
|
+
|
|
88
89
|
match_smp!(defs, smpx)
|
|
89
90
|
end
|
|
90
91
|
|
|
@@ -140,6 +141,7 @@ module AtCoderFriends
|
|
|
140
141
|
inpdefs.each_with_index do |inpdef, i|
|
|
141
142
|
break if i > lines.size
|
|
142
143
|
next if inpdef.item != :number
|
|
144
|
+
|
|
143
145
|
inpdef.item = :string if lines[i].split[0] =~ /[^\-0-9]/
|
|
144
146
|
break if %i[varray matrix].include?(inpdef.container)
|
|
145
147
|
end
|
|
@@ -5,6 +5,7 @@ require 'mechanize'
|
|
|
5
5
|
require 'logger'
|
|
6
6
|
require 'English'
|
|
7
7
|
require 'launchy'
|
|
8
|
+
require 'json'
|
|
8
9
|
|
|
9
10
|
module AtCoderFriends
|
|
10
11
|
# scrapes AtCoder contest site and
|
|
@@ -12,15 +13,8 @@ module AtCoderFriends
|
|
|
12
13
|
# - submits sources
|
|
13
14
|
class ScrapingAgent
|
|
14
15
|
include PathUtil
|
|
15
|
-
|
|
16
16
|
BASE_URL = 'https://atcoder.jp/'
|
|
17
17
|
XPATH_SECTION = '//h3[.="%<title>s"]/following-sibling::section'
|
|
18
|
-
LANG_TBL = {
|
|
19
|
-
'cxx' => '3003',
|
|
20
|
-
'cs' => '3006',
|
|
21
|
-
'java' => '3016',
|
|
22
|
-
'rb' => '3024'
|
|
23
|
-
}.freeze
|
|
24
18
|
|
|
25
19
|
attr_reader :contest, :config, :agent
|
|
26
20
|
|
|
@@ -74,7 +68,18 @@ module AtCoderFriends
|
|
|
74
68
|
post_src(q, ext, src)
|
|
75
69
|
end
|
|
76
70
|
|
|
71
|
+
def code_test(path, infile)
|
|
72
|
+
path, _dir, _prg, _base, ext, _q = split_prg_path(path)
|
|
73
|
+
src = File.read(path, encoding: Encoding::UTF_8)
|
|
74
|
+
data = File.read(infile)
|
|
75
|
+
login
|
|
76
|
+
code_test_loop(ext, src, data)
|
|
77
|
+
end
|
|
78
|
+
|
|
77
79
|
def login
|
|
80
|
+
return unless config['user'] && !config['user'].empty?
|
|
81
|
+
return unless config['password'] && !config['password'].empty?
|
|
82
|
+
|
|
78
83
|
page = agent.get(common_url('login'))
|
|
79
84
|
form = page.forms[1]
|
|
80
85
|
form.field_with(name: 'username').value = config['user']
|
|
@@ -132,19 +137,76 @@ module AtCoderFriends
|
|
|
132
137
|
end
|
|
133
138
|
|
|
134
139
|
def post_src(q, ext, src)
|
|
135
|
-
lang_id = LANG_TBL[ext.downcase]
|
|
136
|
-
raise AppError, ".#{ext} is not available." unless lang_id
|
|
137
140
|
page = agent.get(contest_url('submit'))
|
|
138
141
|
form = page.forms[1]
|
|
139
142
|
form.field_with(name: 'data.TaskScreenName') do |sel|
|
|
140
143
|
option = sel.options.find { |op| op.text.start_with?(q) }
|
|
141
144
|
option&.select || (raise AppError, "unknown problem:#{q}.")
|
|
142
145
|
end
|
|
143
|
-
form.add_field!('data.LanguageId', lang_id)
|
|
146
|
+
form.add_field!('data.LanguageId', lang_id(ext))
|
|
144
147
|
form.field_with(name: 'sourceCode').value = src
|
|
145
148
|
form.submit
|
|
146
149
|
end
|
|
147
150
|
|
|
151
|
+
def code_test_loop(ext, src, data)
|
|
152
|
+
page = agent.get(contest_url('custom_test'))
|
|
153
|
+
script = page.search('script').text
|
|
154
|
+
csrf_token = script.scan(/var csrfToken = "(.*)"/)[0][0]
|
|
155
|
+
payload = {
|
|
156
|
+
'data.LanguageId' => lang_id(ext),
|
|
157
|
+
'sourceCode' => src,
|
|
158
|
+
'input' => data,
|
|
159
|
+
'csrf_token' => csrf_token
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
page = agent.post(contest_url('custom_test/submit/json'), payload)
|
|
163
|
+
msg = page.body
|
|
164
|
+
raise AppError, msg unless msg.empty?
|
|
165
|
+
|
|
166
|
+
100.times do
|
|
167
|
+
page = agent.get(contest_url('custom_test/json?reload=true'))
|
|
168
|
+
data = JSON.parse(page.body)
|
|
169
|
+
return nil unless data.is_a?(Hash) && data['Result']
|
|
170
|
+
return data if data.dig('Result', 'Status') == 3
|
|
171
|
+
return data unless data['Interval']
|
|
172
|
+
|
|
173
|
+
sleep 1.0 * data['Interval'] / 1000
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
nil
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def lang_list
|
|
180
|
+
@lang_list ||= begin
|
|
181
|
+
page = agent.get(contest_url('custom_test'))
|
|
182
|
+
form = page.forms[1]
|
|
183
|
+
sel = form.field_with(name: 'data.LanguageId')
|
|
184
|
+
sel && sel
|
|
185
|
+
.options
|
|
186
|
+
.reject { |opt| opt.value.empty? }
|
|
187
|
+
.map do |opt|
|
|
188
|
+
{ v: opt.value, t: opt.text }
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def lang_list_txt
|
|
194
|
+
lang_list
|
|
195
|
+
&.map { |opt| "#{opt[:v]} - #{opt[:t]}" }
|
|
196
|
+
&.join("\n")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def lang_id(ext)
|
|
200
|
+
config.dig('ext_settings', ext, 'submit_lang') || (
|
|
201
|
+
msg = <<~MSG
|
|
202
|
+
submit_lang for .#{ext} is not specified.
|
|
203
|
+
Available languages:
|
|
204
|
+
#{lang_list_txt || '(failed to fetch)'}
|
|
205
|
+
MSG
|
|
206
|
+
raise AppError, msg
|
|
207
|
+
)
|
|
208
|
+
end
|
|
209
|
+
|
|
148
210
|
def open_contest
|
|
149
211
|
Launchy.open(contest_url(''))
|
|
150
212
|
end
|
|
@@ -7,26 +7,29 @@ module AtCoderFriends
|
|
|
7
7
|
class TestRunner
|
|
8
8
|
include PathUtil
|
|
9
9
|
|
|
10
|
-
def initialize(path)
|
|
10
|
+
def initialize(path, config)
|
|
11
|
+
@contest = contest_name(path)
|
|
11
12
|
@path, @dir, @prg, @base, @ext, @q = split_prg_path(path)
|
|
13
|
+
@config = config
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
# rubocop:disable Metrics/MethodLength
|
|
15
17
|
def run_test(id, infile, outfile, expfile)
|
|
16
18
|
return false unless File.exist?(infile) && File.exist?(expfile)
|
|
17
19
|
|
|
18
|
-
puts "==== #{id} ===="
|
|
19
|
-
ec = system("#{edit_cmd} < #{infile} > #{outfile}")
|
|
20
|
+
puts "==== #{id} (#{test_loc}) ===="
|
|
20
21
|
|
|
22
|
+
success = send(test_mtd, infile, outfile)
|
|
21
23
|
input, result, expected =
|
|
22
24
|
[infile, outfile, expfile].map { |file| File.read(file) }
|
|
25
|
+
|
|
23
26
|
puts '-- input --'
|
|
24
27
|
print input
|
|
25
28
|
puts '-- expected --'
|
|
26
29
|
print expected
|
|
27
30
|
puts '-- result --'
|
|
28
31
|
print result
|
|
29
|
-
if !
|
|
32
|
+
if !success
|
|
30
33
|
puts '!!!!! RE !!!!!'
|
|
31
34
|
elsif result != expected
|
|
32
35
|
puts '!!!!! WA !!!!!'
|
|
@@ -37,33 +40,48 @@ module AtCoderFriends
|
|
|
37
40
|
end
|
|
38
41
|
# rubocop:enable Metrics/MethodLength
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
43
|
+
def test_loc
|
|
44
|
+
test_cmd ? 'local' : 'remote'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_mtd
|
|
48
|
+
test_cmd ? :local_test : :remote_test
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def local_test(infile, outfile)
|
|
52
|
+
system("#{test_cmd} < #{infile} > #{outfile}")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def remote_test(infile, outfile)
|
|
56
|
+
agent = ScrapingAgent.new(@contest, @config)
|
|
57
|
+
res = agent.code_test(@path, infile)
|
|
58
|
+
unless res && res['Result']
|
|
59
|
+
File.write(outfile, 'Remote test failed.')
|
|
60
|
+
return false
|
|
61
|
+
end
|
|
62
|
+
puts "Exit code: #{res.dig('Result', 'ExitCode')}"
|
|
63
|
+
puts "Time: #{res.dig('Result', 'TimeConsumption')}ms"
|
|
64
|
+
puts "Memory: #{res.dig('Result', 'MemoryConsumption')}KB"
|
|
65
|
+
if res.dig('Result', 'ExitCode') != 0
|
|
66
|
+
File.write(outfile, res['Stderr'])
|
|
67
|
+
return false
|
|
68
|
+
end
|
|
69
|
+
File.write(outfile, res['Stdout'])
|
|
70
|
+
true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_cmd
|
|
74
|
+
@test_cmd ||= begin
|
|
75
|
+
cmds = @config.dig('ext_settings', @ext, 'test_cmd')
|
|
76
|
+
cmd = cmds && (cmds[which_os.to_s] || cmds['default'])
|
|
77
|
+
return nil unless cmd
|
|
78
|
+
|
|
79
|
+
cmd.gsub('{dir}', @dir).gsub('{base}', @base)
|
|
61
80
|
end
|
|
62
81
|
end
|
|
63
|
-
# rubocop:enable Metrics/MethodLength
|
|
64
82
|
|
|
65
83
|
def which_os
|
|
66
|
-
@
|
|
84
|
+
@which_os ||= begin
|
|
67
85
|
case RbConfig::CONFIG['host_os']
|
|
68
86
|
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
|
69
87
|
:windows
|
|
@@ -15,18 +15,21 @@ module AtCoderFriends
|
|
|
15
15
|
|
|
16
16
|
def verify
|
|
17
17
|
return unless File.exist?(path)
|
|
18
|
+
|
|
18
19
|
FileUtils.makedirs(vdir) unless Dir.exist?(vdir)
|
|
19
20
|
FileUtils.touch(vpath)
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
def unverify
|
|
23
24
|
return unless File.exist?(vpath)
|
|
25
|
+
|
|
24
26
|
File.delete(vpath)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def verified?
|
|
28
30
|
return false unless File.exist?(vpath)
|
|
29
31
|
return false if File.mtime(vpath) < File.mtime(path)
|
|
32
|
+
|
|
30
33
|
true
|
|
31
34
|
end
|
|
32
35
|
end
|
metadata
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: at_coder_friends
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nejiko96
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-09-
|
|
11
|
+
date: 2019-09-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: launchy
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 2.4.3
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 2.4.3
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: mechanize
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 2.
|
|
33
|
+
version: '2.0'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 2.
|
|
40
|
+
version: '2.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: bundler
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '2.0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
54
|
+
version: '2.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rake
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
61
|
+
version: '12.3'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
68
|
+
version: '12.3'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: rspec
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -135,7 +135,8 @@ files:
|
|
|
135
135
|
- at_coder_friends.gemspec
|
|
136
136
|
- bin/console
|
|
137
137
|
- bin/setup
|
|
138
|
-
- config
|
|
138
|
+
- config/default.yml
|
|
139
|
+
- docs/CONFIGURATION.md
|
|
139
140
|
- exe/at_coder_friends
|
|
140
141
|
- lib/at_coder_friends.rb
|
|
141
142
|
- lib/at_coder_friends/cli.rb
|
|
@@ -172,7 +173,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
172
173
|
- !ruby/object:Gem::Version
|
|
173
174
|
version: '0'
|
|
174
175
|
requirements: []
|
|
175
|
-
|
|
176
|
+
rubyforge_project:
|
|
177
|
+
rubygems_version: 2.5.2.3
|
|
176
178
|
signing_key:
|
|
177
179
|
specification_version: 4
|
|
178
180
|
summary: AtCoder support tool
|