Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class AddressDistance < ActiveRecord::Base
- MAX_ELEMENTS_PER_QUERY = 100
- MAX_PER_DIRECTION = 25
- SECONDS_PER_ELEMENT = 0.01
- # Origins and destinations are Address arrays
- # Retrieves and saves a distance matrix
- def self.gather_distance_matrix(srcs, dsts = srcs.deep_dup)
- # recursive calls don't hit the originating while loop
- while srcs.size > MAX_PER_DIRECTION
- gather_distance_matrix(srcs.pop(MAX_PER_DIRECTION),
- dsts.deep_dup)
- end
- while srcs.size > MAX_PER_DIRECTION
- gather_distance_matrix(srcs.deep_dup,
- dsts.pop(MAX_PER_DIRECTION))
- end
- # e.g. if origins and destinations have sizes [19, 13],
- # they will become [19, 13], [19, 8], [7, 8]; then 7 * 8 < 100
- while srcs.size * dsts.size > MAX_ELEMENTS_PER_QUERY
- if MAX_ELEMENTS_PER_QUERY % srcs.size < MAX_ELEMENTS_PER_QUERY % dsts.size
- gather_distance_matrix(srcs.deep_dup,
- dsts.pop(MAX_ELEMENTS_PER_QUERY / srcs.size))
- else
- gather_distance_matrix(srcs.pop(MAX_ELEMENTS_PER_QUERY / dsts.size),
- dsts.deep_dup)
- end
- end
- # assumes response is not an error
- matrix = GoogleMapsWrapper.distance_matrix(srcs.map(&:geocode),
- dsts.map(&:geocode))
- # save response
- matrix.each_with_index do |origin, i|
- origin.each_with_index do |distance_params, j|
- seconds, _meters = distance_params
- # TODO: save metric distance also
- ad = AddressDistance.find_or_create_by(from_address_id: srcs[i].id,
- to_address_id: dsts[j].id)
- ad.update(distance_seconds: seconds)
- end
- end
- sleep(srcs.size * dsts.size * SECONDS_PER_ELEMENT)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement