Advertisement
Guest User

Untitled

a guest
Jan 18th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.79 KB | None | 0 0
  1. class AddressDistance < ActiveRecord::Base
  2. MAX_ELEMENTS_PER_QUERY = 100
  3. MAX_PER_DIRECTION = 25
  4. SECONDS_PER_ELEMENT = 0.01
  5.  
  6. # Origins and destinations are Address arrays
  7. # Retrieves and saves a distance matrix
  8. def self.gather_distance_matrix(srcs, dsts = srcs.deep_dup)
  9. # recursive calls don't hit the originating while loop
  10. while srcs.size > MAX_PER_DIRECTION
  11. gather_distance_matrix(srcs.pop(MAX_PER_DIRECTION),
  12. dsts.deep_dup)
  13. end
  14. while srcs.size > MAX_PER_DIRECTION
  15. gather_distance_matrix(srcs.deep_dup,
  16. dsts.pop(MAX_PER_DIRECTION))
  17. end
  18.  
  19. # e.g. if origins and destinations have sizes [19, 13],
  20. # they will become [19, 13], [19, 8], [7, 8]; then 7 * 8 < 100
  21. while srcs.size * dsts.size > MAX_ELEMENTS_PER_QUERY
  22. if MAX_ELEMENTS_PER_QUERY % srcs.size < MAX_ELEMENTS_PER_QUERY % dsts.size
  23. gather_distance_matrix(srcs.deep_dup,
  24. dsts.pop(MAX_ELEMENTS_PER_QUERY / srcs.size))
  25. else
  26. gather_distance_matrix(srcs.pop(MAX_ELEMENTS_PER_QUERY / dsts.size),
  27. dsts.deep_dup)
  28. end
  29. end
  30.  
  31. # assumes response is not an error
  32. matrix = GoogleMapsWrapper.distance_matrix(srcs.map(&:geocode),
  33. dsts.map(&:geocode))
  34.  
  35. # save response
  36. matrix.each_with_index do |origin, i|
  37. origin.each_with_index do |distance_params, j|
  38. seconds, _meters = distance_params
  39. # TODO: save metric distance also
  40. ad = AddressDistance.find_or_create_by(from_address_id: srcs[i].id,
  41. to_address_id: dsts[j].id)
  42. ad.update(distance_seconds: seconds)
  43. end
  44. end
  45.  
  46. sleep(srcs.size * dsts.size * SECONDS_PER_ELEMENT)
  47. end
  48. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement