jtest 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
  gem "thor"
6
+ gem "htmlentities", "~> 4.3.1"
6
7
 
7
8
  # Add dependencies to develop your gem here.
8
9
  # Include everything needed to run rake, tests, features, etc.
data/README.rdoc CHANGED
@@ -1,6 +1,61 @@
1
1
  = jtest
2
+ jtest is a command-line tool designed to improve your productivity when solving problems from http://jutge.org
2
3
 
3
- Tool for automatic testing and creating problems from Jutge.org
4
+ jtest provides some simple commands to finding new problems and creating workspaces to solve them. Also, jtest can compile and test your "solutions" with the public samples of the problems.
5
+
6
+ == Usage
7
+
8
+ === Finding a problem
9
+ $ jtest find Treasures
10
+ working Trying to find problems that match: Treasures
11
+ P70690 Treasures in a map (1)
12
+ P60796 Treasures in a map (2)
13
+ P90766 Treasures in a map (3)
14
+ P39846 Treasures in a map (4)
15
+ found 4 matches found!
16
+
17
+ This will show all the problems that contain `Treasures` in his name!
18
+
19
+ === Creating a new problem
20
+ Let's create a workspace for solving `Treasures in a map (1)`.
21
+ $ jtest new 70690
22
+ connecting Getting info about problem P70690_en...
23
+ found P70690_en: Treasures in a map (1)
24
+ working Creating workspace for P70690_en: Treasures in a map (1)
25
+ create P70690_Treasures_in_a_map_(1)
26
+ create P70690_Treasures_in_a_map_(1)/sample1.dat
27
+ create P70690_Treasures_in_a_map_(1)/sample1.out
28
+ create P70690_Treasures_in_a_map_(1)/sample2.dat
29
+ create P70690_Treasures_in_a_map_(1)/sample2.out
30
+ create P70690_Treasures_in_a_map_(1)/sample3.dat
31
+ create P70690_Treasures_in_a_map_(1)/sample3.out
32
+ create P70690_Treasures_in_a_map_(1)/main.cc
33
+ As you can see, jtest automatically downloads every public sample of the problem and creates a C++ main file to start solving your problem.
34
+
35
+ === Testing your solutions
36
+ All right! I think I've solved the problem we created before. Let's see if it passes the public samples!
37
+ $ jtest test
38
+ testing Running tests on P70690_Treasures_in_a_map_(1)...
39
+ compile P70690_Treasures_in_a_map_(1)/main.cc
40
+ running P70690_Treasures_in_a_map_(1)/sample1.dat
41
+ wrong P70690_Treasures_in_a_map_(1)/sample1.out
42
+ running P70690_Treasures_in_a_map_(1)/sample2.dat
43
+ wrong P70690_Treasures_in_a_map_(1)/sample2.out
44
+ running P70690_Treasures_in_a_map_(1)/sample3.dat
45
+ wrong P70690_Treasures_in_a_map_(1)/sample3.out
46
+ ---------------------------------------------------
47
+ failed 0
48
+ missing 0
49
+ wrong 3
50
+ passed 0
51
+ total 3
52
+ ---------------------------------------------------
53
+ Ooops! It seems my solution doesn't work very well... When the Nth sample test fails jtest saves the output of your solution as sampleN_test.out in the problem's workspace, so you can see what's going wrong.
54
+
55
+ === Getting help
56
+ You can obtain help about how to use one command with the help command. For example:
57
+ $ jtest help new
58
+ Will show you all the information you need to use the `new` command (syntax, options, description, etc.).
4
59
 
5
60
  == Contributing to jtest
6
61
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/ext/mkrf_conf.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+
3
+ # the whole reason this file exists: to return an error if openssl
4
+ # isn't installed.
5
+ require 'openssl'
6
+
7
+ # create dummy rakefile to indicate success
8
+ f = File.open(File.join(File.dirname(__FILE__), "Rakefile"), "w")
9
+ f.write("task :default\n")
10
+ f.close
11
+
12
+ # based on
13
+ # https://github.com/tablatom/hobo/commit/0085d4d3c5fdf2f71ca8f4412927c5147fa3d96f
14
+ # Thanks tablatom! ;)
data/jtest.gemspec CHANGED
@@ -5,14 +5,15 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "jtest"
8
- s.version = "0.1.1"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["H\u{e9}ctor Ram\u{f3}n Jim\u{e9}nez"]
12
- s.date = "2012-11-05"
12
+ s.date = "2013-01-16"
13
13
  s.description = "Tool for automatic testing and creating problems from Jutge.org"
14
14
  s.email = "hector0193@gmail.com"
15
15
  s.executables = ["jtest"]
16
+ s.extensions = ["ext/mkrf_conf.rb"]
16
17
  s.extra_rdoc_files = [
17
18
  "LICENSE.txt",
18
19
  "README.rdoc"
@@ -25,14 +26,17 @@ Gem::Specification.new do |s|
25
26
  "Rakefile",
26
27
  "VERSION",
27
28
  "bin/jtest",
29
+ "ext/mkrf_conf.rb",
28
30
  "jtest.gemspec",
29
31
  "lib/jtest.rb",
30
32
  "lib/jtest/cli.rb",
31
33
  "lib/jtest/commands.rb",
34
+ "lib/jtest/commands/find.rb",
32
35
  "lib/jtest/commands/new.rb",
33
36
  "lib/jtest/commands/test.rb",
34
37
  "lib/jtest/commands/update.rb",
35
38
  "lib/jtest/problem.rb",
39
+ "lib/jtest/templates/main.tt",
36
40
  "test/helper.rb",
37
41
  "test/jtest/test_problem.rb",
38
42
  "test/test_jtest.rb"
@@ -48,6 +52,7 @@ Gem::Specification.new do |s|
48
52
 
49
53
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
54
  s.add_runtime_dependency(%q<thor>, [">= 0"])
55
+ s.add_runtime_dependency(%q<htmlentities>, ["~> 4.3.1"])
51
56
  s.add_development_dependency(%q<shoulda>, [">= 0"])
52
57
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
53
58
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
@@ -55,6 +60,7 @@ Gem::Specification.new do |s|
55
60
  s.add_development_dependency(%q<simplecov>, [">= 0"])
56
61
  else
57
62
  s.add_dependency(%q<thor>, [">= 0"])
63
+ s.add_dependency(%q<htmlentities>, ["~> 4.3.1"])
58
64
  s.add_dependency(%q<shoulda>, [">= 0"])
59
65
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
60
66
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
@@ -63,6 +69,7 @@ Gem::Specification.new do |s|
63
69
  end
64
70
  else
65
71
  s.add_dependency(%q<thor>, [">= 0"])
72
+ s.add_dependency(%q<htmlentities>, ["~> 4.3.1"])
66
73
  s.add_dependency(%q<shoulda>, [">= 0"])
67
74
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
68
75
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
data/lib/jtest/cli.rb CHANGED
@@ -8,6 +8,10 @@ module Jtest
8
8
 
9
9
  add_runtime_options!
10
10
 
11
+ register Jtest::Commands::Find, "find", "find [NAME]",
12
+ "Finds all the problems that match with the given name"
13
+ tasks["find"].options = Jtest::Commands::Find.class_options
14
+
11
15
  register Jtest::Commands::New, "new", "new [ID]",
12
16
  "Creates a workspace to solve problem with the given id"
13
17
  tasks["new"].options = Jtest::Commands::New.class_options
@@ -0,0 +1,34 @@
1
+ require "htmlentities"
2
+ require "jtest/problem"
3
+
4
+ module Jtest
5
+ module Commands
6
+ class Find < Thor::Group
7
+ include Thor::Actions
8
+
9
+ desc "Finds all the problems that match with the given name"
10
+
11
+ argument :name, :type => :string, :desc => "A problem name to match"
12
+
13
+ def get_problems
14
+ say_status :working, "Trying to find problems that match: #{name}", :yellow
15
+ @problems = Problem.find(name)
16
+ end
17
+
18
+ def show_problems
19
+ coder = HTMLEntities.new
20
+ @problems.each do |problem|
21
+ say_status problem[0], coder.decode(problem[1]), :blue
22
+ end
23
+
24
+ if @problems.empty?
25
+ say_status :not_found, "0 matches found :(", :red
26
+ else
27
+ say_status :found,
28
+ "#{@problems.size} match#{'es' if @problems.size != 1} found!",
29
+ :green
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,39 +1,45 @@
1
1
  require "jtest/problem"
2
2
 
3
3
  module Jtest
4
- module Commands
5
- class New < Thor::Group
6
- include Thor::Actions
7
-
8
- desc "Creates a workspace to solve problem with the given id"
9
-
10
- argument :id, :type => :numeric, :desc => "The problem identifier"
11
- class_option :lang, :type => :string, :aliases => '-l', :desc => "Language of the problem",
12
- :default => 'en'
13
- class_option :prefix, :type => :string, :aliases => '-p', :desc => "Prefix of the problem",
14
- :default => 'P'
15
-
16
- def get_problem_info
17
- @problem = Problem.new(id, options)
18
-
19
- say_status :connecting, "Getting info about problem #{@problem.id}...", :yellow
20
- @problem.retrieve_info
21
-
22
- raise "Problem #{@problem.id} not found :(" unless @problem.exists?
23
-
24
- say_status :found, @problem.title, :green
25
- end
26
-
27
- def create_workspace
28
- say_status :working, "Creating workspace for #{@problem.title}", :yellow
29
-
30
- empty_directory @problem.dirname
4
+ module Commands
5
+ class New < Thor::Group
6
+ include Thor::Actions
7
+
8
+ desc "Creates a workspace to solve problem with the given id"
9
+
10
+ argument :id, :type => :numeric, :desc => "The problem identifier"
11
+ class_option :lang, :type => :string, :aliases => '-l', :desc => "Language of the problem",
12
+ :default => 'en'
13
+ class_option :prefix, :type => :string, :aliases => '-p', :desc => "Prefix of the problem",
14
+ :default => 'P'
15
+
16
+ def self.source_root
17
+ File.dirname(__FILE__)
18
+ end
19
+
20
+ def get_problem_info
21
+ @problem = Problem.new(id, options)
22
+
23
+ say_status :connecting, "Getting info about problem #{@problem.id}...", :yellow
24
+ @problem.retrieve_info
25
+
26
+ raise "Problem #{@problem.id} not found :(" unless @problem.exists?
27
+
28
+ say_status :found, @problem.title, :green
29
+ end
30
+
31
+ def create_workspace
32
+ say_status :working, "Creating workspace for #{@problem.title}", :yellow
33
+
34
+ empty_directory @problem.dirname
31
35
 
32
36
  @problem.samples.each_with_index do |sample, index|
33
37
  create_file "#{@problem.dirname}/sample#{index+1}.dat", sample[0]
34
38
  create_file "#{@problem.dirname}/sample#{index+1}.out", sample[1]
35
39
  end
40
+
41
+ template "../templates/main.tt", "#{@problem.dirname}/main.cc"
36
42
  end
37
- end
38
- end
39
- end
43
+ end
44
+ end
45
+ end
@@ -1,4 +1,5 @@
1
1
  require "jtest/commands/new"
2
+ require "jtest/commands/find"
2
3
  require "jtest/commands/test"
3
4
  require "jtest/commands/update"
4
5
 
@@ -6,4 +7,4 @@ module Jtest
6
7
  module Commands
7
8
 
8
9
  end
9
- end
10
+ end
data/lib/jtest/problem.rb CHANGED
@@ -2,80 +2,101 @@ require "open-uri"
2
2
  require "openssl"
3
3
 
4
4
  module Jtest
5
- class Problem
6
- URL = "https://www.jutge.org/problems/"
7
- REGEXPS = {
8
- :title => /<title>Jutge :: Problem (.+?)<\/title>/,
9
- :samples => /<pre.+?>(.+?)<\/pre>/m,
10
- :dir_id => /[0-9]+/,
11
- :invalid_url => "Wrong URL."
12
- }
13
- DEFAULT_OPTIONS = {:lang => 'en', :prefix => 'P', :dirname => nil}
14
-
15
- attr_reader :id
16
- attr_reader :title
17
- attr_reader :samples
18
- attr_reader :dirname
19
-
20
- def initialize(id, options = {})
21
- options = DEFAULT_OPTIONS.merge(options)
22
-
23
- @id = options[:prefix] + id.to_s + '_' + options[:lang]
24
- @title = nil
25
- @samples = []
26
- @dirname = options[:dirname]
27
- end
28
-
29
- def connect
30
- url = URL + @id
31
- @source = open(url, :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE).read
32
- end
33
-
34
- def exists?
35
- connect if @source.nil?
36
-
37
- not @source.include? REGEXPS[:invalid_url]
38
- end
39
-
40
- def retrieve_info
41
- connect
42
-
43
- return false unless exists?
44
-
45
- @title = @source.scan(REGEXPS[:title])[0][0]
46
- @samples = @source.scan(REGEXPS[:samples]).flatten.each_slice(2).to_a
47
- @dirname = @title.gsub(/_(.+?)\:/, '').gsub(/\s/, '_') if @dirname.nil?
48
-
49
- return true
50
- end
51
-
52
- class << self
53
- def select(ids, options = {})
54
- options = DEFAULT_OPTIONS.merge(options)
55
- dirs = dirs_match(ids)
56
-
57
- problems = []
58
- dirs.each do |dir|
59
- REGEXPS[:dir_id].match(dir) do |match|
60
- options[:dirname] = dir
61
- problems << Problem.new(match, options) unless match.nil?
62
- end
63
- end
64
-
65
- return problems
66
- end
67
-
68
- private
69
- def dirs_match(ids)
70
- if ids == ["all"]
71
- dirs = Dir["[PX]*_*"]
72
- else
73
- dirs = []
74
- ids.each { |id| dirs += Dir["#{id}*"] }
75
- end
76
-
77
- return dirs
78
- end
79
- end
80
- end
81
- end
5
+ class Problem
6
+ URL = "https://www.jutge.org/problems/"
7
+ REGEXPS = {
8
+ :title => /<title>Jutge :: Problem (.+?)<\/title>/,
9
+ :samples => /<pre.+?>(.+?)<\/pre>/m,
10
+ :dir_id => /[0-9]+/,
11
+ :invalid_url => "Wrong URL."
12
+ }
13
+ DEFAULT_OPTIONS = {:lang => 'en', :prefix => 'P', :dirname => nil}
14
+
15
+ attr_reader :id
16
+ attr_reader :title
17
+ attr_reader :samples
18
+ attr_reader :dirname
19
+
20
+ def initialize(id, options = {})
21
+ options = DEFAULT_OPTIONS.merge(options)
22
+
23
+ @id = options[:prefix] + id.to_s + '_' + options[:lang]
24
+ @title = nil
25
+ @samples = []
26
+ @dirname = options[:dirname]
27
+ end
28
+
29
+ def connect
30
+ url = URL + @id
31
+ @source = open(url, :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE).read
32
+ end
33
+
34
+ def exists?
35
+ connect if @source.nil?
36
+
37
+ not @source.include? REGEXPS[:invalid_url]
38
+ end
39
+
40
+ def retrieve_info
41
+ connect
42
+
43
+ return false unless exists?
44
+
45
+ @title = @source.scan(REGEXPS[:title])[0][0]
46
+ @samples = @source.scan(REGEXPS[:samples]).flatten.each_slice(2).to_a
47
+ @dirname = @title.gsub(/_(.+?)\:/, '').gsub(/\s/, '_') if @dirname.nil?
48
+
49
+ return true
50
+ end
51
+
52
+ class << self
53
+ def select(ids, options = {})
54
+ options = DEFAULT_OPTIONS.merge(options)
55
+ dirs = dirs_match(ids)
56
+
57
+ problems = []
58
+ dirs.each do |dir|
59
+ REGEXPS[:dir_id].match(dir) do |match|
60
+ options[:dirname] = dir
61
+ problems << Problem.new(match, options) unless match.nil?
62
+ end
63
+ end
64
+
65
+ return problems
66
+ end
67
+
68
+ def find(name)
69
+ list_entry = /
70
+ <td.+?> # Before problem id
71
+ (P[0-9]+) # Capture problem id
72
+ <\/.+?td> # After problem id
73
+ \n # Line break
74
+ \s+? # Possible whitespaces
75
+ <td.+?> # Before problem title
76
+ ( # Capture problem title
77
+ [^<>]*? # All characters except HTML tags
78
+ #{Regexp.quote(name)} # Match the given name
79
+ [^<>]*? # Same as before
80
+ ) # End capture
81
+ <\/.+?td>/x # After problem title
82
+
83
+ source = open(URL, :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE).read
84
+ problems = source.scan(list_entry).flatten.each_slice(2).to_a
85
+
86
+ return problems
87
+ end
88
+
89
+ private
90
+ def dirs_match(ids)
91
+ if ids == ["all"]
92
+ dirs = Dir["[PX]*_*"]
93
+ else
94
+ dirs = []
95
+ ids.each { |id| dirs += Dir["#{id}*"] }
96
+ end
97
+
98
+ return dirs
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,8 @@
1
+ #include <iostream>
2
+
3
+ using namespace std;
4
+
5
+ int main()
6
+ {
7
+
8
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jtest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-05 00:00:00.000000000 Z
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: htmlentities
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 4.3.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 4.3.1
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: shoulda
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -111,7 +127,8 @@ description: Tool for automatic testing and creating problems from Jutge.org
111
127
  email: hector0193@gmail.com
112
128
  executables:
113
129
  - jtest
114
- extensions: []
130
+ extensions:
131
+ - ext/mkrf_conf.rb
115
132
  extra_rdoc_files:
116
133
  - LICENSE.txt
117
134
  - README.rdoc
@@ -123,14 +140,17 @@ files:
123
140
  - Rakefile
124
141
  - VERSION
125
142
  - bin/jtest
143
+ - ext/mkrf_conf.rb
126
144
  - jtest.gemspec
127
145
  - lib/jtest.rb
128
146
  - lib/jtest/cli.rb
129
147
  - lib/jtest/commands.rb
148
+ - lib/jtest/commands/find.rb
130
149
  - lib/jtest/commands/new.rb
131
150
  - lib/jtest/commands/test.rb
132
151
  - lib/jtest/commands/update.rb
133
152
  - lib/jtest/problem.rb
153
+ - lib/jtest/templates/main.tt
134
154
  - test/helper.rb
135
155
  - test/jtest/test_problem.rb
136
156
  - test/test_jtest.rb
@@ -149,7 +169,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
169
  version: '0'
150
170
  segments:
151
171
  - 0
152
- hash: 360134583439998368
172
+ hash: -358689626784226077
153
173
  required_rubygems_version: !ruby/object:Gem::Requirement
154
174
  none: false
155
175
  requirements: