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