jtest 0.1.1 → 0.2.0

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.
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: