From ef924b51cfbcbf37da9ebf302f5c805053f8634b Mon Sep 17 00:00:00 2001 From: meltar Date: Sun, 14 Apr 2013 14:07:59 -0400 Subject: [PATCH 1/4] Panda complete --- Gemfile.lock | 1 + lib/calculates_route.rb | 5 +++-- lib/sales_person.rb | 9 +++++++-- salesperson.rb | 20 +++++++++++++++----- spec/calculates_route_spec.rb | 3 ++- spec/sales_person_spec.rb | 19 ++++++++++++++----- 6 files changed, 42 insertions(+), 15 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 28827b4..497da3c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,6 +20,7 @@ GEM PLATFORMS ruby + x86-mingw32 DEPENDENCIES activesupport diff --git a/lib/calculates_route.rb b/lib/calculates_route.rb index 4488393..360dfb1 100644 --- a/lib/calculates_route.rb +++ b/lib/calculates_route.rb @@ -1,10 +1,11 @@ class CalculatesRoute - def self.calculate(points) + def self.calculate(points, start_point) remaining_points = points route = [] - route << remaining_points.slice!(0) + start_index = remaining_points.index(start_point) + route << remaining_points.slice!(remaining_points.index(start_point)) until remaining_points == [] do next_point = shortest_distance(route.last, remaining_points) route << remaining_points.slice!(remaining_points.index(next_point)) diff --git a/lib/sales_person.rb b/lib/sales_person.rb index d0c2890..f3ca414 100644 --- a/lib/sales_person.rb +++ b/lib/sales_person.rb @@ -9,7 +9,12 @@ 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) + CalculatesRoute.calculate(cities, find_city(start)) end end diff --git a/salesperson.rb b/salesperson.rb index 9cafbd7..eb2438c 100644 --- a/salesperson.rb +++ b/salesperson.rb @@ -2,9 +2,19 @@ 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")) +phil.schedule_city(Place.build("Target, Marietta, GA")) +phil.schedule_city(Place.build("IKEA, Atlanta, GA")) +phil.schedule_city(Place.build("Petco, Kennesaw, GA")) +phil.schedule_city(Place.build("Hobbytown USA, Kennesaw, GA")) +phil.schedule_city(Place.build("Publix Delk Rd, Marietta, GA")) -puts phil.route +puts "All places:" +puts phil.cities +puts +puts "Where should the person start?" +puts +start = gets.chomp +if (start.empty? == false) + puts "The route:" + puts phil.route(start) +end \ No newline at end of file diff --git a/spec/calculates_route_spec.rb b/spec/calculates_route_spec.rb index 47679d6..9931ca9 100644 --- a/spec/calculates_route_spec.rb +++ b/spec/calculates_route_spec.rb @@ -10,6 +10,7 @@ it "should calculate the route" do points = [dallas, el_paso, austin, lubbock] expected = [dallas, austin, lubbock, el_paso] - CalculatesRoute.calculate(points).should eq(expected) + start_point = dallas + CalculatesRoute.calculate(points, start_point).should eq(expected) end end diff --git a/spec/sales_person_spec.rb b/spec/sales_person_spec.rb index 08a6ce9..d010a82 100644 --- a/spec/sales_person_spec.rb +++ b/spec/sales_person_spec.rb @@ -16,15 +16,24 @@ }.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("Atlanta, GA") + cities = [start, stub, stub] subject.stub(:cities) { cities } - CalculatesRoute.should_receive(:calculate).with(cities) - subject.route + CalculatesRoute.should_receive(:calculate).with(cities, nil) + subject.route(start) end it "should returns the route from CalculatesRoute" do - route_stub = [stub, stub] + route_stub = [stub("Marietta, GA"), stub("Atlanta, GA")] + start = stub("Marietta, GA") CalculatesRoute.stub(:calculate) { route_stub } - subject.route.should eq(route_stub) + subject.route(start).should eq(route_stub) end end From 16e5e627631232495e3182186a341bc352e02e75 Mon Sep 17 00:00:00 2001 From: meltar Date: Sun, 14 Apr 2013 14:17:38 -0400 Subject: [PATCH 2/4] Panda complete --- Gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile b/Gemfile index 276e671..1b26299 100644 --- a/Gemfile +++ b/Gemfile @@ -4,3 +4,4 @@ gem 'rake' gem 'rspec' gem 'activesupport' gem 'geocoder' +gem 'benchmark' From fd25ef6ef658835426227dc40f50f53f1aa61bc2 Mon Sep 17 00:00:00 2001 From: meltar Date: Sun, 14 Apr 2013 18:22:09 -0400 Subject: [PATCH 3/4] Tiger complete (using nokogiri and open-uri and configured Geocoder to use Bing maps) --- Gemfile | 4 ++-- Gemfile.lock | 2 ++ lib/calculates_route.rb | 7 ++++-- lib/map.rb | 6 +++++ lib/place.rb | 1 + salesperson.rb | 51 ++++++++++++++++++++++++++++++++++------- 6 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 1b26299..4359af1 100644 --- a/Gemfile +++ b/Gemfile @@ -3,5 +3,5 @@ source 'https://rubygems.org' gem 'rake' gem 'rspec' gem 'activesupport' -gem 'geocoder' -gem 'benchmark' +gem "geocoder" +gem 'nokogiri' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 497da3c..030bc16 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,6 +8,7 @@ GEM geocoder (1.1.1) i18n (0.6.0) multi_json (1.3.4) + nokogiri (1.5.9-x86-mingw32) rake (0.9.2.2) rspec (2.10.0) rspec-core (~> 2.10.0) @@ -25,5 +26,6 @@ PLATFORMS DEPENDENCIES activesupport geocoder + nokogiri rake rspec diff --git a/lib/calculates_route.rb b/lib/calculates_route.rb index 360dfb1..2521550 100644 --- a/lib/calculates_route.rb +++ b/lib/calculates_route.rb @@ -4,8 +4,11 @@ def self.calculate(points, start_point) remaining_points = points route = [] - start_index = remaining_points.index(start_point) - route << remaining_points.slice!(remaining_points.index(start_point)) + if start_point.nil? + route << remaining_points.slice!(0) + else + route << remaining_points.slice!(remaining_points.index(start_point)) + end until remaining_points == [] do next_point = shortest_distance(route.last, remaining_points) route << remaining_points.slice!(remaining_points.index(next_point)) diff --git a/lib/map.rb b/lib/map.rb index e9abfde..d229281 100644 --- a/lib/map.rb +++ b/lib/map.rb @@ -1,4 +1,10 @@ require 'geocoder' + +Geocoder.configure( + lookup: :bing, + api_key: 'AkTjVpt-Si67rkjRTerrBqnmMIJSwWAEXSsoMJQMHa3ZO1rbHbECo1crQ_iuGTg-' +) + class Map def self.search(terms) diff --git a/lib/place.rb b/lib/place.rb index 99eaadf..8a4628c 100644 --- a/lib/place.rb +++ b/lib/place.rb @@ -7,6 +7,7 @@ def self.build(name) results = Map.search(name) Place.new.tap do |p| p.name = name + #puts "Coords: #{results.coordinates}" p.coordinates = results.coordinates end end diff --git a/salesperson.rb b/salesperson.rb index eb2438c..964e10e 100644 --- a/salesperson.rb +++ b/salesperson.rb @@ -1,12 +1,20 @@ Dir["./lib/*.rb"].each {|file| require file } - +require "benchmark" +require 'nokogiri' +require 'open-uri' phil = SalesPerson.new -phil.schedule_city(Place.build("Target, Marietta, GA")) -phil.schedule_city(Place.build("IKEA, Atlanta, GA")) -phil.schedule_city(Place.build("Petco, Kennesaw, GA")) -phil.schedule_city(Place.build("Hobbytown USA, Kennesaw, GA")) -phil.schedule_city(Place.build("Publix Delk Rd, Marietta, GA")) +# 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 @@ -15,6 +23,33 @@ puts start = gets.chomp if (start.empty? == false) - puts "The route:" + puts "The route starting at #{start}:\n" puts phil.route(start) -end \ No newline at end of file +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 +puts "Texas city count: #{texas_cities.count}" + +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 + + the_route = [] + puts "\nBenchmarking results for #{val} cities:" + Benchmark.bm do |x| + x.report do + the_route = current.route(nil) + end + puts "The route:" + puts the_route + end +end + + From 6e1fa8ac29b6cae5663886d575e1e9d79a55ebe3 Mon Sep 17 00:00:00 2001 From: meltar Date: Tue, 16 Apr 2013 13:24:02 -0400 Subject: [PATCH 4/4] Eagle complete with some refactoring --- Gemfile.lock | 3 ++- lib/calculates_route.rb | 17 ++++++++++------- lib/map.rb | 3 ++- lib/place.rb | 1 - lib/sales_person.rb | 11 +++++++++-- salesperson.rb | 17 ++++++++++------- spec/calculates_route_spec.rb | 9 +++++++-- spec/sales_person_spec.rb | 14 +++++++++----- 8 files changed, 49 insertions(+), 26 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 030bc16..9d419d7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,9 +5,10 @@ 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) diff --git a/lib/calculates_route.rb b/lib/calculates_route.rb index 2521550..0c37655 100644 --- a/lib/calculates_route.rb +++ b/lib/calculates_route.rb @@ -1,26 +1,29 @@ class CalculatesRoute - def self.calculate(points, start_point) + attr_reader :total_distance + def self.calculate(points, start_point) + @total_distance = 0 remaining_points = points route = [] - if start_point.nil? + index = remaining_points.index(start_point) + if index.nil? route << remaining_points.slice!(0) else - route << remaining_points.slice!(remaining_points.index(start_point)) + 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 - diff --git a/lib/map.rb b/lib/map.rb index d229281..994c189 100644 --- a/lib/map.rb +++ b/lib/map.rb @@ -2,7 +2,8 @@ Geocoder.configure( lookup: :bing, - api_key: 'AkTjVpt-Si67rkjRTerrBqnmMIJSwWAEXSsoMJQMHa3ZO1rbHbECo1crQ_iuGTg-' + api_key: 'AkTjVpt-Si67rkjRTerrBqnmMIJSwWAEXSsoMJQMHa3ZO1rbHbECo1crQ_iuGTg-', + timeout: 10 ) class Map diff --git a/lib/place.rb b/lib/place.rb index 8a4628c..99eaadf 100644 --- a/lib/place.rb +++ b/lib/place.rb @@ -7,7 +7,6 @@ def self.build(name) results = Map.search(name) Place.new.tap do |p| p.name = name - #puts "Coords: #{results.coordinates}" p.coordinates = results.coordinates end end diff --git a/lib/sales_person.rb b/lib/sales_person.rb index f3ca414..128d99c 100644 --- a/lib/sales_person.rb +++ b/lib/sales_person.rb @@ -10,11 +10,18 @@ def schedule_city(city) end def find_city(city_name) - found = @cities.select {|city| city if city.name == city_name} + found = cities.select {|city| city if city.name == city_name} found.first end def route(start) - CalculatesRoute.calculate(cities, find_city(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 diff --git a/salesperson.rb b/salesperson.rb index 964e10e..8b19fd3 100644 --- a/salesperson.rb +++ b/salesperson.rb @@ -23,8 +23,12 @@ puts start = gets.chomp if (start.empty? == false) + vals = phil.route(start) puts "The route starting at #{start}:\n" - puts phil.route(start) + puts vals.fetch(:route) + travel = vals.fetch(:time) + puts "Total traveling time in hours: #{vals.fetch(:time).round(2)}" + end texas_cities = [] @@ -32,7 +36,6 @@ doc.css(".TGOV_SCRD_Header a").map do |node| texas_cities << node.content end -puts "Texas city count: #{texas_cities.count}" bench_vals = [2, 10, 50, 200] bench_vals.each do |val| @@ -45,11 +48,11 @@ puts "\nBenchmarking results for #{val} cities:" Benchmark.bm do |x| x.report do - the_route = current.route(nil) + vals = current.route(nil) end puts "The route:" - puts the_route + puts vals.fetch(:route) + travel = vals.fetch(:time) + puts "Total traveling time in hours: #{vals.fetch(:time).round(2)}" end -end - - +end \ No newline at end of file diff --git a/spec/calculates_route_spec.rb b/spec/calculates_route_spec.rb index 9931ca9..a1d284a 100644 --- a/spec/calculates_route_spec.rb +++ b/spec/calculates_route_spec.rb @@ -10,7 +10,12 @@ it "should calculate the route" do points = [dallas, el_paso, austin, lubbock] expected = [dallas, austin, lubbock, el_paso] - start_point = dallas - CalculatesRoute.calculate(points, start_point).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 diff --git a/spec/sales_person_spec.rb b/spec/sales_person_spec.rb index d010a82..c6b1d90 100644 --- a/spec/sales_person_spec.rb +++ b/spec/sales_person_spec.rb @@ -24,16 +24,20 @@ end it "should calculate a route via the CalculatesRoute" do - start = stub("Atlanta, GA") - cities = [start, 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, nil) - subject.route(start) + CalculatesRoute.should_receive(:calculate).with(cities, start) + subject.route("Atlanta, GA") end - it "should returns the route from CalculatesRoute" do + + 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 } + CalculatesRoute.stub(:route).and_return(route_stub) subject.route(start).should eq(route_stub) end + end