commendo 0.0.2 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01e2c317e998efe31d72e1a399d1d8eb677854a7
4
- data.tar.gz: fad0b2a2c09333ef31eff3f3aaaf91c7b3d1862f
3
+ metadata.gz: 6882c6ed2001ecae7be9eae066e3f534beeb1559
4
+ data.tar.gz: 0a0982ccc0a17285537b1adfc12bfe854da6c10f
5
5
  SHA512:
6
- metadata.gz: 8d0563d3909815866885f6f654c172f39675c442fb24a7306162090f848e2e50f4161aabf0fcc4f4779e474ff3b5c9902ec8d5c7cdc66db69cd7a3886f17a9bc
7
- data.tar.gz: f05702dd19c5be8b6480ef4a513294c493f7138a2bb2d3c5f329fc6a734a9060660ab168f4d987f830c188142fc6bd5334c0a903b0f45024d7810ba7cb02e284
6
+ metadata.gz: 834aeca013589496b5e6b95a0d5ec7e327fc6192ba57e7dab7c2d8507055013058a96b354b13bb2422c21caa7cce92c0fd5f0011c60d3cb5c202b723eb94dbf4
7
+ data.tar.gz: d773e4c3776f66ba003cf7b7c1327a376e439f8f72480b903d1512db906c27aa55c9f01a052c11a24fbde4f4e90d7bb50b13d6494fbd963ea407d0d4807eb5fd
@@ -1,3 +1,6 @@
1
+ # 0.0.3 / 2014-03-31
2
+ * [FEATURE] Filtering of recommendations based on tags
3
+
1
4
  # 0.0.2 / 2014-03-31
2
5
  * [FEATURE] Weighted groups. Incremental additions. Deletions.
3
6
 
@@ -1,8 +1,9 @@
1
1
  require 'redis'
2
2
  require 'commendo/version'
3
3
  require 'commendo/content_set'
4
+ require 'commendo/tag_set'
4
5
  require 'commendo/weighted_group'
5
6
 
6
7
  module Commendo
7
- # Your code goes here...
8
+
8
9
  end
@@ -2,10 +2,10 @@ module Commendo
2
2
 
3
3
  class ContentSet
4
4
 
5
- attr_accessor :redis, :key_base
5
+ attr_accessor :redis, :key_base, :tag_set
6
6
 
7
- def initialize(redis, key_base)
8
- @redis, @key_base = redis, key_base
7
+ def initialize(redis, key_base, tag_set = nil)
8
+ @redis, @key_base, @tag_set = redis, key_base, tag_set
9
9
  end
10
10
 
11
11
  def add_by_group(group, *resources)
@@ -68,7 +68,19 @@ module Commendo
68
68
  similar_resources.map do |resource|
69
69
  {resource: resource[0], similarity: resource[1].to_f}
70
70
  end
71
+ end
72
+
73
+ def filtered_similar_to(resource, options = {})
74
+ similar = similar_to(resource)
75
+ return similar if options[:include].nil? && options[:exclude].nil?
76
+ similar.delete_if { |s| !options[:exclude].nil? && tags_match(s[:resource], options[:exclude]) }
77
+ similar.delete_if { |s| !options[:include].nil? && !tags_match(s[:resource], options[:include]) }
78
+ similar
79
+ end
71
80
 
81
+ def tags_match(resource, tags)
82
+ resource_tags = tag_set.get(resource)
83
+ (resource_tags & tags).length > 0
72
84
  end
73
85
 
74
86
  def similarity_key(resource)
@@ -0,0 +1,36 @@
1
+ module Commendo
2
+
3
+ class TagSet
4
+
5
+ attr_accessor :redis, :key_base
6
+
7
+ def initialize(redis, key_base)
8
+ @redis, @key_base = redis, key_base
9
+ end
10
+
11
+ def get(resource)
12
+ redis.smembers(resource_key(resource)).sort
13
+ end
14
+
15
+ def add(resource, *tags)
16
+ redis.sadd(resource_key(resource), tags)
17
+ end
18
+
19
+ def set(resource, *tags)
20
+ delete(resource)
21
+ add(resource, *tags)
22
+ end
23
+
24
+ def delete(resource)
25
+ redis.del(resource_key(resource))
26
+ end
27
+
28
+ private
29
+
30
+ def resource_key(resource)
31
+ "#{key_base}:#{resource}"
32
+ end
33
+
34
+ end
35
+ end
36
+
@@ -1,3 +1,3 @@
1
1
  module Commendo
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -66,12 +66,12 @@ module Commendo
66
66
  end
