pcoder 0.0.3

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b95bbdb05e44583430cfc83e11fa38b5dba7c7a5
4
+ data.tar.gz: eda24f50deb0392c7afe547db3cb473e4e058699
5
+ SHA512:
6
+ metadata.gz: 5576e9ce6b58b874e4f3f472d69083eb3ea23d01719c1368616d973bf03d6c0073b5ee44a10686f405bb4422d2d1342dccddefe4db1a8ad9710b70e4a3f98444
7
+ data.tar.gz: 5d35207ef9b29c704711dcf9f1313ca26352bae0cf52705a1d57634ab9fc25b160c5500bdfb5917985b0e17b1f1e8f050675e1f4d08f1b50dec87be727c6dbfd
@@ -0,0 +1,6 @@
1
+ .*
2
+ !.git*
3
+ *.gem
4
+ pkg/*
5
+ spec/etc/account.rb
6
+ !spec/etc/account.rb.example
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pcoder.gemspec
4
+ gemspec
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ pcoder (0.0.1)
5
+ highline
6
+ mechanize
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.2.2)
12
+ domain_name (0.5.10)
13
+ unf (>= 0.0.5, < 1.0.0)
14
+ highline (1.6.16)
15
+ mechanize (2.6.0)
16
+ domain_name (~> 0.5, >= 0.5.1)
17
+ mime-types (~> 1.17, >= 1.17.2)
18
+ net-http-digest_auth (~> 1.1, >= 1.1.1)
19
+ net-http-persistent (~> 2.5, >= 2.5.2)
20
+ nokogiri (~> 1.4)
21
+ ntlm-http (~> 0.1, >= 0.1.1)
22
+ webrobots (>= 0.0.9, < 0.2)
23
+ mime-types (1.22)
24
+ net-http-digest_auth (1.3)
25
+ net-http-persistent (2.8)
26
+ nokogiri (1.5.9)
27
+ ntlm-http (0.1.1)
28
+ rake (10.0.4)
29
+ rspec (2.13.0)
30
+ rspec-core (~> 2.13.0)
31
+ rspec-expectations (~> 2.13.0)
32
+ rspec-mocks (~> 2.13.0)
33
+ rspec-core (2.13.1)
34
+ rspec-expectations (2.13.0)
35
+ diff-lcs (>= 1.1.3, < 2.0)
36
+ rspec-mocks (2.13.0)
37
+ unf (0.1.1)
38
+ unf_ext
39
+ unf_ext (0.0.6)
40
+ webrobots (0.1.1)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ pcoder!
47
+ rake
48
+ rspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Suguru Odai
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.
@@ -0,0 +1,53 @@
1
+ # Pcoder
2
+
3
+ Pcoder submits local file to AtCoder.
4
+ http://atcoder.jp/
5
+
6
+ ## Installation
7
+
8
+ $ gem install pcoder
9
+
10
+ ## Naming file rules
11
+
12
+ [Contest sub domain]_[task].[expansion]
13
+
14
+ ### Example
15
+
16
+ Task: http://practice.contest.atcoder.jp/tasks/practice_1
17
+
18
+ practice_1.c
19
+ practice_1.cc
20
+ practice_1.cpp
21
+ practice_1.java
22
+ practice_1.pl
23
+ practice_1.php
24
+ practice_1.rb
25
+ practice_1.py
26
+ practice_1.hs
27
+
28
+ Task: http://arc013.contest.atcoder.jp/tasks/arc013_3
29
+
30
+ arc013_3.c
31
+ arc013_3.cc
32
+ arc013_3.cpp
33
+ arc013_3.java
34
+ arc013_3.pl
35
+ arc013_3.php
36
+ arc013_3.rb
37
+ arc013_3.py
38
+ arc013_3.hs
39
+
40
+ ## Usage
41
+
42
+ $ pcoder [file...]
43
+ Username: # Enter Your AtCoder ID.
44
+ Password: # Enter Your AtCoder Password.
45
+ Successfully uploaded.
46
+
47
+ ## Help
48
+
49
+ pcoder [file...]
50
+ -s Set Atcoder contest site sub domain.
51
+ -t Set task alphabet.
52
+ --proxy Set proxy host. Example: [ --proxy proxy.example.com:8080 ]
53
+ -h --help Display Help.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'pcoder'
4
+
5
+ pcoder = Pcoder::Processor.new
6
+ pcoder.parse_options
7
+ pcoder.run
@@ -0,0 +1,156 @@
1
+ require 'mechanize'
2
+ require 'optparse'
3
+ require 'highline'
4
+
5
+ module Pcoder
6
+ ATCODER_HOST = "contest.atcoder.jp"
7
+
8
+ class SourceCode
9
+ attr_reader :basename, :language_id, :task, :body
10
+
11
+ def initialize(path)
12
+ @basename = File.basename(path)
13
+ extname = File.extname(path)
14
+ @language_id = to_language_id(extname)
15
+ @task = @basename.split(/[_.]/)[1]
16
+ @body = File.open(path).read
17
+ end
18
+
19
+ def set_task_option(task)
20
+ @task = task.split("_").last
21
+ end
22
+
23
+ private
24
+
25
+ def to_language_id(extname)
26
+ case extname
27
+ # C
28
+ when ".c" then "1"
29
+ # C++
30
+ when ".cc", ".cpp" then "2"
31
+ # Java
32
+ when ".java" then "3"
33
+ # PHP
34
+ when ".php" then "5"
35
+ # D
36
+ when ".d" then "6"
37
+ # Python
38
+ when ".py" then "7"
39
+ # Perl
40
+ when ".pl" then "8"
41
+ # Ruby
42
+ when ".rb" then "9"
43
+ # Haskell
44
+ when ".hs" then "11"
45
+ # Pascal
46
+ when ".p", ".pp", ".pas" then "12"
47
+ # HavaScript
48
+ when ".js" then "15"
49
+ # Visual Basic
50
+ when ".vb" then "16"
51
+ # Text
52
+ when ".txt", ".text" then "17"
53
+ else nil
54
+ end
55
+ end
56
+ end
57
+
58
+ class Atcoder
59
+ def initialize
60
+ @agent = Mechanize.new
61
+ end
62
+
63
+ def login(user, pass, host)
64
+ @agent.get("http://#{host}/login")
65
+ before_uri = @agent.page.uri
66
+ @agent.page.form_with do |f|
67
+ f.field_with(:name => "name").value = user
68
+ f.field_with(:name => "password").value = pass
69
+ end.click_button
70
+ if @agent.page.uri == before_uri
71
+ mes = "The username or password you entered is incorrect."
72
+ raise LoginError.exception(mes)
73
+ end
74
+ true
75
+ end
76
+
77
+ def submit(source)
78
+ @agent.get("http://#{@agent.page.uri.host}/submit")
79
+ task_id = get_task_id(source.task)
80
+ @agent.page.form_with do |f|
81
+ f.field_with(:name => "task_id").value = task_id
82
+ f.field_with(:name => "language_id_#{task_id}").value = source.language_id
83
+ f.field_with(:name => "source_code").value = source.body
84
+ end.click_button
85
+ if @agent.page.uri.path == "/submit"
86
+ mes = "Please check file name or body and try again"
87
+ raise InputFormError.exception(mes)
88
+ end
89
+ true
90
+ end
91
+
92
+ def set_proxy(proxy)
93
+ host, port = proxy.split(":")
94
+ @agent.set_proxy(host, port)
95
+ end
96
+
97
+ def get_task_id(pos)
98
+ @agent.get("http://#{@agent.page.uri.host}/submit")
99
+ selecter = "//select[@id=\"submit-task-selector\"]/option[#{pos}]"
100
+ @agent.page.at(selecter)['value']
101
+ end
102
+ end
103
+
104
+ class Processor
105
+ def initialize
106
+ @opts = {}
107
+ end
108
+
109
+ def run(path = ARGV[0], this = self, atcoder = Atcoder.new, source = nil)
110
+ exit_with_message("Please specify a file and try agein.") if path.nil?
111
+ user = this.enter_username
112
+ pass = this.enter_password
113
+ source ||= SourceCode.new(path)
114
+ host = contest_host(source.basename)
115
+ atcoder.login(user, pass, host)
116
+ atcoder.set_proxy(@opts[:proxy]) if @opts[:proxy]
117
+ source.set_task_option(@opts[:task]) if @opts[:task]
118
+ puts "Successfully uploaded." if atcoder.submit(source)
119
+ end
120
+
121
+ def parse_options
122
+ opt = OptionParser.new
123
+ opt.banner = "#{File.basename($0)} [file...]"
124
+ opt.on("-t Task", "Set contest task name.") {|v| @opts[:task] = v }
125
+ opt.on("--proxy Proxy", "Set proxy host. Example: \[ --proxy proxy.example.com:8080 \]") {|v| @opts[:proxy] = v }
126
+ opt.on("-h", "--help", "Display Help.") do
127
+ puts opt.help
128
+ exit
129
+ end
130
+ opt.parse!(ARGV)
131
+ end
132
+
133
+ protected
134
+
135
+ def exit_with_message(mes)
136
+ puts mes
137
+ exit
138
+ end
139
+
140
+ def enter_username
141
+ HighLine.new.ask("Username: ")
142
+ end
143
+
144
+ def enter_password
145
+ HighLine.new.ask("Password: ") { |q| q.echo = "*" }
146
+ end
147
+
148
+ def contest_host(basename)
149
+ sub_domain = (@opts[:task] || basename ).split("_").first
150
+ "#{sub_domain}.#{ATCODER_HOST}"
151
+ end
152
+ end
153
+
154
+ class LoginError < StandardError; end
155
+ class InputFormError < StandardError; end
156
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "pcoder"
7
+ gem.version = "0.0.3"
8
+ gem.authors = ["Suguru Odai"]
9
+ gem.email = ["ourqwers@gmail.com"]
10
+ gem.description = "Pcoder submits local file to atcoder."
11
+ gem.summary = "Pcoder submits local file to atcoder."
12
+ gem.homepage = "https://github.com/Shindo200/pcoder"
13
+ gem.license = "MIT"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "mechanize"
21
+ gem.add_dependency "highline"
22
+ gem.add_development_dependency "rake"
23
+ gem.add_development_dependency "rspec"
24
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ # Atcoder account to use with rspec.
2
+ ATCODER_USER = "example"
3
+ ATCODER_PASS = "example"
@@ -0,0 +1 @@
1
+ # Method check.
@@ -0,0 +1,190 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+
4
+ module Pcoder
5
+ SPEC_HOST = "arc012.contest.atcoder.jp"
6
+ SPEC_FILE = "../etc/practice_1.rb"
7
+
8
+ describe SourceCode do
9
+ let(:path) { File.expand_path(SPEC_FILE, __FILE__) }
10
+ let(:source) { SourceCode.new(path) }
11
+
12
+ describe "#initialize" do
13
+ context "with \"#{SPEC_FILE}\"" do
14
+ it { source.basename.should eq "practice_1.rb" }
15
+ it { source.language_id.should eq "9" }
16
+ it { source.task.should eq "1" }
17
+ it { source.body.should eq "# Method check.\n" }
18
+ end
19
+ end
20
+
21
+ describe "#set_task_option" do
22
+ context "with \"arc012_1\"" do
23
+ it do
24
+ source.send(:set_task_option, "arc012_1")
25
+ source.task.should eq "1"
26
+ end
27
+ end
28
+
29
+ context "with \"arc012_2\"" do
30
+ it do
31
+ source.send(:set_task_option, "arc012_2")
32
+ source.task.should eq "2"
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "#to_language_id" do
38
+ context "with \".c\"" do
39
+ it { source.send(:to_language_id, ".c").should eq "1" }
40
+ end
41
+
42
+ context "with \".cc\"" do
43
+ it { source.send(:to_language_id, ".cc").should eq "2" }
44
+ end
45
+
46
+ context "with \".cpp\"" do
47
+ it { source.send(:to_language_id, ".cpp").should eq "2" }
48
+ end
49
+
50
+ context "with \".java\"" do
51
+ it { source.send(:to_language_id, ".java").should eq "3" }
52
+ end
53
+
54
+ context "with \".php\"" do
55
+ it { source.send(:to_language_id, ".php").should eq "5" }
56
+ end
57
+
58
+ context "with \".d\"" do
59
+ it { source.send(:to_language_id, ".d").should eq "6" }
60
+ end
61
+
62
+ context "with \".py\"" do
63
+ it { source.send(:to_language_id, ".py").should eq "7" }
64
+ end
65
+
66
+ context "with \".pl\"" do
67
+ it { source.send(:to_language_id, ".pl").should eq "8" }
68
+ end
69
+
70
+ context "with \".rb\"" do
71
+ it { source.send(:to_language_id, ".rb").should eq "9" }
72
+ end
73
+
74
+ context "with \".hs\"" do
75
+ it { source.send(:to_language_id, ".hs").should eq "11" }
76
+ end
77
+
78
+ context "with \".p\"" do
79
+ it { source.send(:to_language_id, ".p").should eq "12" }
80
+ end
81
+
82
+ context "with \".pp\"" do
83
+ it { source.send(:to_language_id, ".pp").should eq "12" }
84
+ end
85
+
86
+ context "with \".pas\"" do
87
+ it { source.send(:to_language_id, ".pas").should eq "12" }
88
+ end
89
+
90
+ context "with \".js\"" do
91
+ it { source.send(:to_language_id, ".js").should eq "15" }
92
+ end
93
+
94
+ context "with \".vb\"" do
95
+ it { source.send(:to_language_id, ".vb").should eq "16" }
96
+ end
97
+
98
+ context "with \".txt\"" do
99
+ it { source.send(:to_language_id, ".txt").should eq "17" }
100
+ end
101
+
102
+ context "with \".text\"" do
103
+ it { source.send(:to_language_id, ".text").should eq "17" }
104
+ end
105
+
106
+ context "with \"\"" do
107
+ it { source.send(:to_language_id, "").should be_nil }
108
+ end
109
+ end
110
+ end
111
+
112
+ describe Atcoder do
113
+ let(:atcoder) { Atcoder.new }
114
+
115
+ describe "#login" do
116
+ context "with not_user, not_pass" do
117
+ it { proc { atcoder.send(:login, 'foo', 'bar', SPEC_HOST)}.should raise_error(LoginError) }
118
+ end
119
+
120
+ context "with user, pass" do
121
+ it { atcoder.send(:login, ATCODER_USER, ATCODER_PASS, SPEC_HOST).class.should be_true }
122
+ end
123
+ end
124
+
125
+
126
+ describe "#get_task_id" do
127
+ before { atcoder.send(:login, ATCODER_USER, ATCODER_PASS, SPEC_HOST) }
128
+
129
+ context "with agent, \"1\"" do
130
+ it { atcoder.send(:get_task_id, "1").should eq "440" }
131
+ end
132
+
133
+ context "with agent, \"2\"" do
134
+ it { atcoder.send(:get_task_id, "2").should eq "441" }
135
+ end
136
+ end
137
+ end
138
+
139
+ describe Processor do
140
+ let(:processor) { Processor.new }
141
+
142
+ describe "#run" do
143
+ let(:path) { File.expand_path(SPEC_FILE, __FILE__) }
144
+ let(:atcoder) { double("atcoder").as_null_object }
145
+ let(:source) { double("source").as_null_object }
146
+ let(:this) { double("processor") }
147
+ before do
148
+ atcoder.stub(:submit).and_return(nil)
149
+ this.stub(:enter_username).and_return(ATCODER_USER)
150
+ this.stub(:enter_password).and_return(ATCODER_PASS)
151
+ end
152
+
153
+ context "with user, pass, path, mock_model" do
154
+ it "call Atcoder#submit with SourceCode" do
155
+ atcoder.should_receive(:submit).with(kind_of(SourceCode))
156
+ processor.run(path, this, atcoder)
157
+ end
158
+ end
159
+
160
+ context "with proxy option \"proxy.example.com\"" do
161
+ before { processor.instance_eval { @opts[:proxy] = "proxy.example.com" }}
162
+
163
+ it "call Atcoder#set_proxy with proxy value" do
164
+ atcoder.should_receive(:set_proxy).with("proxy.example.com")
165
+ processor.run(path, this, atcoder)
166
+ end
167
+ end
168
+
169
+ context "with task option \"practice_1\"" do
170
+ before { processor.instance_eval { @opts[:task] = "practice_1" }}
171
+
172
+ it "call SourceCode#set_task_option with task value" do
173
+ source.should_receive(:set_task_option).with("practice_1")
174
+ processor.run(path, this, atcoder, source)
175
+ end
176
+ end
177
+ end
178
+
179
+ describe "#contest_host" do
180
+ context "with \"practice_1.rb\""do
181
+ it { processor.send(:contest_host, "practice_1.rb").should eq "practice.contest.atcoder.jp" }
182
+ end
183
+
184
+ context "with task option \"arc012_1\""do
185
+ before { processor.instance_eval { @opts[:task] = "arc012_1" }}
186
+ it { processor.send(:contest_host, "practice_1.rb").should eq "arc012.contest.atcoder.jp" }
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../spec', __FILE__)
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'pcoder'
4
+ require 'etc/account'
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pcoder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Suguru Odai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mechanize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: highline
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Pcoder submits local file to atcoder.
70
+ email:
71
+ - ourqwers@gmail.com
72
+ executables:
73
+ - pcoder
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/pcoder
84
+ - lib/pcoder.rb
85
+ - pcoder.gemspec
86
+ - spec/etc/.gitkeep
87
+ - spec/etc/account.rb.example
88
+ - spec/etc/practice_1.rb
89
+ - spec/pcoder_spec.rb
90
+ - spec/spec_helper.rb
91
+ homepage: https://github.com/Shindo200/pcoder
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.0.3
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Pcoder submits local file to atcoder.
115
+ test_files:
116
+ - spec/etc/.gitkeep
117
+ - spec/etc/account.rb.example
118
+ - spec/etc/practice_1.rb
119
+ - spec/pcoder_spec.rb
120
+ - spec/spec_helper.rb