the_array_comparator 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.gitignore +16 -0
  2. data/.rspec +2 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +6 -0
  5. data/CONTRIBUTIONS.md +7 -0
  6. data/Gemfile +30 -0
  7. data/Gemfile.lock +122 -0
  8. data/LICENSE.md +20 -0
  9. data/README.md +121 -0
  10. data/RELEASE_NOTES.md +0 -0
  11. data/Rakefile +93 -0
  12. data/TODO.md +1 -0
  13. data/gemfiles/Gemfile.default +30 -0
  14. data/gemfiles/Gemfile.travis +15 -0
  15. data/lib/the_array_comparator/check.rb +27 -0
  16. data/lib/the_array_comparator/comparator.rb +123 -0
  17. data/lib/the_array_comparator/exceptions.rb +21 -0
  18. data/lib/the_array_comparator/result.rb +21 -0
  19. data/lib/the_array_comparator/sample.rb +28 -0
  20. data/lib/the_array_comparator/strategies/base.rb +41 -0
  21. data/lib/the_array_comparator/strategies/contains_all.rb +35 -0
  22. data/lib/the_array_comparator/strategies/contains_all_with_substring_search.rb +39 -0
  23. data/lib/the_array_comparator/strategies/contains_any.rb +34 -0
  24. data/lib/the_array_comparator/strategies/contains_any_with_substring_search.rb +33 -0
  25. data/lib/the_array_comparator/strategies/contains_not.rb +32 -0
  26. data/lib/the_array_comparator/strategies/contains_not_with_substring_search.rb +33 -0
  27. data/lib/the_array_comparator/strategies/is_equal.rb +30 -0
  28. data/lib/the_array_comparator/strategies/is_not_equal.rb +30 -0
  29. data/lib/the_array_comparator/testing_helper/data_set.rb +63 -0
  30. data/lib/the_array_comparator/testing_helper/test_data.rb +33 -0
  31. data/lib/the_array_comparator/testing_helper.rb +55 -0
  32. data/lib/the_array_comparator/version.rb +6 -0
  33. data/lib/the_array_comparator.rb +34 -0
  34. data/script/console +8 -0
  35. data/script/terminal +12 -0
  36. data/spec/benchmark/benchmark_spec.rb +28 -0
  37. data/spec/check_spec.rb +30 -0
  38. data/spec/comparator/base_spec.rb +16 -0
  39. data/spec/comparator/comparator_spec.rb +198 -0
  40. data/spec/comparator/contains_all_spec.rb +52 -0
  41. data/spec/comparator/contains_all_with_substring_search_spec.rb +41 -0
  42. data/spec/comparator/contains_any_spec.rb +45 -0
  43. data/spec/comparator/contains_any_with_substring_search_spec.rb +35 -0
  44. data/spec/comparator/contains_not_spec.rb +45 -0
  45. data/spec/comparator/contains_not_with_substring_search_spec.rb +28 -0
  46. data/spec/comparator/is_equal_spec.rb +51 -0
  47. data/spec/comparator/is_not_equal_spec.rb +39 -0
  48. data/spec/result_spec.rb +31 -0
  49. data/spec/sample_spec.rb +24 -0
  50. data/spec/spec_helper.rb +38 -0
  51. data/spec/strategies_helper.rb +11 -0
  52. data/spec/testing_helper/testing_helper_spec.rb +27 -0
  53. data/the_array_comparator.gemspec +21 -0
  54. metadata +132 -0
@@ -0,0 +1,41 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ #base class for strategies
8
+ class Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @param [Sample] sample
13
+ # the probe which should be used for the check
14
+ #
15
+ # @return [Object]
16
+ # the strategy
17
+ def initialize(sample=Sample.new)
18
+ @data = sample.data
19
+ @keywords = sample.keywords
20
+ @exceptions = sample.exceptions
21
+ @tag = sample.tag
22
+ end
23
+
24
+ # Check the keywords with the data
25
+ #
26
+ # @note
27
+ # needs to be implemented by the concrete strategy
28
+ # @raise [RuntimeError]
29
+ # error when not implemented by strategy
30
+ def success?
31
+ raise Exceptions::IncompatibleComparator, "The chosen comparator is incompatible, Please check the documentation for comparator strategies on how to build a compatible one."
32
+ end
33
+
34
+ private
35
+
36
+ def warning_unsupported_exceptions
37
+ warn "Exceptions are not supported by this strategy." unless @exceptions.blank?
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,35 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ #strategy contains
8
+ class ContainsAll < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+
16
+ warning_unsupported_exceptions
17
+ end
18
+
19
+ # Check the keywords with the data
20
+ #
21
+ # @return [Boolean]
22
+ # The result of the check
23
+ def success?
24
+ return true if @keywords.blank? and @data.blank?
25
+ return false if @keywords.blank? or @data.blank?
26
+
27
+ if ( @keywords - @data ).blank?
28
+ return true
29
+ else
30
+ return false
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,39 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ # strategy contains substring
8
+ class ContainsAllWithSubstringSearch < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+ end
16
+
17
+ # Check the keywords with the data
18
+ #
19
+ # @return [Boolean]
20
+ # The result of the check
21
+ def success?
22
+ return true if @keywords.blank? and @data.blank?
23
+
24
+ #return true if @data.all? do |line|
25
+ # #does a keyword match and it is not an the exception list
26
+ # binding.pry
27
+ # @keywords.all?{ |k| line[k] } and not @exceptions.any?{ |e| line[e] }
28
+ #end
29
+
30
+ return true if @keywords.all? do |word|
31
+ #does a keyword match and it is not an the exception list
32
+ @data.any?{ |line| line[word] and not @exceptions.any?{ |e| line[e] } }
33
+ end
34
+
35
+ false
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,34 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ #strategy contains
8
+ class ContainsAny < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+
16
+ warning_unsupported_exceptions
17
+ end
18
+
19
+ # Check the keywords with the data
20
+ #
21
+ # @return [Boolean]
22
+ # The result of the check
23
+ def success?
24
+ return true if @keywords.blank? and @data.blank?
25
+
26
+ if ( @keywords & @data ).blank?
27
+ return false
28
+ else
29
+ return true
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ # strategy contains substring
8
+ class ContainsAnyWithSubstringSearch < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+ end
16
+
17
+ # Check the keywords with the data
18
+ #
19
+ # @return [Boolean]
20
+ # The result of the check
21
+ def success?
22
+ return true if @keywords.blank? and @data.blank?
23
+
24
+ return true if @data.any? do |line|
25
+ #does a keyword match and it is not an the exception list
26
+ @keywords.any?{ |k| line[k] } and not @exceptions.any?{ |e| line[e] }
27
+ end
28
+
29
+ false
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ #strategy contains
8
+ class ContainsNot < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+ end
16
+
17
+ # Check the keywords with the data
18
+ #
19
+ # @return [Boolean]
20
+ # The result of the check
21
+ def success?
22
+ return false if @keywords.blank? and @data.blank?
23
+
24
+ if ( @keywords & @data ).blank?
25
+ return true
26
+ else
27
+ return false
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ # strategy not contains substring
8
+ class ContainsNotWithSubstringSearch < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+ end
16
+
17
+ # Check the keywords with the data
18
+ #
19
+ # @return [Boolean]
20
+ # The result of the check
21
+ def success?
22
+ return false if @keywords.blank? and @data.blank?
23
+
24
+ return true if @data.all? do |line|
25
+ #if a keyword is found, check if there's an exception
26
+ @keywords.none?{ |k| line[k] } or @exceptions.any?{ |e| line[e] }
27
+ end
28
+
29
+ false
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ #strategy is equal
8
+ class IsEqual < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+
16
+ warning_unsupported_exceptions
17
+ end
18
+
19
+ # Check the keywords with the data
20
+ #
21
+ # @return [Boolean]
22
+ # The result of the check
23
+ def success?
24
+ return true if @keywords.to_a == @data
25
+
26
+ false
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ #encoding: utf-8
2
+
3
+ # the main module
4
+ module TheArrayComparator
5
+ # the available strategies
6
+ module Strategies
7
+ #strategy is not equal
8
+ class IsNotEqual < Base
9
+
10
+ # Create a new instance of strategy
11
+ #
12
+ # @see Base
13
+ def initialize(sample=Sample.new)
14
+ super
15
+
16
+ warning_unsupported_exceptions
17
+ end
18
+
19
+ # Check the keywords with the data
20
+ #
21
+ # @return [Boolean]
22
+ # The result of the check
23
+ def success?
24
+ return true if @keywords.to_a != @data
25
+
26
+ false
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,63 @@
1
+ module TheArrayComparator
2
+ module TestingHelper
3
+ # Keywords only make sense together with the raw data
4
+ class DataSet
5
+ #@!attribute [rw] keywords
6
+ # keywords which need to be hidden in the raw data
7
+ #
8
+ #@!attribute [rw] raw_data
9
+ # the raw data which should be used to hide the keywords
10
+ attr_accessor :keywords, :raw_data
11
+
12
+ # Create new instance
13
+ #
14
+ # @return [DataSet]
15
+ # the object holding the data
16
+ def initialize(keywords=[],raw_data=[])
17
+ @keywords = keywords
18
+ @raw_data = raw_data
19
+ end
20
+
21
+ # A stripe of data
22
+ #
23
+ # @return [Array]
24
+ # a pice of raw data
25
+ def stripe_of_data
26
+ raw_data.shift(stripe_size)
27
+ end
28
+
29
+ # A tripe of the keywords
30
+ #
31
+ # @return [String,Integer]
32
+ # one keyword
33
+ def stripe_of_keywords
34
+ keywords.shift unless keywords.blank?
35
+ end
36
+
37
+ # The count of the keywords
38
+ # @return [Integer]
39
+ # How many key words are available
40
+ def count_of_keywords
41
+ keywords.size
42
+ end
43
+
44
+ private
45
+
46
+ def divisor
47
+ if count_of_keywords > 0 and count_of_keywords <= count_of_rawdata
48
+ return count_of_keywords
49
+ else
50
+ return 1
51
+ end
52
+ end
53
+
54
+ def stripe_size
55
+ raw_data.size / divisor
56
+ end
57
+
58
+ def count_of_rawdata
59
+ raw_data.size
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,33 @@
1
+ module TheArrayComparator
2
+ module TestingHelper
3
+ class TestData
4
+
5
+ # Create test data instance
6
+ #
7
+ # @return [TestData]
8
+ # the test data object used to generate the test data
9
+ def initialize(dataset)
10
+ @dataset = dataset
11
+ @data = []
12
+ end
13
+
14
+ # Generate the test data
15
+ #
16
+ # @return [Array]
17
+ # the test data
18
+ def generate
19
+ if @data.blank?
20
+ @dataset.count_of_keywords.times do
21
+ @data.concat @dataset.stripe_of_data
22
+ @data << @dataset.stripe_of_keywords
23
+ end
24
+
25
+ #put the rest into the output
26
+ @data.concat @dataset.raw_data
27
+ end
28
+
29
+ @data
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,55 @@
1
+ #the main module
2
+ module TheArrayComparator
3
+ # helper for tests
4
+ module TestingHelper
5
+
6
+ # Generate data for the tests
7
+ #
8
+ # @param [Hash] options
9
+ #
10
+ # @option options [Array] :keywords
11
+ # the keywords which should be hidden in the data
12
+ #
13
+ # @option options [Array] :raw_data
14
+ # the data which should be used to hide the keywords
15
+ #
16
+ # @option options [Integer] :count_of_data
17
+ # how much raw data should be generated if none is given
18
+ #
19
+ # @return [Array]
20
+ # the testdata (raw_data + keywords)
21
+ def generate_testdata(options)
22
+ opts = {
23
+ keywords: [],
24
+ raw_data: [],
25
+ count_of_data: 100,
26
+ }.merge options
27
+
28
+ raw_data = options[:raw_data] || Faker::Lorem.sentences(opts[:count_of_data])
29
+ dataset = DataSet.new(options[:keywords],raw_data)
30
+
31
+ testdata = TestData.new(dataset)
32
+ testdata.generate
33
+ end
34
+ end
35
+ end
36
+
37
+ module Kernel
38
+ #
39
+ # Captures the given stream and returns it:
40
+ #
41
+ # stream = capture(:stdout) { puts 'Cool' }
42
+ # stream # => "Cool\n"
43
+ def capture(stream)
44
+ begin
45
+ stream = stream.to_s
46
+ eval "$#{stream} = StringIO.new"
47
+ yield
48
+ result = eval("$#{stream}").string
49
+ ensure
50
+ eval("$#{stream} = #{stream.upcase}")
51
+ end
52
+
53
+ result
54
+ end
55
+ end
@@ -0,0 +1,6 @@
1
+ #encoding: utf-8
2
+
3
+ #main TheArrayComparator
4
+ module TheArrayComparator
5
+ VERSION = '0.1.1'
6
+ end
@@ -0,0 +1,34 @@
1
+ #encoding: utf-8
2
+
3
+ require 'active_support/core_ext/object/blank'
4
+ require 'set'
5
+ require 'forwardable'
6
+
7
+ require 'the_array_comparator/version'
8
+ require 'the_array_comparator/exceptions'
9
+ require 'the_array_comparator/sample'
10
+ require 'the_array_comparator/check'
11
+ require 'the_array_comparator/result'
12
+ require 'the_array_comparator/strategies/base'
13
+ require 'the_array_comparator/strategies/contains_all_with_substring_search'
14
+ require 'the_array_comparator/strategies/contains_any_with_substring_search'
15
+ require 'the_array_comparator/strategies/contains_all'
16
+ require 'the_array_comparator/strategies/contains_any'
17
+ require 'the_array_comparator/strategies/contains_not_with_substring_search'
18
+ require 'the_array_comparator/strategies/contains_not'
19
+ require 'the_array_comparator/strategies/is_equal'
20
+ require 'the_array_comparator/strategies/is_not_equal'
21
+ require 'the_array_comparator/comparator'
22
+
23
+
24
+ # main module
25
+ module TheArrayComparator
26
+ Comparator.register :contains_all, Strategies::ContainsAll
27
+ Comparator.register :contains_any, Strategies::ContainsAny
28
+ Comparator.register :not_contains, Strategies::ContainsNot
29
+ Comparator.register :contains_all_as_substring, Strategies::ContainsAllWithSubstringSearch
30
+ Comparator.register :contains_any_as_substring, Strategies::ContainsAnyWithSubstringSearch
31
+ Comparator.register :not_contains_substring, Strategies::ContainsNotWithSubstringSearch
32
+ Comparator.register :is_equal, Strategies::IsEqual
33
+ Comparator.register :is_not_equal, Strategies::IsNotEqual
34
+ end
data/script/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.expand_path('../lib', File.dirname(__FILE__))
4
+
5
+ require 'the_array_comparator'
6
+ require 'pry'
7
+
8
+ Pry.start
data/script/terminal ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tmrb'
4
+
5
+ tmux = TmRb::Multiplexer.new
6
+ #creates an empty window
7
+ tmux.new_session(session_name: 'the_array_comparator')
8
+
9
+ tmux.new_window(:name => 'code', :command => "zsh -c 'vim -p lib/**/*.rb'")
10
+ tmux.new_window(:name => 'spec', :command => "zsh -c 'vim -p spec/**/*.rb'")
11
+ tmux.new_window(:name => 'features', :command => "zsh -c 'vim -p features/**/*.{rb,feature}'")
12
+ tmux.start
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe "benchmark for strategies" do
5
+ let(:count_of_lines) { 100000 }
6
+
7
+ describe "strategy contains with substring search" do
8
+ let(:keywords) { %w{ab c d} }
9
+ let(:data) { generate_testdata(keywords: keywords, count_of_data: count_of_lines) }
10
+
11
+ it "is fast", :bm => true do
12
+ comparator = Strategies::ContainsWithSubstringSearch.add_check(data,keywords)
13
+ time_taken = Benchmark.realtime { comparator.success? }
14
+ expect(time_taken).to be < 1
15
+ end
16
+ end
17
+
18
+ describe "strategy contains" do
19
+ let(:keywords) { %w{a c d} }
20
+ let(:data) { generate_testdata(keywords: keywords, count_of_data: count_of_lines) }
21
+
22
+ it "is fast", :bm => true do
23
+ comparator = Strategies::Contains.add_check(data,keywords)
24
+ time_taken = Benchmark.realtime { comparator.success? }
25
+ expect(time_taken).to be < 1
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Check do
4
+ strategy_klass = Class.new do
5
+ def success?
6
+ true
7
+ end
8
+
9
+ def initialize(sample=nil)
10
+ end
11
+ end
12
+
13
+ sample_klass = Class.new do; end
14
+
15
+ it "add a sample and a comparator" do
16
+ Check.new(strategy_klass,sample_klass.new)
17
+ end
18
+
19
+ it "is true if the check is successfull" do
20
+ check = Check.new(strategy_klass,sample_klass.new)
21
+ result = check.success?
22
+ expect(result).to eq(true)
23
+ end
24
+
25
+ it "is able to return the sample of the check" do
26
+ sample = sample_klass.new
27
+ check = Check.new(strategy_klass,sample)
28
+ expect(check.sample).to eq(sample)
29
+ end
30
+ end
@@ -0,0 +1,16 @@
1
+ #enconding: utf-8
2
+ require 'spec_helper'
3
+ require 'strategies_helper'
4
+
5
+ describe Strategies::Base do
6
+
7
+ it "raise an exception if api is not implemented" do
8
+ class TestStrategy < Strategies::Base
9
+ end
10
+
11
+ expect {
12
+ test_strategy = TestStrategy.new
13
+ test_strategy.success?
14
+ }.to raise_error Exceptions::IncompatibleComparator
15
+ end
16
+ end