diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f3e4a68..0000000 --- a/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2012 Jesse Wolgamott - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/calculates_route.rb b/lib/calculates_route.rb index 4488393..5f16ca1 100644 --- a/lib/calculates_route.rb +++ b/lib/calculates_route.rb @@ -1,22 +1,34 @@ +require_relative "./map" class CalculatesRoute - def self.calculate(points) + attr_reader :total_distance, :total_time + + def self.calculate(points, start_point) + @total_distance = 0 remaining_points = points + route = [] - route << remaining_points.slice!(0) - until remaining_points == [] do - next_point = shortest_distance(route.last, remaining_points) - route << remaining_points.slice!(remaining_points.index(next_point)) + conf = remaining_points.index(start_point) + + if conf.nil? + route << remaining_points.slice!(0) + else + route << remaining_points.slice!(conf) end - route + until remaining_points == [] do + next_point = shortest_distance(route.last, remaining_points) + route << remaining_points.slice!(remaining_points.index(next_point.fetch(:point))) + @total_distance += next_point.fetch(:distance) + end + display = {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 +end \ No newline at end of file diff --git a/lib/map.rb b/lib/map.rb index e9abfde..e02317f 100644 --- a/lib/map.rb +++ b/lib/map.rb @@ -5,7 +5,8 @@ def self.search(terms) Array(Geocoder.search(terms)).first end + def self.distance_between(first, second) Geocoder::Calculations.distance_between(first, second) end -end +end \ No newline at end of file diff --git a/lib/place.rb b/lib/place.rb index 99eaadf..59e0df9 100644 --- a/lib/place.rb +++ b/lib/place.rb @@ -1,8 +1,7 @@ require_relative "./map" - class Place - attr_accessor :name, :coordinates +attr_accessor :name, :coordinates def self.build(name) results = Map.search(name) Place.new.tap do |p| @@ -18,4 +17,5 @@ def to_s def to_coordinates coordinates end -end + +end \ No newline at end of file diff --git a/lib/sales_person.rb b/lib/sales_person.rb index d0c2890..7e8ffb1 100644 --- a/lib/sales_person.rb +++ b/lib/sales_person.rb @@ -1,6 +1,9 @@ +require_relative "./calculates_route" + class SalesPerson attr_reader :cities + def initialize @cities = [] end @@ -8,8 +11,22 @@ def initialize def schedule_city(city) @cities << city unless @cities.include?(city) end + + def find_city(start_name) + found = cities.select{|city| city if city.name == start_name} + found.first + end - def route - CalculatesRoute.calculate(cities) + def route(start) + city = find_city(start) + display = CalculatesRoute.calculate(cities, city) + results = {route: display.fetch(:route), time: traveling_time(display.fetch(:distance))} + return [results.fetch(:route), results.fetch(:time)] + end + + def traveling_time(distance) + time = distance/55 + end + end diff --git a/salesperson.rb b/salesperson.rb index 9cafbd7..d8f3f4c 100644 --- a/salesperson.rb +++ b/salesperson.rb @@ -1,10 +1,50 @@ Dir["./lib/*.rb"].each {|file| require file } +require "benchmark" +require 'nokogiri' +require 'open-uri' phil = SalesPerson.new +phil.schedule_city(Place.build("Burbank, CA")) 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("Brooklyn, NY")) +phil.schedule_city(Place.build("Griffith, Park")) +phil.schedule_city(Place.build("Berkeley, San Francisco")) +phil.schedule_city(Place.build("Los Angeles, CA")) +phil.schedule_city(Place.build("San Diego, CA")) +starting_point = "Austin, TX" +puts phil.cities +puts '------------------------' +puts phil.route(starting_point) + + +texas_cities = [] +texas = Nokogiri::HTML(open('http://www.texas.gov/en/discover/Pages/topic.aspx?topicid=/government/localgov')) +texas.css(" .topic-subcategory-link a").map do |node| + texas_cities << node.content + + #puts node.content +end + + +bench_var = [2, 3] + bench_var.each do |var| + content = SalesPerson.new + texas_cities.shuffle.take(var).each do |city| + content.schedule_city(Place.build(city)) + end + + Benchmark.bm do |x| + x.report do + starting_point = "Austin, Texas" + y = content.route(starting_point) + puts y + end + end +end + + -puts phil.route diff --git a/spec/calculates_route_spec.rb b/spec/calculates_route_spec.rb index 47679d6..f17240e 100644 --- a/spec/calculates_route_spec.rb +++ b/spec/calculates_route_spec.rb @@ -1,15 +1,23 @@ require_relative "../lib/calculates_route" -require_relative "../lib/place" - -describe CalculatesRoute do - let(:dallas) {Place.build("Dallas, TX") } - let(:austin ) { Place.build("Austin, TX")} - let(:lubbock ) { Place.build("Lubbock, TX")} - let(:el_paso ) { Place.build("El Paso, TX")} - - it "should calculate the route" do - points = [dallas, el_paso, austin, lubbock] - expected = [dallas, austin, lubbock, el_paso] - CalculatesRoute.calculate(points).should eq(expected) - end -end +require_relative "../lib/place.rb" + + describe CalculatesRoute do + let(:austin) {Place.build("Austin, TX")} + let(:dallas) {Place.build("Dallas, TX")} + let(:el_paso) {Place.build("El Paso, TX")} + let(:lubbock) {Place.build("Lubbock, TX")} + + it "should be able to show the correct route" do + start = austin + inputs = [austin, dallas, el_paso, lubbock] + expected = [austin, dallas, lubbock, el_paso] + CalculatesRoute.calculate(inputs, start).fetch(:route).should eq(expected) + end + + it "should be able to calculate the total distance" do + start = austin + inputs = [austin, dallas, el_paso, lubbock] + CalculatesRoute.calculate(inputs, start).fetch(:distance).should_not be(0) + + end +end \ No newline at end of file diff --git a/spec/map_spec.rb b/spec/map_spec.rb index 2e2f6f1..b86d40f 100644 --- a/spec/map_spec.rb +++ b/spec/map_spec.rb @@ -1,10 +1,11 @@ +require_relative "../lib/place" require_relative "../lib/map" require 'geocoder' -describe Map do +describe Map do describe ":search" do - it "should delegate search to geocoder" do + it "should be able to search in geocoder" do Geocoder.should_receive(:search).with("austin, tx") Map.search("austin, tx") end @@ -18,11 +19,13 @@ end describe ":distance" do - it "should calculate distance between two sets of coordinates" do - alpha = stub - beta = stub + it "should measure the accurate distance between points" do + alpha = stub + beta = stub Geocoder::Calculations.should_receive(:distance_between).with(alpha, beta) Map.distance_between(alpha, beta) end end -end + + +end \ No newline at end of file diff --git a/spec/place_spec.rb b/spec/place_spec.rb index 7d48250..a0c8251 100644 --- a/spec/place_spec.rb +++ b/spec/place_spec.rb @@ -1,43 +1,45 @@ -require_relative "../lib/place" -require_relative "../lib/map" - -describe Place do +require_relative '../lib/place' +require_relative '../lib/map' +describe Place do + it "should have a name" do subject.should respond_to(:name) end - it "should have a coordinates" do - subject.coordinates = [29,-95] - subject.coordinates.should eq([29,-95]) - end + it "should have a coordinate" do + subject.coordinates = [-29, -95] + subject.coordinates.should eq([-29, -95]) + end describe ":build" do - let(:name) { "El Paso, TX"} + let(:name) {"El Paso, TX"} let(:result) { stub("el paso", coordinates: [29, -95])} - it "should build from the map" do - Map.should_receive(:search).with(name).and_return(result) - Place.build(name) - end + it "should build from the map" do + Map.should_receive(:search).with(name).and_return(result) + Place.build(name) + end - it "should be place" do - Map.stub(:search).with(name).and_return(result) - Place.build(name).should be_a(Place) - end + it "should be place" do + Map.stub(:search).with(name).and_return(result) + Place.build(name).should be_a(Place) end +end describe "#to_s" do it "should use the city as the to_s" do - subject.stub(:name) { "Boston" } + subject.stub(:name) {"Boston"} subject.to_s.should eq("Boston") end end describe "#to_coordinates" do - it "should delegate to_coorinates to coordinates" do - subject.stub(:coordinates) { [5,5]} - subject.to_coordinates.should eq ([5,5]) + it "should use the coordinates as the to_s" do + subject.stub(:coordinates) {[29, -95]} + subject.to_coordinates.should eq([29, -95]) end end -end + + +end \ No newline at end of file diff --git a/spec/sales_person_spec.rb b/spec/sales_person_spec.rb index 08a6ce9..6a00326 100644 --- a/spec/sales_person_spec.rb +++ b/spec/sales_person_spec.rb @@ -1,30 +1,45 @@ -require_relative "../lib/sales_person" -require_relative "../lib/calculates_route" +require_relative '../lib/sales_person' +require_relative '../lib/calculates_route' +require 'rspec' -describe SalesPerson do - it "should have many cities" do - city = stub - subject.schedule_city(city) - subject.cities.should include(city) - end + describe SalesPerson do + it "should be able to schedule many cities" do + city = stub + subject.schedule_city(city) + subject.cities.should include(city) + end - it "should keep the cities only scheduled once" do - city = stub - expect{ + it "should not include the same city" do + city = stub + city = stub subject.schedule_city(city) subject.schedule_city(city) - }.to change(subject.cities,:count).by(1) - end + subject.cities.count.should eq(1) + end - it "should calculate a route via the CalculatesRoute" do - cities = [stub, stub, stub] - subject.stub(:cities) { cities } - CalculatesRoute.should_receive(:calculate).with(cities) - subject.route - end - it "should returns the route from CalculatesRoute" do - route_stub = [stub, stub] - CalculatesRoute.stub(:calculate) { route_stub } - subject.route.should eq(route_stub) + it "should find a starting point" do + city = stub + city.stub(name: "Austin, TX") + subject.schedule_city(city) + subject.find_city("Austin, TX").should eq(city) + end + it "should be able to calcuate the route via CalculatesRoute" do + start = stub(name: "Austin, TX") + point = stub(name: "Los Angeles, CA") + cities = [start, point] + subject.stub(:cities) {cities} + CalculatesRoute.should_receive(:calculate).with(cities, start) + subject.route("Austin, TX") + end + + it "should return the route from CalcuatesRoute" do + route = [stub("Austin, Tx"), stub("Los Angeles, CA")] + start = stub("Austin, TX") + cities = [stub, stub, stub] + CalculatesRoute.stub(:calculate) {route} + CalculatesRoute.stub(:route).and_return(route) + subject.route.(start).should eq(route) + + + end end -end