commendo 0.0.5 → 0.0.6

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: d5d32053e7810788416b8a9d1c42937bff79462b
4
- data.tar.gz: aa65282bdfbe68311fdc140fcbbe59dabc029c92
3
+ metadata.gz: 1f16a2f22f2afbdf32e7242ee821fca56ba8c690
4
+ data.tar.gz: c77c52106e8df36b855f41eb2c6bbd0d0f82bbbe
5
5
  SHA512:
6
- metadata.gz: 316b145f9abc4370d0e621e2e374ae9105fe61f9f647b150a1acca82b4818be46bd994eac011cba57d6560bf8c8e5430d0b6a7e09634c313ea09723cd2f35662
7
- data.tar.gz: f9d134bf294c9abd189af50400948d4dc2fed55e5fb925e3f39cc714fa6090cc4c67bac3dd896e0c40bcde730549deebe4b3525d9ec520c6432882beec0e7afa
6
+ metadata.gz: 86cd12a3d567df7dc14bc77767d4297fca094fa4d0987bd8eb6674103c77455afc383a2933a2fa947e75b2ede3b07dd244379bf1b8ce5530b6d0e662c9830868
7
+ data.tar.gz: e327b49f232971ecb94c1e8bbec2e1ebf06673cdc596e2bc1a8722238fbc0316d24d84582d30a39769224288119e764cd473252c73184ee4d1b4fe190b62aea1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # 0.0.6 / 2014-04-01
2
+ * [FEATURE] Weighted groups now accept array of resources and return combined similarity scores
3
+
1
4
  # 0.0.5 / 2014-03-31
2
5
  * [FEATURE] Can now accept array of resources and return combined similarity scores
3
6
 
@@ -86,17 +86,12 @@ module Commendo
86
86
 
87
87
  def filtered_similar_to(resource, options = {})
88
88
  similar = similar_to(resource)
89
- return similar if options[:include].nil? && options[:exclude].nil?
90
- similar.delete_if { |s| !options[:exclude].nil? && tags_match(s[:resource], options[:exclude]) }
91
- similar.delete_if { |s| !options[:include].nil? && !tags_match(s[:resource], options[:include]) }
89
+ return similar if @tag_set.nil? || options[:include].nil? && options[:exclude].nil?
90
+ similar.delete_if { |s| !options[:exclude].nil? && @tag_set.matches(s[:resource], *options[:exclude]) }
91
+ similar.delete_if { |s| !options[:include].nil? && !@tag_set.matches(s[:resource], *options[:include]) }
92
92
  similar
93
93
  end
94
94
 
95
- def tags_match(resource, tags)
96
- resource_tags = tag_set.get(resource)
97
- (resource_tags & tags).length > 0
98
- end
99
-
100
95
  def similarity_key(resource)
101
96
  "#{similar_key_base}:#{resource}"
102
97
  end
@@ -137,7 +132,6 @@ module Commendo
137
132
  "#{key_base}:groups"
138
133
  end
139
134
 
140
-
141
135
  def group_key(group)
142
136
  "#{group_key_base}:#{group}"
143
137
  end
@@ -21,6 +21,11 @@ module Commendo
21
21
  add(resource, *tags)
22
22
  end
23
23
 
24
+ def matches(resource, *tags)
25
+ resource_tags = get(resource)
26
+ (resource_tags & tags).length > 0
27
+ end
28
+
24
29
  def delete(resource)
25
30
  redis.del(resource_key(resource))
26
31
  end
@@ -1,3 +1,3 @@
1
1
  module Commendo
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.6'
3
3
  end
@@ -2,18 +2,21 @@ module Commendo
2
2
 
3
3
  class WeightedGroup
4
4
 
5
- attr_accessor :content_sets, :redis, :key_base
5
+ attr_accessor :content_sets, :redis, :key_base, :tag_set
6
6
 
7
7
  def initialize(redis, key_base, *content_sets)
8
8
  @content_sets, @redis, @key_base = content_sets, redis, key_base
9
9
  end
10
10
 
11
11
  def similar_to(resource)
12
- keys = content_sets.map do |cs|
13
- cs[:cs].similarity_key(resource)
14
- end
15
- weights = content_sets.map do |cs|
16
- cs[:weight]
12
+ resources = resource.kind_of?(Array) ? resource : [resource]
13
+ keys = []
14
+ weights = []
15
+ content_sets.each do |cs|
16
+ resources.each do |resource|
17
+ keys << cs[:cs].similarity_key(resource)
18
+ weights << cs[:weight]
19
+ end
17
20
  end
18
21
  tmp_key = "#{key_base}:tmp:#{SecureRandom.uuid}"
19
22
  redis.zunionstore(tmp_key, keys, weights: weights)
@@ -26,6 +29,14 @@ module Commendo
26
29
 
27
30
  end
28
31
 
32
+ def filtered_similar_to(resource, options = {})
33
+ similar = similar_to(resource)
34
+ return similar if @tag_set.nil? || options[:include].nil? && options[:exclude].nil?
35
+ similar.delete_if { |s| !options[:exclude].nil? && @tag_set.matches(s[:resource], *options[:exclude]) }
36
+ similar.delete_if { |s| !options[:include].nil? && !@tag_set.matches(s[:resource], *options[:include]) }
37
+ similar
38
+ end
39
+
29
40
  end
30
41
 
31
42
  end
data/test/tag_set_test.rb CHANGED
@@ -44,5 +44,26 @@ module Commendo
44
44
  assert_equal ['qip', 'qux'], ts.get(2)
45
45
  end
46
46
 
47
+ def test_matches_tags
48
+ redis = Redis.new(db: 15)
49
+ redis.flushdb
50
+ ts = TagSet.new(redis, 'TagSetTest')
51
+ ts.set(1, 'foo', 'bar', 'baz')
52
+ ts.set(2, 'qux', 'qip')
53
+
54
+ assert ts.matches(1, 'foo')
55
+ assert ts.matches(1, 'bar', 'baz')
56
+ assert ts.matches(1, 'bar', 'baz', 'foo')
57
+ refute ts.matches(1, 'qux')
58
+ refute ts.matches(1, 'qip')
59
+
60
+ refute ts.matches(2, 'foo')
61
+ refute ts.matches(2, 'bar', 'baz')
62
+ refute ts.matches(2, 'bar', 'baz', 'foo')
63
+ assert ts.matches(2, 'qux', 'qip')
64
+ assert ts.matches(2, 'qux')
65
+ assert ts.matches(2, 'qip')
66
+ end
67
+
47
68
  end
48
69
  end
@@ -9,21 +9,36 @@ module Commendo
9
9
 
10
10
  class WeightedGroupTest < Minitest::Test
11
11
 
12
- def test_calls_each_content_set
13
- redis = Redis.new(db: 15)
14
- redis.flushdb
15
- cs1 = ContentSet.new(redis, 'CommendoTests:ContentSet1')
16
- cs2 = ContentSet.new(redis, 'CommendoTests:ContentSet2')
17
- cs3 = ContentSet.new(redis, 'CommendoTests:ContentSet3')
12
+ def setup
13
+ super
14
+ @redis ||= Redis.new(db: 15)
15
+ @redis.flushdb
16
+ @tag_set = TagSet.new(@redis, 'CommendoTests:Tags')
17
+ @cs1 = ContentSet.new(@redis, 'CommendoTests:ContentSet1', @tag_set)
18
+ @cs2 = ContentSet.new(@redis, 'CommendoTests:ContentSet2', @tag_set)
19
+ @cs3 = ContentSet.new(@redis, 'CommendoTests:ContentSet3', @tag_set)
18
20
  (3..23).each do |group|
19
21
  (3..23).each do |res|
20
- cs1.add_by_group(group, res) if (res % group == 0) && (res % 2 == 0)
21
- cs2.add_by_group(group, res) if (res % group == 0) && (res % 3 == 0)
22
- cs3.add_by_group(group, res) if (res % group == 0) && (res % 6 == 0)
22
+ @cs1.add_by_group(group, res) if (res % group == 0) && (res % 2 == 0)
23
+ @cs2.add_by_group(group, res) if (res % group == 0) && (res % 3 == 0)
24
+ @cs3.add_by_group(group, res) if (res % group == 0) && (res % 6 == 0)
25
+ @tag_set.add(res, 'mod3') if res.modulo(3).zero?
26
+ @tag_set.add(res, 'mod4') if res.modulo(4).zero?
27
+ @tag_set.add(res, 'mod5') if res.modulo(5).zero?
28
+ @tag_set.add(res, 'mod7') if res.modulo(7).zero?
23
29
  end
24
30
  end