67
67
  cs.calculate_similarity
68
68
  expected = [
69
- { resource: '9', similarity: 0.5 },
70
- { resource: '6', similarity: 0.5 },
71
- { resource: '12', similarity: 0.33333333333333 },
72
- { resource: '3', similarity: 0.25 },
73
- { resource: '21', similarity: 0.16666666666667 },
74
- { resource: '15', similarity: 0.16666666666667 }
69
+ {resource: '9', similarity: 0.5},
70
+ {resource: '6', similarity: 0.5},
71
+ {resource: '12', similarity: 0.33333333333333},
72
+ {resource: '3', similarity: 0.25},
73
+ {resource: '21', similarity: 0.16666666666667},
74
+ {resource: '15', similarity: 0.16666666666667}
75
75
  ]
76
76
  assert_equal expected, cs.similar_to(18)
77
77
  end
@@ -88,8 +88,8 @@ module Commendo
88
88
  end
89
89
  cs.calculate_similarity(0.4)
90
90
  expected = [
91
- { resource: '9', similarity: 0.5 },
92
- { resource: '6', similarity: 0.5 },
91
+ {resource: '9', similarity: 0.5},
92
+ {resource: '6', similarity: 0.5},
93
93
  ]
94
94
  assert_equal expected, cs.similar_to(18)
95
95
  end
@@ -144,16 +144,89 @@ module Commendo
144
144
  assert similar_to(cs, 10, 12)
145
145
  end
146
146
 
147
- def test_accepts_tag_collection
148
- skip
147
+ def test_filters_include_by_tag_collection
148
+ redis = Redis.new(db: 15)
149
+ redis.flushdb
150
+ ts = TagSet.new(redis, 'CommendoTests:tags')
151
+ cs = ContentSet.new(redis, 'CommendoTests', ts)
152
+ (3..23).each do |group|
153
+ (3..23).each do |res|
154
+ cs.add(res, group) if res % group == 0
155
+ ts.add(res, 'mod3') if res.modulo(3).zero?
156
+ ts.add(res, 'mod4') if res.modulo(4).zero?
157
+ ts.add(res, 'mod5') if res.modulo(5).zero?
158
+ end
159
+ end
160
+ cs.calculate_similarity
161
+
162
+ actual = cs.filtered_similar_to(10, include: ['mod5'])
163
+ assert_equal 3, actual.length
164
+ assert contains_resource('5', actual)
165
+ assert contains_resource('15', actual)
166
+ assert contains_resource('20', actual)
167
+
149
168
  end
150
169
 
151
- def test_filters_by_tag_collection
152
- skip
170
+ def test_filters_exclude_by_tag_collection
171
+ redis = Redis.new(db: 15)
172
+ redis.flushdb
173
+ ts = TagSet.new(redis, 'CommendoTests:tags')
174
+ cs = ContentSet.new(redis, 'CommendoTests', ts)
175
+ (3..23).each do |group|
176
+ (3..23).each do |res|
177
+ cs.add(res, group) if res % group == 0
178
+ ts.add(res, 'mod3') if res.modulo(3).zero?
179
+ ts.add(res, 'mod4') if res.modulo(4).zero?
180
+ ts.add(res, 'mod5') if res.modulo(5).zero?
181
+ end
182
+ end
183
+ cs.calculate_similarity
184
+
185
+ actual = cs.filtered_similar_to(10, exclude: ['mod3'])
186
+ assert_equal 2, actual.length
187
+ assert contains_resource('5', actual)
188
+ assert contains_resource('20', actual)
189
+ refute contains_resource('15', actual)
190
+
191
+ end
192
+
193
+ def test_filters_includes_and_exclude_by_tag_collection
194
+ redis = Redis.new(db: 15)
195
+ redis.flushdb
196
+ ts = TagSet.new(redis, 'CommendoTests:tags')
197
+ cs = ContentSet.new(redis, 'CommendoTests', ts)
198
+ (3..23).each do |group|
199
+ (3..23).each do |res|
200
+ cs.add(res, group) if res % group == 0
201
+ ts.add(res, 'mod3') if res.modulo(3).zero?
202
+ ts.add(res, 'mod4') if res.modulo(4).zero?
203
+ ts.add(res, 'mod5') if res.modulo(5).zero?
204
+ end
205
+ end
206
+ cs.calculate_similarity
207
+
208
+ actual = cs.filtered_similar_to(12, include: ['mod4'], exclude: ['mod3', 'mod5'])
209
+ assert_equal 3, actual.length
210
+
211
+ refute contains_resource('6', actual)
212
+ refute contains_resource('18', actual)
213
+ assert contains_resource('4', actual)
214
+ refute contains_resource('3', actual)
215
+ refute contains_resource('9', actual)
216
+ assert contains_resource('8', actual)
217
+ refute contains_resource('21', actual)
218
+ assert contains_resource('16', actual)
219
+ refute contains_resource('15', actual)
220
+ refute contains_resource('20', actual)
221
+
153
222
  end
