lib/wurfl-lite.rb in wurfl-lite-1.0.2 vs lib/wurfl-lite.rb in wurfl-lite-1.1.0
- old
+ new
@@ -3,22 +3,49 @@
require 'hpricot'
require 'amatch'
class WURFL
+ LATEST = 'http://downloads.sourceforge.net/project/wurfl/WURFL/latest/wurfl-latest.xml.gz'
+ BROWSER_PATCH = 'http://wurfl.sourceforge.net/web_browsers_patch.xml'
+
+ attr_accessor :insertion, :substitution, :deletion
+ attr_accessor :match_threshold
+
+ def initialize( filenames = [ LATEST, BROWSER_PATCH ] )
+ clear!
+ [filenames].flatten.each do |filename|
+ process_xml!( filename )
+ end
+ @insertion = 2
+ @substitution = 1
+ @deletion = 1.5
+ @match_threshold = 0.15
+ end
+
class Hash < ::Hash
def method_missing( method )
has_key?( method ) ? self[ method ] : ( self[ :fall_back ] ? self[ :fall_back ].send( method ) : nil )
end
end
def clear!
@devices = Hash.new
@devices_by_id = {}
+ @files = []
end
+ def reset!
+ files = @files
+ clear!
+ files.each do |filename|
+ process_xml!( filename )
+ end
+ end
+
def process_xml!( filename )
+ @files << filename
data = open( filename ).read
begin # Try decompress it, in case it's a compressed file
# XXX Yes, this does seem ugly, but is there another way?
data = Zlib::GzipReader.new(StringIO.new(data.to_s)).read
rescue Zlib::GzipFile::Error
@@ -53,22 +80,35 @@
@devices[ key ][ :fall_back ] = @devices_by_id[ @devices[ key ][ :fall_back ] ]
end
end
- def initialize( filename = 'http://downloads.sourceforge.net/project/wurfl/WURFL/latest/wurfl-latest.xml.gz' )
- clear!
- process_xml!( filename )
- process_xml!( 'http://wurfl.sourceforge.net/web_browsers_patch.xml' )
- end
-
def []( user_agent )
device = @devices[ user_agent ]
- return device if device
+ if device
+ device[ :wurfl_match ] = { :distance => 0, :distance_normalized => 0 }
+ return device
+ end
match = Amatch::Sellers.new( user_agent )
+ match.insertion = @insertion
+ match.substitution = @substitution
+ match.deletion = @deletion
keys = @devices.keys
distances = match.match( keys )
- use_key = keys.zip( distances ).sort{|a,b|a.last<=>b.last}.first.first
- @devices[ user_agent ] = @devices[ use_key ]
+ sorted_list = keys.zip( distances ).sort{|a,b|a.last<=>b.last}
+ use_key = sorted_list.first.first
+ device = @devices[ use_key ]
+ distance = sorted_list.first.last
+ distance_normalised = distance/(user_agent.length+1)
+
+ if distance_normalised > @match_threshold
+ nil
+ else
+ device[ :wurfl_match ] = {
+ :distance => distance,
+ :distance_normalised => distance_normalised
+ }
+ @devices[ user_agent ] = device
+ end
end
end