spot 2.0.1 → 2.0.4

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