clicoder 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 191b32a24645db71142a867c9d5663ccc529657e
4
+ data.tar.gz: 7a2427b24acb997930e00486f68971e8f4fc3616
5
+ SHA512:
6
+ metadata.gz: 1f4a2a6a5910de3a7148dc0399cefa73d62590b006a4acc09a391ebf67e22975521d6c1e91f85ff144d02c87ac289471cf7cb6e8f7fcfa9ba3e791a36d3d4a74
7
+ data.tar.gz: 7bbd322adfafb27d7c8febffa834aa5f7d5bde772054831b8261e24dc415c19bf47a16b31dc4e56ab91b487ecf790d5719034d83db2fed500a3e498ca2cb06ca
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in clicoder.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Genki Sugimoto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # CLI Coder
2
+
3
+ Command Line Interface for Online Programming Contests.
4
+
5
+ # Why
6
+
7
+ Programming contests are fun.
8
+ However, there are chores which are not fun, like
9
+
10
+ * copy a sample input and run a program against it
11
+ * compare it with a sample answer
12
+ * submit (copy & paste or select a file)
13
+
14
+ This tool automate these chores so that we can enjoy only really fun part of programming contests (which is, thinking and implementing).
15
+
16
+ # Demo Video
17
+
18
+ Here is a demo solving a problem from AOJ (links to youtube):
19
+
20
+ [![CLI Coder demo](http://img.youtube.com/vi/sVH5EIOxDf8/0.jpg)](http://www.youtube.com/watch?v=sVH5EIOxDf8)
21
+
22
+ # Installation
23
+
24
+ $ gem install clicoder
25
+
26
+ # Preparation
27
+
28
+ ## ~/.clicoder.d/config.yml (required)
29
+
30
+ It contains
31
+
32
+ * configurations of template files
33
+ * configurations for various programming contest sites.
34
+
35
+ Example:
36
+
37
+ ```yaml
38
+ ---
39
+ default:
40
+ template: template.cpp # template file. relative to this file
41
+ makefile: Makefile # Makefile used by CLI Coder. relative to this file
42
+ aoj:
43
+ template: aoj_template.cpp # template only used for site 'aoj'
44
+ user_id: Glen_S
45
+ password: PASSWORD
46
+ atcoder:
47
+ user_id: Glen_S
48
+ password: PASSWORD
49
+ ```
50
+
51
+ ## template.cpp etc. (recommended)
52
+
53
+ It is recommended to put your template file under `~/.clicoder.d`.
54
+ It will be copied into working directories as `main.*` each time you start solving new problems.
55
+
56
+ If you don't use templates, make sure you write your solutions in files named `main.*`.
57
+
58
+ ## Makefile (required)
59
+
60
+ It is recommended to put your `Makefile` under `~/.clicoder.d`.
61
+
62
+ CLI Coder uses Makefile to build and execute your program.
63
+
64
+ ## "build" rule
65
+
66
+ It should build your program.
67
+
68
+ Example:
69
+
70
+ build:
71
+ g++ -g main.cpp -o a.out
72
+
73
+ ## "execute" rule
74
+
75
+ It has to run your program with redirection from "in.txt" and redirection to "out.txt".
76
+
77
+ Example:
78
+
79
+ execute:
80
+ ./a.out < in.txt > out.txt
81
+
82
+ # Usage
83
+
84
+ ```sh
85
+ Commands:
86
+ clicoder add_test # Add new test case
87
+ clicoder all # build, execute, and judge
88
+ clicoder browse # Open problem page with the browser
89
+ clicoder build # Build your program using `make build`
90
+ clicoder download # Download description, inputs and outputs
91
+ clicoder execute # Execute your program using `make execute`
92
+ clicoder help [COMMAND] # Describe available commands or one specific command
93
+ clicoder judge # Judge your outputs
94
+ clicoder new <command> # start a new problem
95
+ clicoder submit # Submit your program
96
+ ```
97
+
98
+ ## Sites Available
99
+
100
+ * [AOJ](http://judge.u-aizu.ac.jp/onlinejudge/)
101
+ * [AtCoder](http://atcoder.jp/)
102
+
103
+ ```sh
104
+ clicoder new aoj PROBLEM_NUMBER # Prepare directory to deal with new problem from AOJ
105
+ clicoder new atcoder CONTEST_ID PROBLEM_NUMBER # Prepare directory to deal with new problem from AtCoder
106
+ ```
107
+
108
+ ### AOJ
109
+
110
+ PROBLEM_NUMBER is shown in problem URL like this:
111
+
112
+ <pre>http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=<strong>0001</strong></pre>
113
+
114
+ ### AtCoder
115
+
116
+ CONTEST_ID is shown in contest URL like this:
117
+
118
+ <pre>http://<strong>arc001</strong>.contest.atcoder.jp/</pre>
119
+
120
+ PROBLEM_NUMBER is a number starting from 1, or it can be found in problem URL like this:
121
+
122
+ <pre>http://arc001.contest.atcoder.jp/tasks/arc001_<strong>1</strong></pre>
123
+
124
+ # Tips
125
+
126
+ I recommend you to use this shell function for AOJ:
127
+
128
+ ```sh
129
+ function aoj() {
130
+ clicoder new aoj $1
131
+ dir=$(printf "%04d" $1)
132
+ cd $dir
133
+ }
134
+ ```
135
+
136
+ # Contributing
137
+
138
+ **Please send your pull requests to "develop" branch.**
139
+ Thank you for your contributions.
140
+
141
+ 1. Fork it
142
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
143
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
144
+ 4. Push to the branch (`git push origin my-new-feature`)
145
+ 5. Create new Pull Request
146
+
147
+ ## Add a Site
148
+
149
+ It's easy to add new sites.
150
+
151
+ 1. Implement new site class
152
+ 2. Add it to the factory method (`new_with_config`) in `lib/clicoder/site_base.rb`
153
+ 3. Add new command (`clicoder new new_site ARGS`) in `lib/clicoder/cli.rb`
154
+
155
+ Site classes resides in `lib/clicoder/sites` directory.
156
+ See existing sites for examples.
157
+
158
+ Basically, you need to implement these methods:
159
+
160
+ ### initialize
161
+
162
+ Initialize a site instance (i.e. a problem) and set local configurations (like problem id).
163
+
164
+ ### submit
165
+
166
+ Submit your code.
167
+
168
+ ### open_submission
169
+
170
+ Open submission status page. This will be called automatically after successful submissions.
171
+
172
+ ### login
173
+
174
+ Sometimes you need to login to see problems or to submit your solutions.
175
+ This method has to log in and execute given block under logged-in condition.
176
+
177
+ ### site_name
178
+
179
+ Returns site name.
180
+
181
+ ### problem_url
182
+
183
+ Returns problem url.
184
+
185
+ ### description_xpath
186
+
187
+ Returns xpath which indicates where the problem description is.
188
+ Used to download problem description.
189
+
190
+ ### inputs_xpath
191
+
192
+ Returns xpath which indicates where the sample inputs are.
193
+ Used to download sample inputs.
194
+
195
+ ### outputs_xpath
196
+
197
+ Returns xpath which indicates where the sample outputs are.
198
+ Used to download sample outputs.
199
+
200
+ ### working_directory
201
+
202
+ Returns a directory name it should create with `clicoder new` command.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/clicoder ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'clicoder/cli'
4
+ Clicoder::ArubaCLI.new(ARGV.dup).execute!
data/clicoder.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'clicoder/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "clicoder"
8
+ spec.version = Clicoder::VERSION
9
+ spec.authors = ["Genki Sugimoto"]
10
+ spec.email = ["cfhoyuk.reccos.nelg@gmail.com"]
11
+ spec.description = %q{Make it easy to deal with online programming contests from the command line}
12
+ spec.summary = %q{CLI interface to online programming contests}
13
+ spec.homepage = "https://github.com/Genki-S/clicoder"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "nokogiri"
22
+ spec.add_dependency "thor"
23
+ spec.add_dependency "abstract_method"
24
+ spec.add_dependency "launchy"
25
+ spec.add_dependency "reverse_markdown"
26
+ spec.add_dependency "mechanize"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.3"
29
+ spec.add_development_dependency "rake"
30
+ spec.add_development_dependency "rspec"
31
+ spec.add_development_dependency "webmock"
32
+ spec.add_development_dependency "cucumber"
33
+ spec.add_development_dependency "aruba"
34
+ spec.add_development_dependency "pry"
35
+ end
@@ -0,0 +1,79 @@
1
+ Feature: SampleSite
2
+ In order to make it easy to deal with programming contests
3
+ As a CLI
4
+ I want to provide commands to perform common tasks
5
+
6
+ Scenario: Start a new problem
7
+ When I run `clicoder new sample_site`
8
+ Then the output should contain "created directory working_directory"
9
+
10
+ Scenario: Build a program
11
+ Given in a problem directory
12
+ When I run `clicoder build`
13
+ Then an executable should be generated
14
+
15
+ Scenario: Run a program
16
+ Given in a problem directory
17
+ When I run `clicoder build`
18
+ And I run `clicoder execute`
19
+ Then my answer should be output in my outputs directory
20
+
21
+ Scenario: Judge without outputs
22
+ Given in a problem directory
23
+ When I run `clicoder judge`
24
+ Then the output should contain "Wrong Answer"
25
+
26
+ Scenario: Judge wrong outputs
27
+ Given in a problem directory
28
+ When I run `clicoder build`
29
+ And I run `clicoder execute`
30
+ Given outputs are wrong
31
+ When I run `clicoder judge`
32
+ Then the output should contain "Wrong Answer"
33
+
34
+ Scenario: Judge correct outputs
35
+ Given in a problem directory
36
+ When I run `clicoder build`
37
+ And I run `clicoder execute`
38
+ Given outputs are correct
39
+ When I run `clicoder judge`
40
+ Then the output should contain "Correct Answer"
41
+
42
+ Scenario: Judge outputs within allowed absolute error
43
+ Given in a problem directory
44
+ And the answer differs in second decimal place
45
+ When I run `clicoder judge`
46
+ Then the output should contain "Wrong Answer"
47
+
48
+ Scenario: Judge outputs within allowed absolute error
49
+ Given in a problem directory
50
+ And the answer differs in second decimal place
51
+ When I run `clicoder judge -d 2`
52
+ Then the output should contain "Wrong Answer"
53
+
54
+ Scenario: Judge outputs within allowed absolute error
55
+ Given in a problem directory
56
+ And the answer differs in second decimal place
57
+ When I run `clicoder judge -d 1`
58
+ Then the output should contain "Correct Answer"
59
+
60
+ Scenario: Submit with user_id and password
61
+ Given SampleSite submission url is stubbed with webmock
62
+ And in a problem directory
63
+ And Launchy.open is stubbed
64
+ When I run `clicoder submit`
65
+ Then the output should contain "Submission Succeeded."
66
+ And the submission status should be opened
67
+
68
+ Scenario: Submit without user_id and password
69
+ Given SampleSite submission url is stubbed with webmock
70
+ Given in a problem directory
71
+ Given I don't have user_id and password
72
+ When I run `clicoder submit`
73
+ Then the output should contain "Submission Failed."
74
+
75
+ Scenario: Open problem page with browser
76
+ Given in a problem directory
77
+ And Launchy.open is stubbed
78
+ When I run `clicoder browse`
79
+ Then the problem page should be opened
@@ -0,0 +1,80 @@
1
+ require 'clicoder'
2
+ require 'clicoder/sites/sample_site'
3
+ require 'launchy'
4
+
5
+ Given /^SampleSite submission url is stubbed with webmock/ do
6
+ stub_request(:post, "http://samplesite.com/submit").
7
+ with(:body => {"password"=>"sample_password", "user_id"=>"sample_user_id"},
8
+ :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'Host'=>'samplesite.com', 'User-Agent'=>'Ruby'}).
9
+ to_return(:status => 200, :body => "Success", :headers => {})
10
+ stub_request(:post, "http://samplesite.com/submit").
11
+ with(:body => {"password"=>"", "user_id"=>""},
12
+ :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'Host'=>'samplesite.com', 'User-Agent'=>'Ruby'}).
13
+ to_return(:status => 200, :body => "Failure", :headers => {})
14
+ end
15
+
16
+ Given /^I don't have user_id and password/ do
17
+ FileUtils.rm("#{ENV['HOME']}/.clicoder.d/config.yml")
18
+ end
19
+
20
+ Given /^in a problem directory/ do
21
+ sample_site = Clicoder::SampleSite.new
22
+ sample_site.start
23
+ Dir.chdir(sample_site.working_directory)
24
+ end
25
+
26
+ Given /^there is no output/ do
27
+ FileUtils.rm(Dir.glob("#{Clicoder::MY_OUTPUTS_DIRNAME}/*.txt"))
28
+ end
29
+
30
+ Given /^outputs are wrong/ do
31
+ # it's wrong already
32
+ end
33
+
34
+ Given /^outputs are correct/ do
35
+ FileUtils.cp(Dir.glob("#{Clicoder::OUTPUTS_DIRNAME}/*.txt"), Clicoder::MY_OUTPUTS_DIRNAME)
36
+ end
37
+
38
+ Given /^the answer differs in second decimal place/ do
39
+ FileUtils.rm(Dir.glob("#{Clicoder::OUTPUTS_DIRNAME}/*"))
40
+ FileUtils.rm(Dir.glob("#{Clicoder::MY_OUTPUTS_DIRNAME}/*"))
41
+ File.open("#{Clicoder::OUTPUTS_DIRNAME}/0.txt", 'w') do |f|
42
+ f.write(<<-EOS)
43
+ 0.11 0.11
44
+ 0.13 0.13
45
+ EOS
46
+ end
47
+ File.open("#{Clicoder::MY_OUTPUTS_DIRNAME}/0.txt", 'w') do |f|
48
+ f.write(<<-EOS)
49
+ 0.12 0.12
50
+ 0.12 0.12
51
+ EOS
52
+ end
53
+ end
54
+
55
+ Given /^Launchy.open is stubbed/ do
56
+ @launchy_open_count = 0
57
+ Launchy.stub(:open) do |url|
58
+ @launchy_open_count += 1
59
+ puts "opening #{url}"
60
+ end
61
+ end
62
+
63
+ Then /^an executable should be generated/ do
64
+ expect(File.exists?('a.out')).to be_true
65
+ end
66
+
67
+ Then /^my answer should be output in my outputs directory/ do
68
+ Dir.glob("#{Clicoder::INPUTS_DIRNAME}/*.txt") do |file|
69
+ basename = File.basename(file)
70
+ expect(File.exists?("#{Clicoder::MY_OUTPUTS_DIRNAME}/#{basename}")).to be_true
71
+ end
72
+ end
73
+
74
+ Then /^the submission status should be opened/ do
75
+ @launchy_open_count.should eq(1)
76
+ end
77
+
78
+ Then /^the problem page should be opened/ do
79
+ @launchy_open_count.should eq(1)
80
+ end
@@ -0,0 +1,26 @@
1
+ require 'aruba/cucumber'
2
+ require 'aruba/in_process'
3
+ require 'cucumber/rspec/doubles'
4
+
5
+ require 'clicoder/cli'
6
+
7
+ ENV['PATH'] = "#{Dir.pwd}/bin:#{ENV['PATH']}"
8
+
9
+ Aruba::InProcess.main_class = Clicoder::ArubaCLI
10
+ Aruba.process = Aruba::InProcess
11
+
12
+ Before do
13
+ # Don't use tmp/aruba dir
14
+ @dirs = ['.']
15
+ end
16
+
17
+ Around do |scenario, block|
18
+ Dir.mktmpdir do |dir|
19
+ Dir.chdir(dir) do
20
+ ENV['HOME'] = Dir.pwd
21
+ FileUtils.cp_r("#{FIXTURE_DIR}/clicoder.d", '.clicoder.d')
22
+
23
+ block.call
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ require 'webmock/cucumber'
2
+
3
+ # TODO: DRY. see spec/spec_helper.rb
4
+ GEM_ROOT = Gem::Specification.find_by_name('clicoder').gem_dir
5
+ FIXTURE_DIR = GEM_ROOT + '/fixtures'
@@ -0,0 +1,6 @@
1
+ build:
2
+ g++ main.cpp
3
+
4
+ execute:
5
+ ./a.out < in.txt > out.txt
6
+
@@ -0,0 +1,9 @@
1
+ ---
2
+ default:
3
+ template: template.cpp
4
+ makefile: Makefile
5
+ sample_site:
6
+ user_id: sample_user_id
7
+ password: sample_password
8
+ template: sample_template.cpp
9
+ makefile: sample_Makefile
@@ -0,0 +1,6 @@
1
+ #include <iostream>
2
+
3
+ int main()
4
+ {
5
+ printf("Hello, World.\n");
6
+ }
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Sample Problem</title>
6
+ </head>
7
+ <body>
8
+ <div id="description">
9
+ <h1>Sample Problem</h1>
10
+ <p>
11
+ Double the numbers.
12
+ </p>
13
+ </div>
14
+ <div id="inputs">
15
+ <pre>10</pre>
16
+ <pre>0.01</pre>
17
+ </div>
18
+ <div id="outputs">
19
+ <pre>20</pre>
20
+ <pre>0.02</pre>
21
+ </div>
22
+ </body>
23
+ </html>