clicoder 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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>