Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ source 'https://rubygems.org'
gem 'rake'
gem 'rspec'
gem 'activesupport'
gem 'geocoder'
gem "geocoder"
gem 'nokogiri'
6 changes: 5 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ GEM
i18n (~> 0.6)
multi_json (~> 1.0)
diff-lcs (1.1.3)
geocoder (1.1.1)
geocoder (1.1.6)
i18n (0.6.0)
multi_json (1.3.4)
nokogiri (1.5.9)
nokogiri (1.5.9-x86-mingw32)
rake (0.9.2.2)
rspec (2.10.0)
rspec-core (~> 2.10.0)
Expand All @@ -20,9 +22,11 @@ GEM

PLATFORMS
ruby
x86-mingw32

DEPENDENCIES
activesupport
geocoder
nokogiri
rake
rspec
19 changes: 13 additions & 6 deletions lib/calculates_route.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
class CalculatesRoute

def self.calculate(points)
attr_reader :total_distance

def self.calculate(points, start_point)
@total_distance = 0
remaining_points = points
route = []
route << remaining_points.slice!(0)
index = remaining_points.index(start_point)
if index.nil?
route << remaining_points.slice!(0)
else
route << remaining_points.slice!(index)
end
until remaining_points == [] do
next_point = shortest_distance(route.last, remaining_points)
route << remaining_points.slice!(remaining_points.index(next_point))
route << remaining_points.slice!(remaining_points.index(next_point.fetch(:point)))
@total_distance += next_point.fetch(:distance)
end
route
vals = {route: route, distance: @total_distance}
end

def self.shortest_distance(from, possible)
distances = possible.map do |point|
{point: point, distance: Map.distance_between(from, point)}
end
distances.sort{|a,b| a.fetch(:distance) <=> b.fetch(:distance)}.first.fetch(:point)
point = distances.sort{|a,b| a.fetch(:distance) <=> b.fetch(:distance)}.first
end
end

7 changes: 7 additions & 0 deletions lib/map.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
require 'geocoder'

Geocoder.configure(
lookup: :bing,
api_key: 'AkTjVpt-Si67rkjRTerrBqnmMIJSwWAEXSsoMJQMHa3ZO1rbHbECo1crQ_iuGTg-',
timeout: 10
)

class Map

def self.search(terms)
Expand Down
16 changes: 14 additions & 2 deletions lib/sales_person.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ def schedule_city(city)
@cities << city unless @cities.include?(city)
end

def route
CalculatesRoute.calculate(cities)
def find_city(city_name)
found = cities.select {|city| city if city.name == city_name}
found.first
end

def route(start)
city = find_city(start)
vals = CalculatesRoute.calculate(cities, city)
results = {route: vals.fetch(:route), time: traveling_time(vals.fetch(:distance)) }
end

def traveling_time(distance)
time = distance / 55
end

end
60 changes: 54 additions & 6 deletions salesperson.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,58 @@
Dir["./lib/*.rb"].each {|file| require file }

require "benchmark"
require 'nokogiri'
require 'open-uri'

phil = SalesPerson.new
phil.schedule_city(Place.build("Dallas, TX"))
phil.schedule_city(Place.build("El Paso, TX"))
phil.schedule_city(Place.build("Austin, TX"))
phil.schedule_city(Place.build("Lubbock, TX"))
# these locations work with google, but not bing
#phil.schedule_city(Place.build("Target, Smyrna, GA"))
#phil.schedule_city(Place.build("IKEA, Atlanta, GA"))
#phil.schedule_city(Place.build("Petco, Kennesaw, GA"))
#phil.schedule_city(Place.build("Hobby Town USA, Kennesaw, GA"))
#phil.schedule_city(Place.build("Publix Delk Rd, Marietta, GA"))
phil.schedule_city(Place.build("Marietta, GA"))
phil.schedule_city(Place.build("Sandy Springs, GA"))
phil.schedule_city(Place.build("Roswell, GA"))
phil.schedule_city(Place.build("Buford, GA"))
phil.schedule_city(Place.build("Smyrna, GA"))

puts "All places:"
puts phil.cities
puts
puts "Where should the person start?"
puts
start = gets.chomp
if (start.empty? == false)
vals = phil.route(start)
puts "The route starting at #{start}:\n"
puts vals.fetch(:route)
travel = vals.fetch(:time)
puts "Total traveling time in hours: #{vals.fetch(:time).round(2)}"

end

texas_cities = []
doc = Nokogiri::HTML(open('http://www.texas.gov/en/discover/Pages/topic.aspx?topicid=/government/localgov'))
doc.css(".TGOV_SCRD_Header a").map do |node|
texas_cities << node.content
end

bench_vals = [2, 10, 50, 200]
bench_vals.each do |val|
current = SalesPerson.new
texas_cities.shuffle.take(val).each do |city|
current.schedule_city(Place.build(city))
end

puts phil.route
the_route = []
puts "\nBenchmarking results for #{val} cities:"
Benchmark.bm do |x|
x.report do
vals = current.route(nil)
end
puts "The route:"
puts vals.fetch(:route)
travel = vals.fetch(:time)
puts "Total traveling time in hours: #{vals.fetch(:time).round(2)}"
end
end
8 changes: 7 additions & 1 deletion spec/calculates_route_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
it "should calculate the route" do
points = [dallas, el_paso, austin, lubbock]
expected = [dallas, austin, lubbock, el_paso]
CalculatesRoute.calculate(points).should eq(expected)
CalculatesRoute.calculate(points, "dallas").fetch(:route).should eq(expected)
end

it "should log the total miles" do
points = [dallas, el_paso, austin, lubbock]
vals = CalculatesRoute.calculate(points, "Austin, TX")
vals.fetch(:distance).should_not be(0)
end
end
25 changes: 19 additions & 6 deletions spec/sales_person_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,28 @@
}.to change(subject.cities,:count).by(1)
end

it "should find a city using a name entered by the user" do
city = stub
city.stub(name:"Atlanta, GA")
subject.schedule_city(city)
subject.find_city("Atlanta, GA").should eq(city)
end

it "should calculate a route via the CalculatesRoute" do
cities = [stub, stub, stub]
start = stub(name: "Atlanta, GA")
last = stub(name: "Marietta, GA")
cities = [start, last]
subject.stub(:cities) { cities }
CalculatesRoute.should_receive(:calculate).with(cities)
subject.route
CalculatesRoute.should_receive(:calculate).with(cities, start)
subject.route("Atlanta, GA")
end
it "should returns the route from CalculatesRoute" do
route_stub = [stub, stub]

it "should return the route from CalculatesRoute" do
route_stub = [stub("Marietta, GA"), stub("Atlanta, GA")]
start = stub("Marietta, GA")
CalculatesRoute.stub(:calculate) { route_stub }
subject.route.should eq(route_stub)
CalculatesRoute.stub(:route).and_return(route_stub)
subject.route(start).should eq(route_stub)
end

end