picky 2.1.2 → 2.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.
Files changed (82) hide show
  1. data/{lib → aux}/picky/cli.rb +50 -38
  2. data/bin/picky +1 -1
  3. data/lib/picky/application.rb +5 -2
  4. data/lib/picky/index/base.rb +88 -25
  5. data/lib/picky/index/memory.rb +8 -8
  6. data/lib/picky/index/redis.rb +8 -8
  7. data/lib/picky/index_bundle.rb +2 -2
  8. data/lib/picky/indexing/indexes.rb +6 -6
  9. data/lib/picky/internals/calculations/location.rb +54 -42
  10. data/lib/picky/internals/index/backend.rb +21 -21
  11. data/lib/picky/internals/index/file/text.rb +11 -11
  12. data/lib/picky/internals/index/files.rb +6 -6
  13. data/lib/picky/internals/index/redis.rb +14 -14
  14. data/lib/picky/internals/indexed/bundle/base.rb +2 -2
  15. data/lib/picky/internals/indexed/bundle/redis.rb +3 -3
  16. data/lib/picky/internals/indexed/category.rb +8 -9
  17. data/lib/picky/internals/indexed/wrappers/bundle/calculation.rb +25 -23
  18. data/lib/picky/internals/indexed/wrappers/bundle/location.rb +36 -34
  19. data/lib/picky/internals/indexed/wrappers/bundle/wrapper.rb +35 -33
  20. data/lib/picky/internals/indexed/wrappers/category/location.rb +27 -0
  21. data/lib/picky/internals/indexers/base.rb +28 -0
  22. data/lib/picky/internals/indexers/parallel.rb +64 -0
  23. data/lib/picky/internals/indexers/serial.rb +20 -29
  24. data/lib/picky/internals/indexing/bundle/base.rb +2 -2
  25. data/lib/picky/internals/indexing/bundle/super_base.rb +3 -3
  26. data/lib/picky/internals/indexing/category.rb +30 -27
  27. data/lib/picky/internals/indexing/index.rb +82 -27
  28. data/lib/picky/internals/indexing/wrappers/category/location.rb +27 -0
  29. data/lib/picky/internals/query/indexes.rb +1 -1
  30. data/lib/picky/internals/query/qualifiers.rb +7 -6
  31. data/lib/picky/internals/query/weights.rb +6 -0
  32. data/lib/picky/internals/shared/category.rb +52 -0
  33. data/lib/picky/internals/tokenizers/base.rb +1 -1
  34. data/lib/picky/internals/tokenizers/location.rb +54 -0
  35. data/lib/picky/loader.rb +16 -3
  36. data/lib/picky/no_source_specified_exception.rb +3 -0
  37. data/lib/picky/search.rb +44 -5
  38. data/lib/picky/sources/base.rb +2 -2
  39. data/lib/picky/sources/couch.rb +1 -1
  40. data/lib/picky/sources/csv.rb +1 -1
  41. data/lib/picky/sources/db.rb +9 -9
  42. data/lib/picky/sources/delicious.rb +1 -1
  43. data/lib/picky/sources/wrappers/base.rb +12 -13
  44. data/lib/picky/sources/wrappers/location.rb +24 -54
  45. data/lib/tasks/search.rake +4 -5
  46. data/lib/tasks/todo.rake +1 -1
  47. data/spec/{lib → aux/picky}/cli_spec.rb +13 -8
  48. data/spec/lib/application_spec.rb +21 -16
  49. data/spec/lib/index/base_spec.rb +74 -27
  50. data/spec/lib/index/redis_spec.rb +1 -1
  51. data/spec/lib/index_bundle_spec.rb +1 -1
  52. data/spec/lib/indexing/indexes_spec.rb +5 -5
  53. data/spec/lib/internals/calculations/location_spec.rb +14 -3
  54. data/spec/lib/internals/index/files_spec.rb +2 -3
  55. data/spec/lib/internals/index/redis_spec.rb +122 -49
  56. data/spec/lib/internals/indexed/bundle/memory_spec.rb +4 -6
  57. data/spec/lib/internals/indexed/bundle/redis_spec.rb +2 -3
  58. data/spec/lib/internals/indexed/wrappers/bundle/calculation_spec.rb +3 -3
  59. data/spec/lib/internals/indexed/wrappers/bundle/wrapper_spec.rb +3 -3
  60. data/spec/lib/internals/indexers/parallel_spec.rb +36 -0
  61. data/spec/lib/internals/indexers/serial_spec.rb +6 -14
  62. data/spec/lib/internals/indexing/bundle/memory_partial_generation_speed_spec.rb +2 -3
  63. data/spec/lib/internals/indexing/bundle/memory_spec.rb +5 -6
  64. data/spec/lib/internals/indexing/bundle/redis_spec.rb +5 -6
  65. data/spec/lib/internals/indexing/category_spec.rb +21 -6
  66. data/spec/lib/internals/indexing/index_spec.rb +43 -7
  67. data/spec/lib/query/indexes_spec.rb +1 -1
  68. data/spec/lib/search_spec.rb +51 -2
  69. data/spec/lib/sources/couch_spec.rb +6 -6
  70. data/spec/lib/sources/csv_spec.rb +4 -4
  71. data/spec/lib/sources/db_spec.rb +13 -14
  72. data/spec/lib/sources/delicious_spec.rb +3 -3
  73. data/spec/lib/sources/wrappers/base_spec.rb +9 -10
  74. data/spec/lib/sources/wrappers/location_spec.rb +11 -23
  75. metadata +14 -15
  76. data/lib/picky/auxiliary/terminal.rb +0 -219
  77. data/lib/picky/internals/configuration/index.rb +0 -67
  78. data/lib/picky/internals/indexers/no_source_specified_error.rb +0 -7
  79. data/lib/picky/internals/indexing/categories.rb +0 -46
  80. data/spec/lib/auxiliary/terminal_spec.rb +0 -150
  81. data/spec/lib/internals/configuration/index_spec.rb +0 -80
  82. data/spec/lib/internals/indexing/categories_spec.rb +0 -49
@@ -19,7 +19,7 @@ module Picky
19
19
 
20
20
  class Base
21
21
  def usage name, params
22
- puts "Usage\n picky #{name} #{params_to_s(params)}"
22
+ puts "Usage:\n picky #{name} #{params_to_s(params)}"
23
23
  end
24
24
  # String params are optional, Symbol params aren't.
25
25
  #
@@ -27,25 +27,21 @@ module Picky
27
27
  params.map { |param| param.respond_to?(:to_str) ? "[#{param}]" : param }.join(' ') if params
28
28
  end
29
29
  end
30
- class Statistics < Base
30
+ class Generate < Base
31
31
  def execute name, args, params
32
- relative_log_file = args.shift
33
- port = args.shift
34
-
35
- usage(name, params) || exit(1) unless relative_log_file
36
-
37
- ENV['PICKY_LOG_FILE'] = File.expand_path relative_log_file
38
- ENV['PICKY_STATISTICS_PORT'] = port
39
-
40
- begin
41
- require 'picky-statistics'
42
- rescue LoadError => e
43
- require 'picky/extensions/object'
44
- warn_gem_missing 'picky-statistics', 'the Picky statistics'
45
- exit 1
46
- end
32
+ Kernel.system "picky-generate #{args.join(' ')}"
33
+ end
34
+ end
35
+ class Help < Base
36
+ # Displays usage information.
37
+ #
38
+ def execute name, args, params
39
+ commands = Picky::CLI.mapping.map do |command, object_and_params|
40
+ _, *params = object_and_params
41
+ " picky #{command} #{params_to_s(params)}"
42
+ end.join(?\n)
47
43
 
48
- require 'picky-statistics/application/app'
44
+ Kernel.puts "Possible commands:\n#{commands}\n"
49
45
  end
50
46
  end
51
47
  class Live < Base
@@ -58,32 +54,47 @@ module Picky
58
54
  ENV['PICKY_LIVE_URL'] = url
59
55
  ENV['PICKY_LIVE_PORT'] = port
60
56
 
61
- begin
62
- require 'picky-live'
63
- rescue LoadError => e
64
- require 'picky/extensions/object'
65
- warn_gem_missing 'picky-live', 'the Picky Live Interface'
66
- exit 1
67
- end
68
-
57
+ require 'picky-live'
69
58
  require 'picky-live/application/app'
59
+ rescue LoadError => e
60
+ require 'picky/extensions/object'
61
+ warn_gem_missing 'picky-live', 'the Picky Live Interface'
62
+ exit 1
70
63
  end
71
64
  end
72
- class Generate < Base
65
+ class Search < Base
73
66
  def execute name, args, params
74
- Kernel.system "picky-generate #{args.join(' ')}"
67
+ url_or_path = args.shift
68
+ ids = args.shift
69
+
70
+ usage(name, params) || exit(1) unless url_or_path
71
+
72
+ require 'picky-client'
73
+ require 'picky-client/aux/terminal'
74
+ terminal = Terminal.new url_or_path, ids
75
+ terminal.run
76
+ rescue LoadError => e
77
+ require 'picky/extensions/object'
78
+ warn_gem_missing 'picky-client', 'the Picky client'
79
+ exit 1
75
80
  end
76
81
  end
77
- class Help < Base
78
- # Displays usage information.
79
- #
82
+ class Statistics < Base
80
83
  def execute name, args, params
81
- commands = Picky::CLI.mapping.map do |command, object_and_params|
82
- _, *params = object_and_params
83
- " picky #{command} #{params_to_s(params)}"
84
- end.join(?\n)
84
+ relative_log_file = args.shift
85
+ port = args.shift
85
86
 
86
- Kernel.puts "Possible commands:\n#{commands}\n"
87
+ usage(name, params) || exit(1) unless relative_log_file
88
+
89
+ ENV['PICKY_LOG_FILE'] = File.expand_path relative_log_file
90
+ ENV['PICKY_STATISTICS_PORT'] = port
91
+
92
+ require 'picky-statistics'
93
+ require 'picky-statistics/application/app'
94
+ rescue LoadError => e
95
+ require 'picky/extensions/object'
96
+ warn_gem_missing 'picky-statistics', 'the Picky statistics'
97
+ exit 1
87
98
  end
88
99
  end
89
100
 
@@ -92,8 +103,9 @@ module Picky
92
103
  @@mapping = {
93
104
  :generate => [Generate, :'{sinatra_client,unicorn_server,empty_unicorn_server}', :'app_directory_name'],
94
105
  :help => [Help],
95
- :stats => [Statistics, :'logfile (e.g. log/search.log)', 'port (default: 4567)'],
96
- :live => [Live, 'host:port/path (default: localhost:8080/admin)', 'port (default: 4568)']
106
+ :live => [Live, 'host:port/path (default: localhost:8080/admin)', 'port (default: 4568)'],
107
+ :search => [Search, :url_or_path, 'amount of ids (default 20)'],
108
+ :stats => [Statistics, :'logfile (e.g. log/search.log)', 'port (default: 4567)']
97
109
  }
98
110
  def self.mapping
99
111
  @@mapping
data/bin/picky CHANGED
@@ -5,7 +5,7 @@ begin
5
5
  require 'picky/cli'
6
6
  rescue LoadError => e
7
7
  require 'rubygems'
8
- picky_path = File.expand_path '../../lib', __FILE__
8
+ picky_path = File.expand_path '../../aux', __FILE__
9
9
  $:.unshift(picky_path) if File.directory?(picky_path) && !$:.include?(picky_path)
10
10
  require 'picky/cli'
11
11
  end
@@ -152,16 +152,19 @@ class Application
152
152
  # Returns a configured tokenizer that
153
153
  # is used for indexing by default.
154
154
  #
155
- def default_indexing options = {}
155
+ def indexing options = {}
156
156
  Internals::Tokenizers::Index.default = Internals::Tokenizers::Index.new(options)
157
157
  end
158
+ alias default_indexing indexing
158
159
 
159
160
  # Returns a configured tokenizer that
160
161
  # is used for querying by default.
161
162
  #
162
- def default_querying options = {}
163
+ def searching options = {}
163
164
  Internals::Tokenizers::Query.default = Internals::Tokenizers::Query.new(options)
164
165
  end
166
+ alias default_querying searching
167
+ alias querying searching
165
168
 
166
169
  # Routes.
167
170
  #
@@ -9,29 +9,36 @@ module Index
9
9
  #
10
10
  class Base
11
11
 
12
- attr_reader :name, :indexing, :indexed
12
+ attr_reader :name
13
13
 
14
14
  # Create a new index with a given source.
15
15
  #
16
16
  # === Parameters
17
17
  # * name: A name that will be used for the index directory and in the Picky front end.
18
- # * source: Where the data comes from, e.g. Sources::CSV.new(...)
18
+ # * source: Where the data comes from, e.g. Sources::CSV.new(...). Optional, can be defined in the block using #source.
19
19
  #
20
20
  # === Options
21
21
  # * result_identifier: Use if you'd like a different identifier/name in the results than the name of the index.
22
22
  # * after_indexing: As of this writing only used in the db source. Executes the given after_indexing as SQL after the indexing process.
23
+ # * tokenizer: The tokenizer to use for this index.
23
24
  #
24
- # Example:
25
+ # Examples:
25
26
  # my_index = Index::Memory.new(:my_index, some_source) do
26
- # define_category :bla
27
+ # category :bla
28
+ # end
29
+ #
30
+ # my_index = Index::Memory.new(:my_index) do
31
+ # source Sources::CSV.new(file: 'data/index.csv')
32
+ # category :bla
27
33
  # end
28
34
  #
29
35
  #
30
- def initialize name, source, options = {}
31
- check name, source
36
+ def initialize name, options = {}
37
+ check_name name
38
+ @name = name.to_sym
32
39
 
33
- @name = name.to_sym
34
- @indexing = Internals::Indexing::Index.new name, source, options
40
+ check_options options
41
+ @indexing = Internals::Indexing::Index.new name, options
35
42
  @indexed = Internals::Indexed::Index.new name, options
36
43
 
37
44
  # Centralized registry.
@@ -41,37 +48,97 @@ module Index
41
48
  #
42
49
  #
43
50
  instance_eval(&Proc.new) if block_given?
51
+
52
+ check_source internal_indexing.source
53
+ end
54
+ def internal_indexing
55
+ @indexing
56
+ end
57
+ def internal_indexed
58
+ @indexed
44
59
  end
45
60
  #
46
61
  # Since this is an API, we fail hard quickly.
47
62
  #
48
- def check name, source
63
+ def check_name name
49
64
  raise ArgumentError.new(<<-NAME
65
+
66
+
50
67
  The index identifier (you gave "#{name}") for Index::Memory/Index::Redis should be a String/Symbol,
51
68
  Examples:
52
69
  Index::Memory.new(:my_cool_index, ...) # Recommended
53
70
  Index::Redis.new("a-redis-index", ...)
54
71
  NAME
72
+
73
+
55
74
  ) unless name.respond_to?(:to_sym)
75
+ end
76
+ def check_options options
77
+ raise ArgumentError.new(<<-OPTIONS
78
+
79
+
80
+ Sources are not passed in as second parameter for #{self.class.name} anymore, but either
81
+ * as :source option:
82
+ #{self.class.name}.new(#{name.inspect}, source: #{options})
83
+ or
84
+ * given to the #source method inside the config block:
85
+ #{self.class.name}.new(#{name.inspect}) do
86
+ source #{options}
87
+ end
88
+
89
+ Sorry about that breaking change (in 2.2.0), didn't want to go to 3.0.0 yet!
90
+
91
+ All the best
92
+ -- Picky
93
+
94
+
95
+ OPTIONS
96
+ ) unless options.respond_to?(:[])
97
+ end
98
+ def check_source source
56
99
  raise ArgumentError.new(<<-SOURCE
57
- The index "#{name}" should use a data source that responds to the method #harvest, which yields(id, text).
100
+
101
+
102
+ The index "#{name}" should use a data source that responds to either the method #each, or the method #harvest, which yields(id, text).
58
103
  Or it could use one of the built-in sources:
59
104
  Sources::#{(Sources.constants - [:Base, :Wrappers, :NoCSVFileGiven, :NoCouchDBGiven]).join(',
60
105
  Sources::')}
106
+
107
+
61
108
  SOURCE
62
- ) unless source.respond_to?(:harvest)
109
+ ) unless source.respond_to?(:each) || source.respond_to?(:harvest)
63
110
  end
64
111
 
65
112
  def to_stats
66
113
  stats = <<-INDEX
67
114
  #{name} (#{self.class}):
68
- #{"source: #{indexing.source}".indented_to_s}
69
- #{"categories: #{indexing.categories.categories.map(&:name).join(', ')}".indented_to_s}
115
+ #{"source: #{internal_indexing.source}".indented_to_s}
116
+ #{"categories: #{internal_indexing.categories.map(&:name).join(', ')}".indented_to_s}
70
117
  INDEX
71
- stats << " result identifier: \"#{indexed.result_identifier}\"".indented_to_s unless indexed.result_identifier.to_s == indexed.name.to_s
118
+ stats << " result identifier: \"#{internal_indexed.result_identifier}\"".indented_to_s unless internal_indexed.result_identifier.to_s == internal_indexed.name.to_s
72
119
  stats
73
120
  end
74
121
 
122
+ # Define an index tokenizer on the index.
123
+ #
124
+ # Parameters are the exact same as for the default_indexing.
125
+ #
126
+ def define_indexing options = {}
127
+ internal_indexing.define_indexing options
128
+ end
129
+ alias indexing define_indexing
130
+
131
+ # Define a source on the index.
132
+ #
133
+ # Parameter is a source, either one of the standard sources or
134
+ # anything responding to #each and returning objects that
135
+ # respond to id and the category names (or the category from option).
136
+ #
137
+ def define_source source
138
+ internal_indexing.define_source source
139
+ end
140
+ alias source define_source
141
+
75
142
  # Defines a searchable category on the index.
76
143
  #
77
144
  # === Parameters
@@ -88,8 +155,8 @@ INDEX
88
155
  def define_category category_name, options = {}
89
156
  category_name = category_name.to_sym
90
157
 
91
- indexing_category = indexing.define_category category_name, options
92
- indexed_category = indexed.define_category category_name, options
158
+ indexing_category = internal_indexing.define_category category_name, options
159
+ indexed_category = internal_indexed.define_category category_name, options
93
160
 
94
161
  yield indexing_category, indexed_category if block_given?
95
162
 
@@ -157,22 +224,18 @@ INDEX
157
224
  # * ... all options of #define_category.
158
225
  #
159
226
  def define_ranged_category category_name, range, options = {}
160
- precision = options[:precision]
227
+ precision = options[:precision] || 1
161
228
 
162
229
  options = { partial: Partial::None.new }.merge options
163
230
 
164
- define_category category_name, options do |indexing, indexed|
165
- indexing.source = Sources::Wrappers::Location.new indexing, grid: range, precision: precision
166
- indexing.tokenizer = Internals::Tokenizers::Index.new
167
-
168
- exact_bundle = Indexed::Wrappers::Bundle::Location.new indexed.exact, grid: range, precision: precision
169
- indexed.exact = exact_bundle
170
- indexed.partial = exact_bundle # A partial token also uses the exact index.
231
+ define_category category_name, options do |indexing_category, indexed_category|
232
+ Internals::Indexing::Wrappers::Category::Location.install_on indexing_category, range, precision
233
+ Internals::Indexed::Wrappers::Category::Location.install_on indexed_category, range, precision
171
234
  end
172
235
  end
173
236
  alias ranged_category define_ranged_category
174
237
 
175
- # HIGHLY EXPERIMENTAL Not correctly working yet. Try it if you feel "beta".
238
+ # HIGHLY EXPERIMENTAL Not correctly working yet. Try it if you feel "beta".
176
239
  #
177
240
  # Also a range search see #define_ranged_category, but on the earth's surface.
178
241
  #
@@ -1,9 +1,9 @@
1
1
  module Index
2
-
2
+
3
3
  # An index that is persisted in files, loaded at startup and kept in memory at runtime.
4
4
  #
5
5
  class Memory < Base
6
-
6
+
7
7
  # Create a new memory index for indexing and for querying.
8
8
  #
9
9
  # Parameters:
@@ -14,15 +14,15 @@ module Index
14
14
  # * source: The source the data comes from. See Sources::Base.
15
15
  #
16
16
  # Options:
17
- # * result_identifier: Use if you'd like a different identifier/name in the results JSON than the name of the index.
17
+ # * result_identifier: Use if you'd like a different identifier/name in the results JSON than the name of the index.
18
18
  #
19
- def initialize name, source, options = {}
19
+ def initialize name, options = {}
20
+ super name, options
21
+
20
22
  options[:indexing_bundle_class] ||= Internals::Indexing::Bundle::Memory
21
23
  options[:indexed_bundle_class] ||= Internals::Indexed::Bundle::Memory
22
-
23
- super name, source, options
24
24
  end
25
-
25
+
26
26
  end
27
-
27
+
28
28
  end
@@ -1,9 +1,9 @@
1
1
  module Index
2
-
2
+
3
3
  # An index that is persisted in Redis.
4
4
  #
5
5
  class Redis < Base
6
-
6
+
7
7
  # Create a new Redis index for indexing and for querying.
8
8
  #
9
9
  # Parameters:
@@ -14,15 +14,15 @@ module Index
14
14
  # * source: The source the data comes from. See Sources::Base.
15
15
  #
16
16
  # Options:
17
- # * result_identifier: Use if you'd like a different identifier/name in the results JSON than the name of the index.
17
+ # * result_identifier: Use if you'd like a different identifier/name in the results JSON than the name of the index.
18
18
  #
19
- def initialize name, source, options = {}
19
+ def initialize name, options = {}
20
+ super name, options
21
+
20
22
  options[:indexing_bundle_class] ||= Internals::Indexing::Bundle::Redis
21
23
  options[:indexed_bundle_class] ||= Internals::Indexed::Bundle::Redis
22
-
23
- super name, source, options
24
24
  end
25
-
25
+
26
26
  end
27
-
27
+
28
28
  end
@@ -37,8 +37,8 @@ class IndexBundle # :nodoc:all
37
37
  self.indexes << index
38
38
  self.index_mapping[index.name] = index
39
39
 
40
- indexing.register index.indexing
41
- indexed.register index.indexed
40
+ indexing.register index.internal_indexing
41
+ indexed.register index.internal_indexed
42
42
  end
43
43
 
44
44
  def [] name
@@ -47,8 +47,8 @@ module Indexing # :nodoc:all
47
47
  # Run indexing/caching forked.
48
48
  #
49
49
  Cores.forked self.indexes, { randomly: randomly } do |an_index|
50
- an_index.index
51
- an_index.cache
50
+ an_index.index!
51
+ an_index.cache!
52
52
  end
53
53
 
54
54
  timed_exclaim "Indexing finished."
@@ -60,8 +60,8 @@ module Indexing # :nodoc:all
60
60
  take_snapshot
61
61
 
62
62
  self.indexes.each do |an_index|
63
- an_index.index
64
- an_index.cache
63
+ an_index.index!
64
+ an_index.cache!
65
65
  end
66
66
  end
67
67
 
@@ -69,7 +69,7 @@ module Indexing # :nodoc:all
69
69
  #
70
70
  def generate_index_only index_name, category_name = nil
71
71
  found = find index_name, category_name
72
- found.index if found
72
+ found.index! if found
73
73
  end
74
74
  # Generate only the cache for the given index:category pair.
75
75
  #
@@ -88,7 +88,7 @@ module Indexing # :nodoc:all
88
88
 
89
89
  return index unless category_name
90
90
 
91
- found = index.categories.find category_name
91
+ found = index.find category_name
92
92
  return found if found
93
93
  end
94
94
 
@@ -1,47 +1,59 @@
1
- module Calculations # :nodoc:all
2
-
3
- # A location calculation recalculates a 1-d location
4
- # to the Picky internal 1-d "grid".
5
- #
6
- # For example, if you have a location x == 12.3456,
7
- # it will be recalculated into 3, if the minimum is 9
8
- # and the gridlength is 1.
9
- #
10
- class Location
11
-
12
- attr_reader :minimum
13
-
14
- def initialize user_grid, precision = nil
15
- @user_grid = user_grid
16
- @precision = precision || 1
17
- @grid = @user_grid / (@precision + 0.5)
18
- end
19
-
20
- def minimum= minimum
21
- # Add a margin of 1 user grid.
22
- #
23
- minimum -= @user_grid
24
-
25
- # Add plus 1 grid so that the index key never falls on 0.
26
- # Why? to_i maps by default to 0.
27
- #
28
- minimum -= @grid
29
-
30
- @minimum = minimum
31
- end
32
-
1
+ module Internals
2
+ module Calculations # :nodoc:all
3
+
4
+ # A location calculation recalculates a 1-d location
5
+ # to the Picky internal 1-d "grid".
33
6
  #
7
+ # For example, if you have a location x == 12.3456,
8
+ # it will be recalculated into 3, if the minimum is 9
9
+ # and the gridlength is 1.
34
10
  #
35
- def add_margin length
36
- @minimum -= length
37
- end
38
-
39
- #
40
- #
41
- def recalculate location
42
- ((location - @minimum) / @grid).floor
11
+ class Location
12
+
13
+ attr_reader :minimum, :precision, :grid
14
+
15
+ def initialize user_grid, precision = nil
16
+ @user_grid = user_grid
17
+ @precision = precision || 1
18
+ @grid = @user_grid / (@precision + 0.5)
19
+ end
20
+
21
+ def minimum= minimum
22
+ # Add a margin of 1 user grid.
23
+ #
24
+ minimum -= @user_grid
25
+
26
+ # Add plus 1 grid so that the index key never falls on 0.
27
+ # Why? to_i maps by default to 0.
28
+ #
29
+ minimum -= @grid
30
+
31
+ @minimum = minimum
32
+ end
33
+
34
+ #
35
+ #
36
+ def add_margin length
37
+ @minimum -= length
38
+ end
39
+
40
+ #
41
+ #
42
+ def recalculated_range location
43
+ range recalculate(location)
44
+ end
45
+ #
46
+ #
47
+ def range around_location
48
+ (around_location - @precision)..(around_location + @precision)
49
+ end
50
+ #
51
+ #
52
+ def recalculate location
53
+ ((location - @minimum) / @grid).floor
54
+ end
55
+
43
56
  end
44
-
57
+
45
58
  end
46
-
47
59
  end
@@ -1,29 +1,29 @@
1
1
  module Internals
2
-
2
+
3
3
  module Index
4
-
4
+
5
5
  class Backend
6
-
6
+
7
7
  attr_reader :bundle_name
8
8
  attr_reader :prepared, :index, :weights, :similarity, :configuration
9
-
10
- delegate :index_name, :category_name, :to => :@config
11
-
12
- def initialize bundle_name, config
9
+
10
+ delegate :index_name, :category_name, :to => :@category
11
+
12
+ def initialize bundle_name, category
13
13
  @bundle_name = bundle_name
14
- @config = config
15
- @prepared = File::Text.new config.prepared_index_path
14
+ @category = category
15
+ @prepared = File::Text.new category.prepared_index_path
16
16
  end
17
-
17
+
18
18
  # Delegators.
19
19
  #
20
-
20
+
21
21
  # Retrieving data.
22
22
  #
23
23
  def retrieve &block
24
24
  prepared.retrieve &block
25
25
  end
26
-
26
+
27
27
  # Dumping.
28
28
  #
29
29
  def dump_index index_hash
@@ -38,7 +38,7 @@ module Internals
38
38
  def dump_configuration configuration_hash
39
39
  configuration.dump configuration_hash
40
40
  end
41
-
41
+
42
42
  # Loading.
43
43
  #
44
44
  def load_index
@@ -53,7 +53,7 @@ module Internals
53
53
  def load_configuration
54
54
  configuration.load
55
55
  end
56
-
56
+
57
57
  # Cache ok?
58
58
  #
59
59
  def index_cache_ok?
@@ -65,7 +65,7 @@ module Internals
65
65
  def weights_cache_ok?
66
66
  weights.cache_ok?
67
67
  end
68
-
68
+
69
69
  # Cache small?
70
70
  #
71
71
  def index_cache_small?
@@ -77,7 +77,7 @@ module Internals
77
77
  def weights_cache_small?
78
78
  weights.cache_small?
79
79
  end
80
-
80
+
81
81
  # Copies the indexes to the "backup" directory.
82
82
  #
83
83
  def backup
@@ -86,7 +86,7 @@ module Internals
86
86
  similarity.backup
87
87
  configuration.backup
88
88
  end
89
-
89
+
90
90
  # Restores the indexes from the "backup" directory.
91
91
  #
92
92
  def restore
@@ -95,7 +95,7 @@ module Internals
95
95
  similarity.restore
96
96
  configuration.restore
97
97
  end
98
-
98
+
99
99
  # Delete all index files.
100
100
  #
101
101
  def delete
@@ -104,9 +104,9 @@ module Internals
104
104
  similarity.delete
105
105
  configuration.delete
106
106
  end
107
-
107
+
108
108
  end
109
-
109
+
110
110
  end
111
-
111
+
112
112
  end