25
- [cs1, cs2, cs3].each { |cs| cs.calculate_similarity }
26
- weighted_group = WeightedGroup.new(redis, 'CommendoTests:WeightedGroup', { cs: cs1, weight: 1.0 }, { cs: cs2, weight: 10.0 }, { cs: cs3, weight: 100.0 } )
31
+ [@cs1, @cs2, @cs3].each { |cs| cs.calculate_similarity }
32
+ end
33
+
34
+ def test_calls_each_content_set
35
+ weighted_group = WeightedGroup.new(
36
+ @redis,
37
+ 'CommendoTests:WeightedGroup',
38
+ {cs: @cs1, weight: 1.0},
39
+ {cs: @cs2, weight: 10.0},
40
+ {cs: @cs3, weight: 100.0}
41
+ )
27
42
  expected = [
28
43
  {resource: '6', similarity: 55.5},
29
44
  {resource: '12', similarity: 36.963},
@@ -35,12 +50,107 @@ module Commendo
35
50
  assert_equal expected, weighted_group.similar_to(18)
36
51
  end
37
52
 
53
+ def test_filters_include_recommendations
54
+ weighted_group = WeightedGroup.new(
55
+ @redis,
56
+ 'CommendoTests:WeightedGroup',
57
+ {cs: @cs1, weight: 1.0},
58
+ {cs: @cs2, weight: 10.0},
59
+ {cs: @cs3, weight: 100.0}
60
+ )
61
+ expected = [{resource: '15', similarity: 1.67}]
62
+ weighted_group.tag_set = @tag_set
63
+ assert_equal expected, weighted_group.filtered_similar_to(18, include: ['mod5'])
64
+ end
65
+
66
+ def test_filters_exclude_recommendations
67
+ weighted_group = WeightedGroup.new(
68
+ @redis,
69
+ 'CommendoTests:WeightedGroup',
70
+ {cs: @cs1, weight: 1.0},
71
+ {cs: @cs2, weight: 10.0},
72
+ {cs: @cs3, weight: 100.0}
73
+ )
74
+ expected = [
75
+ {resource: '6', similarity: 55.5},
76
+ {resource: '12', similarity: 36.963},
77
+ {resource: '9', similarity: 5.0},
78
+ {resource: '3', similarity: 2.5}
79
+ ]
80
+ weighted_group.tag_set = @tag_set
81
+ assert_equal expected, weighted_group.filtered_similar_to(18, exclude: ['mod5', 'mod7'])
82
+ end
83
+
84
+ def test_filters_include_and_exclude_recommendations
85
+ weighted_group = WeightedGroup.new(
86
+ @redis,
87
+ 'CommendoTests:WeightedGroup',
88
+ {cs: @cs1, weight: 100.0},
89
+ {cs: @cs2, weight: 10.0},
90
+ {cs: @cs3, weight: 1.0}
91
+ )
92
+ expected = [
93
+ {resource: '16', similarity: 66.7},
94
+ {resource: '4', similarity: 50.0},
95
+ {resource: '12', similarity: 20.0}
96
+ ]
97
+ weighted_group.tag_set = @tag_set
98
+ assert_equal expected, weighted_group.filtered_similar_to(8, include: ['mod4'], exclude: ['mod5'])
99
+ end
100
+
101
+ def test_similar_to_mutliple_items
102
+ weighted_group = WeightedGroup.new(
103
+ @redis,
104
+ 'CommendoTests:WeightedGroup',
105
+ {cs: @cs1, weight: 100.0},
106
+ {cs: @cs2, weight: 10.0},
107
+ {cs: @cs3, weight: 1.0}
108
+ )
109
+ expected = [
110
+ {resource: '12', similarity: 83.0},
111
+ {resource: '18', similarity: 58.0},
112
+ {resource: '8', similarity: 50.0},
113
+ {resource: '16', similarity: 33.3},
114
+ {resource: '20', similarity: 25.0},
115
+ {resource: '9', similarity: 8.33},
116
+ {resource: '21', similarity: 5.83},
117
+ {resource: '15', similarity: 5.83},
118
+ {resource: '6', similarity: 5.0},
119
+ {resource: '3', similarity: 5.0}
120
+ ]
121
+ weighted_group.tag_set = @tag_set
122
+ assert_equal expected, weighted_group.similar_to([3,4,5,6,7])
123
+ end
124
+
125
+ def test_filtered_similar_to_mutliple_items
126
+ weighted_group = WeightedGroup.new(
127
+ @redis,
128
+ 'CommendoTests:WeightedGroup',
129
+ {cs: @cs1, weight: 100.0},
130
+ {cs: @cs2, weight: 10.0},
131
+ {cs: @cs3, weight: 1.0}
132
+ )
133
+ expected = [
134
+ {resource: '12', similarity: 83.0},
135
+ #{resource: '18', similarity: 58.0},
136
+ {resource: '8', similarity: 50.0},
137
+ {resource: '16', similarity: 33.3},
138
+ #{resource: '20', similarity: 25.0},
139
+ #{resource: '9', similarity: 8.33},
140
+ #{resource: '21', similarity: 5.83},
141
+ #{resource: '15', similarity: 5.83},
142
+ #{resource: '6', similarity: 5.0},
143
+ #{resource: '3', similarity: 5.0}
144
+ ]
145
+ weighted_group.tag_set = @tag_set
146
+ assert_equal expected, weighted_group.filtered_similar_to([3,4,5,6,7], include: ['mod4'], exclude: ['mod5'])
147
+ end
148
+
38
149
  def test_precalculates
39
150
  skip
40
151
  end
41
152
 
42
153
 
43
-
44
154
  end
45
155
 
46
156
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: commendo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Styles
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-31 00:00:00.000000000 Z
11
+ date: 2014-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis