at_coder_friends 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 5c01f28420d768fccb30960702213d768caeaefd54cb9686cb0bafb3591ba44d
4
- data.tar.gz: 35acd1fb67232149a831394b4afa34f5eb1ade9e2ea3658d03d0ec191566975b
2
+ SHA1:
3
+ metadata.gz: f97a6bf516dc7443c791b4e2ace991b34eaa47d5
4
+ data.tar.gz: d48834719bdceceb66cd4f1476c54e7b1c5602af
5
5
  SHA512:
6
- metadata.gz: 6015841608385002fea3d1ff31f738f92719ce7fca2d9331e68c44aef8605ba31047194a6e4a53229062110dd2cd55067932baa0c1e44e2628041e5bc72468e4
7
- data.tar.gz: 8a96a65f43b823666914b86eeba623bf0ae15074406c1ad432d55163c9e8b5d88625e7d08046a1db5d8b0698738bb0fcb5c9b7060a9b5a7232202242f2774ea1
6
+ metadata.gz: b4ef816ece17840560b7b9bd39ac4ef56ae346fd859a3b1d737dd9a759faecf77a80244fdd56c97a7aa4542f3bdb65e4346f10239c1cd63e7163038cebc95271
7
+ data.tar.gz: 044e53c76ac9789c2a049a3476141e0d81d103b0d66599bb18e13c0c0b66ec64c65b7fb6062e7ec761d6ba0c536f00d234aa060514eb833e69fc6b922692401e
@@ -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
@@ -1,5 +1,18 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3.1
5
- before_install: gem install bundler -v 1.16.1
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
@@ -1,26 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- at_coder_friends (0.3.3)
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.6.0)
12
- public_suffix (>= 2.0.2, < 4.0)
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.1)
17
+ docile (1.3.2)
18
18
  domain_name (0.5.20190701)
19
19
  unf (>= 0.0.5, < 1.0.0)
20
- hashdiff (0.3.8)
20
+ hashdiff (1.0.0)
21
21
  http-cookie (1.0.3)
22
22
  domain_name (~> 0.5)
23
- json (2.1.0)
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 (3.0.3)
46
- rake (10.5.0)
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.4)
61
- simplecov (0.16.1)
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.5.1)
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 (~> 1.16)
82
- rake (~> 10.0)
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
- 1.17.3
88
+ 2.0.2
data/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ [![Gem Version](https://badge.fury.io/rb/at_coder_friends.svg)](https://badge.fury.io/rb/at_coder_friends)
2
+ [![Build Status](https://travis-ci.org/nejiko96/at_coder_friends.svg?branch=master)](https://travis-ci.org/nejiko96/at_coder_friends)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/dcd1ce08d11703be2f00/maintainability)](https://codeclimate.com/github/nejiko96/at_coder_friends/maintainability)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/dcd1ce08d11703be2f00/test_coverage)](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 Contest Page
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 Convention
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 and test runner supports only ruby and C++.
97
+ - Source generator supports only ruby and C++.
91
98
 
92
- ## For Sublime Text User
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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
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', '~> 1.16'
37
- spec.add_development_dependency 'rake', '~> 10.0'
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'
@@ -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
+ ```
@@ -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 = find_file_upwards(DOTFILE, target_dir)
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
- raise ConfigNotFoundError,
23
- "Configuration file not found: #{start_dir}"
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,8 +5,8 @@ module AtCoderFriends
5
5
  class JudgeTestRunner < TestRunner
6
6
  include PathUtil
7
7
 
8
- def initialize(path)
9
- super(path)
8
+ def initialize(path, config)
9
+ super(path, config)
10
10
  @cases_dir = cases_dir(@dir)
11
11
  @smp_dir = smp_dir(@dir)
12
12
  end
@@ -5,8 +5,8 @@ module AtCoderFriends
5
5
  class SampleTestRunner < TestRunner
6
6
  include PathUtil
7
7
 
8
- def initialize(path)
9
- super(path)
8
+ def initialize(path, config)
9
+ super(path, config)
10
10
  @smp_dir = smp_dir(@dir)
11
11
  end
12
12
 
@@ -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 !ec
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
- # rubocop:disable Metrics/MethodLength
41
- def edit_cmd
42
- case @ext
43
- when 'java'
44
- "java -cp #{@dir} Main"
45
- when 'rb'
46
- "ruby #{@dir}/#{@base}.rb"
47
- when 'cs'
48
- case which_os
49
- when :windows
50
- "#{@dir}/#{@base}.exe"
51
- else
52
- "mono #{@dir}/#{@base}.exe"
53
- end
54
- else # c, cxx
55
- case which_os
56
- when :windows
57
- "#{@dir}/#{@base}.exe"
58
- else
59
- "#{@dir}/#{@base}"
60
- end
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
- @os ||= begin
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AtCoderFriends
4
- VERSION = '0.3.3'
4
+ VERSION = '0.4.0'
5
5
  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.3.3
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-01 00:00:00.000000000 Z
11
+ date: 2019-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: mechanize
14
+ name: launchy
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
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: '2.0'
26
+ version: 2.4.3
27
27
  - !ruby/object:Gem::Dependency
28
- name: launchy
28
+ name: mechanize
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.4.3
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.4.3
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: '1.16'
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: '1.16'
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: '10.0'
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: '10.0'
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/.at_coder_friends.yml.sample
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
- rubygems_version: 3.0.6
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
@@ -1,2 +0,0 @@
1
- user: <user>
2
- password: <password>