commendo 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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