154
223
 
155
224
  def similar_to(cs, resource, similar)
156
- cs.similar_to(resource).select { |sim| sim[:resource] == "#{similar}" }.length > 0
225
+ contains_resource(similar, cs.similar_to(resource))
226
+ end
227
+
228
+ def contains_resource(resource, similarities)
229
+ similarities.select { |sim| sim[:resource] == "#{resource}" }.length > 0
157
230
  end
158
231
 
159
232
  end
@@ -0,0 +1,48 @@
1
+ gem 'minitest'
2
+ require 'minitest/autorun'
3
+ require 'minitest/pride'
4
+ require 'minitest/mock'
5
+ require 'mocha/setup'
6
+ require 'commendo'
7
+
8
+ module Commendo
9
+
10
+ class TagSetTest < Minitest::Test
11
+
12
+ def test_adds_tags_for_resource
13
+ redis = Redis.new(db: 15)
14
+ redis.flushdb
15
+ ts = TagSet.new(redis, 'TagSetTest')
16
+ assert_equal [], ts.get(1)
17
+ ts.add(1, 'foo', 'bar', 'baz')
18
+ assert_equal ['bar', 'baz','foo'], ts.get(1)
19
+ ts.add(1, 'qux', 'qip')
20
+ assert_equal ['bar', 'baz', 'foo', 'qip', 'qux'], ts.get(1)
21
+ end
22
+
23
+ def test_sets_tags_for_resource
24
+ redis = Redis.new(db: 15)
25
+ redis.flushdb
26
+ ts = TagSet.new(redis, 'TagSetTest')
27
+ assert_equal [], ts.get(1)
28
+ ts.set(1, 'foo', 'bar', 'baz')
29
+ assert_equal ['bar', 'baz', 'foo'], ts.get(1)
30
+ ts.set(1, 'qux', 'qip')
31
+ assert_equal ['qip', 'qux'], ts.get(1)
32
+ end
33
+
34
+ def test_deletes_tags_for_resource
35
+ redis = Redis.new(db: 15)
36
+ redis.flushdb
37
+ ts = TagSet.new(redis, 'TagSetTest')
38
+ ts.set(1, 'foo', 'bar', 'baz')
39
+ ts.set(2, 'qux', 'qip')
40
+ assert_equal ['bar', 'baz', 'foo'], ts.get(1)
41
+ assert_equal ['qip', 'qux'], ts.get(2)
42
+ ts.delete(1)
43
+ assert_equal [], ts.get(1)
44
+ assert_equal ['qip', 'qux'], ts.get(2)
45
+ end
46
+
47
+ end
48
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: commendo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Styles
@@ -111,9 +111,11 @@ files:
111
111
  - lib/commendo.rb
112
112
  - lib/commendo/content_set.rb
113
113
  - lib/commendo/similarity.lua
114
+ - lib/commendo/tag_set.rb
114
115
  - lib/commendo/version.rb
115
116
  - lib/commendo/weighted_group.rb
116
117
  - test/content_set_test.rb
118
+ - test/tag_set_test.rb
117
119
  - test/weighted_group_test.rb
118
120
  homepage: ''
119
121
  licenses:
@@ -141,5 +143,6 @@ specification_version: 4
141
143
  summary: A Jaccard-similarity recommender using Redis sets
142
144
  test_files:
143
145
  - test/content_set_test.rb
146
+ - test/tag_set_test.rb
144
147
  - test/weighted_group_test.rb
145
148
  has_rdoc: