spot 2.0.1 → 2.0.4

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.
@@ -2,10 +2,10 @@
2
2
  require "spot/song"
3
3
  require "spot/artist"
4
4
  require "spot/album"
5
+ require "spot/prime"
5
6
  require "spot/clean"
6
7
  require "json"
7
8
  require "rest-client"
8
- require "levenshteinish"
9
9
  require "charlock_holmes/string"
10
10
  require "yaml"
11
11
  require "uri"
@@ -96,53 +96,15 @@ module Spot
96
96
  end
97
97
 
98
98
  def result
99
- @prime ? results.sort_by do |res|
100
- res.popularity
101
- end.reverse[0..6].map do |r|
102
- song, artist = type_of(r)
103
-
104
- match = clean!([song, artist].join(" ")).split(/\s+/)
105
- raw = clean!(search).split(/\s+/)
106
-
107
- if raw.length < match.length
108
- diff = match - raw
109
- res = diff.length.to_f/match.length
110
- else
111
- diff = raw - match
112
- res = diff.length.to_f/raw.length
113
- end
114
-
115
- if diff.length > 1 and not match.map{ |m| diff.include?(m) }.all?
116
- res =+ diff.map do |value|
117
- match.map do |m|
118
- Levenshtein.distance(value, m)
119
- end.inject(:+)
120
- end.inject(:+) / @config[:offset]
121
- end
122
-
123
- [res - r.popularity/@config[:popularity], r]
124
- end.reject do |distance, song|
125
- exclude?(song.to_s) or not song.valid?
126
- end.sort_by do |distance, _|
127
- distance
128
- end.map(&:last).first : results.select(&:valid?).first
129
- end
130
-
131
- def type_of(r)
132
- if @type == :songs
133
- return r.name.to_s.downcase, r.artist.name.to_s.downcase
134
- elsif @type == :artists
135
- return r.song.title.to_s.downcase, r.name.to_s.downcase
99
+ if @prime
100
+ Spot::Prime.new(results.sort_by(&:popularity).reverse[0..6], search).
101
+ results.
102
+ select(&:valid?).
103
+ first
136
104
  else
137
- return "", r.artist.to_s.downcase
105
+ results.select(&:valid?).first
138
106
  end
139
107
  end
140
-
141
- def exclude?(compare)
142
- @exclude.
143
- reject{ |value| @search.to_s.match(/#{value}/i) }.
144
- map{ |value| compare.match(/#{value}/i) }.any?
145
- end
146
108
 
147
109
  #
148
110
  # @value String To be cleaned
@@ -26,11 +26,11 @@ module Spot
26
26
  /\.[a-z0-9]{2,3}$/,
27
27
  /\[[^\]]*\]/,
28
28
  /".*"/,
29
- /'.*'[^s]/,
29
+ /(\s+|^)'.*'(\s+|$)/,
30
30
  /[&|\/|\+][^\z]*/,
31
31
  /^(\d+.*?[^a-z]+?)/i
32
32
  ].each do |reg|
33
- string = string.gsub(reg, '').strip
33
+ string = string.gsub(reg, ' ').strip
34
34
  end
35
35
 
36
36
  [
@@ -0,0 +1,73 @@
1
+ require "levenshtein"
2
+ require_relative "clean"
3
+
4
+ module Spot
5
+ class Prime
6
+ @@ignore = YAML.load(File.read("#{File.dirname(__FILE__)}/ignore.yml"))
7
+
8
+ #
9
+ # @results Array<Object>
10
+ # @compare String
11
+ # @options Hash
12
+ #
13
+ def initialize(results, compare, options = {})
14
+ @options = {
15
+ popularity: 7,
16
+ exclude: 2,
17
+ limit: 0.7,
18
+ offset: 10
19
+ }.merge(options)
20
+
21
+ @results, @compare = results, compare
22
+ end
23
+
24
+ #
25
+ # @return Array<Object>
26
+ #
27
+ def results
28
+ @results.sort_by(&:popularity).map do |result|
29
+ match = clean(result.to_s).split(/\s+/).sort
30
+ raw = clean(@compare).split(/\s+/).sort
31
+
32
+ if raw.length < match.length
33
+ diff = (match - raw)
34
+ res = diff.length.to_f / match.length
35
+ else
36
+ diff = (raw - match)
37
+ res = diff.length.to_f / raw.length
38
+ end
39
+
40
+ if diff.length > 1 and not match.map{ |m| diff.include?(m) }.all?
41
+ res =+ diff.map do |value|
42
+ match.map { |m| Levenshtein.normalized_distance(value, m) }.inject(:+)
43
+ end.inject(:+) / @options[:offset]
44
+ end
45
+
46
+ [res - result.popularity / @options[:popularity], result]
47
+ end.reject do |_, result|
48
+ Spot::Prime.ignore?(result.to_s, @compare)
49
+ end.sort_by do |distance, _|
50
+ distance
51
+ end.map(&:last)
52
+ end
53
+
54
+ #
55
+ # @value String To be cleaned
56
+ # @return String A cleaned string
57
+ #
58
+ def clean(value)
59
+ Spot::Clean.new(value).process
60
+ end
61
+
62
+ #
63
+ # @this String
64
+ # @compare String
65
+ # @return Boolean
66
+ #
67
+ def self.ignore?(this, compare = nil)
68
+ @@ignore.
69
+ reject{ |value| compare.to_s.match(/#{value}/i) }.
70
+ map{ |value| this.match(/#{value}/i) }.any?
71
+ end
72
+ end
73
+ end
@@ -20,6 +20,10 @@ describe Spot::Clean do
20
20
  Spot::Clean.new("Song A \"abc def\"").process.should eq("song a")
21
21
  end
22
22
 
23
+ it "Sweet Child O' Mine by Guns N' Roses => sweet child o' mine by guns n' roses" do
24
+ Spot::Clean.new("Sweet Child O' Mine by Guns N' Roses").process.should eq("sweet child o' mine by guns n' roses")
25
+ end
26
+
23
27
  it "Song - A [B + C] => Song - A" do
24
28
  Spot::Clean.new("Song - A [B + C]").process.should eq("song a")
25
29
  end
@@ -103,6 +107,10 @@ describe Spot::Clean do
103
107
  Spot::Clean.new("Knockin' On Heaven's Door").process.should eq("knockin' on heaven's door")
104
108
  end
105
109
 
110
+ it "I Love Rock'n'roll => i love rock'n'roll" do
111
+ Spot::Clean.new("I Love Rock'n'roll").process.should eq("i love rock'n'roll")
112
+ end
113
+
106
114
  it "Jason Derulo - Undefeated" do
107
115
  Spot::Clean.new("Undefeated").process.should eq("undefeated")
108
116
  end
@@ -0,0 +1,31 @@
1
+ describe Spot::Prime do
2
+ context "exclude" do
3
+ it "should have a working exclude? method" do
4
+ {
5
+ "tribute" => true,
6
+ "cover random" => true,
7
+ "live" => true,
8
+ "club mix random" => true,
9
+ "LIVE" => true,
10
+ "karaoKE" => true,
11
+ "instrumental" => true,
12
+ "Karaoke - Won't Get Fooled Again" => true,
13
+ "club version" => true,
14
+ "instrumentals" => true,
15
+ "demo" => true,
16
+ "made famous by" => true,
17
+ "remixes" => true,
18
+ "ringtone" => true,
19
+ "ringtones" => true,
20
+ "riingtonerandom" => false,
21
+ "club random mix" => false,
22
+ "random" => false,
23
+ "oliver" => false,
24
+ "acoustic" => true,
25
+ "aacoustic" => false
26
+ }.each do |comp, outcome|
27
+ Spot::Prime.ignore?(comp).should eq(outcome)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -130,36 +130,6 @@ describe Spot::Search do
130
130
  end
131
131
  end
132
132
 
133
- context "exclude" do
134
- it "should have a working exclude? method" do
135
- {
136
- "tribute" => true,
137
- "cover random" => true,
138
- "live" => true,
139
- "club mix random" => true,
140
- "LIVE" => true,
141
- "karaoKE" => true,
142
- "instrumental" => true,
143
- "Karaoke - Won't Get Fooled Again" => true,
144
- "club version" => true,
145
- "instrumentals" => true,
146
- "demo" => true,
147
- "made famous by" => true,
148
- "remixes" => true,
149
- "ringtone" => true,
150
- "ringtones" => true,
151
- "riingtonerandom" => false,
152
- "club random mix" => false,
153
- "random" => false,
154
- "oliver" => false,
155
- "acoustic" => true,
156
- "aacoustic" => false
157
- }.each do |comp, outcome|
158
- @spot.exclude?(comp).should eq(outcome)
159
- end
160
- end
161
- end
162
-
163
133
  context "territory" do
164
134
  it "should not find any songs when using a non valid territory" do
165
135
  @spot.territory("RANDOM").find_all_songs("search").results.should be_empty
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "spot"
6
- s.version = "2.0.1"
6
+ s.version = "2.0.4"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Linus Oleander"]
9
9
  s.email = ["linus@oleander.nu"]
@@ -17,13 +17,13 @@ Gem::Specification.new do |s|
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
-
20
+
21
21
  s.add_dependency("json_pure")
22
22
  s.add_dependency("rest-client")
23
23
  s.add_dependency("abstract")
24
- s.add_dependency("levenshteinish")
24
+ s.add_dependency("levenshtein", "~> 0.2.2")
25
25
  s.add_dependency("charlock_holmes")
26
-
26
+
27
27
  s.add_development_dependency("rspec")
28
28
  s.add_development_dependency("vcr")
29
29
  s.add_development_dependency("webmock", "~> 1.8.0")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spot
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-18 00:00:00.000000000Z
12
+ date: 2012-06-26 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json_pure
16
- requirement: &70287100095840 !ruby/object:Gem::Requirement
16
+ requirement: &70221274908280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70287100095840
24
+ version_requirements: *70221274908280
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rest-client
27
- requirement: &70287100095400 !ruby/object:Gem::Requirement
27
+ requirement: &70221274907840 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70287100095400
35
+ version_requirements: *70221274907840
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: abstract
38
- requirement: &70287100094980 !ruby/object:Gem::Requirement
38
+ requirement: &70221274907420 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,21 +43,21 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70287100094980
46
+ version_requirements: *70221274907420
47
47
  - !ruby/object:Gem::Dependency
48
- name: levenshteinish
49
- requirement: &70287100094560 !ruby/object:Gem::Requirement
48
+ name: levenshtein
49
+ requirement: &70221274906920 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
- - - ! '>='
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 0.2.2
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70287100094560
57
+ version_requirements: *70221274906920
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: charlock_holmes
60
- requirement: &70287100094140 !ruby/object:Gem::Requirement
60
+ requirement: &70221274906500 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70287100094140
68
+ version_requirements: *70221274906500
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &70287100093720 !ruby/object:Gem::Requirement
71
+ requirement: &70221274906040 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70287100093720
79
+ version_requirements: *70221274906040
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: vcr
82
- requirement: &70287100093300 !ruby/object:Gem::Requirement
82
+ requirement: &70221274905620 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70287100093300
90
+ version_requirements: *70221274905620
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: webmock
93
- requirement: &70287100092800 !ruby/object:Gem::Requirement
93
+ requirement: &70221274905120 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: 1.8.0
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70287100092800
101
+ version_requirements: *70221274905120
102
102
  description: A Ruby implementation of the Spotify Meta API.
103
103
  email:
104
104
  - linus@oleander.nu
@@ -118,6 +118,7 @@ files:
118
118
  - lib/spot/clean.rb
119
119
  - lib/spot/exclude.yml
120
120
  - lib/spot/ignore.yml
121
+ - lib/spot/prime.rb
121
122
  - lib/spot/song.rb
122
123
  - spec/album_spec.rb
123
124
  - spec/artist_spec.rb
@@ -128,6 +129,7 @@ files:
128
129
  - spec/fixtures/exclude.tribute.json
129
130
  - spec/fixtures/track.json
130
131
  - spec/fixtures/vcr_cassettes/spotify.yml
132
+ - spec/prime_spec.rb
131
133
  - spec/song_spec.rb
132
134
  - spec/spec_helper.rb
133
135
  - spec/spot_spec.rb
@@ -166,6 +168,7 @@ test_files:
166
168
  - spec/fixtures/exclude.tribute.json
167
169
  - spec/fixtures/track.json
168
170
  - spec/fixtures/vcr_cassettes/spotify.yml
171
+ - spec/prime_spec.rb
169
172
  - spec/song_spec.rb
170
173
  - spec/spec_helper.rb
171
174
  - spec/spot_spec.rb