Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
17 changes: 9 additions & 8 deletions lib/calculates_route.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
class CalculatesRoute

def self.calculate(points)

def self.calculate(points, starting_point)
remaining_points = points
route = []
route << remaining_points.slice!(0)
until remaining_points == [] do
route << remaining_points.slice!(remaining_points.index(starting_point))
until remaining_points == [] do
next_point = shortest_distance(route.last, remaining_points)
puts "from: #{route.last} ... to: #{next_point}"
route << remaining_points.slice!(remaining_points.index(next_point))

end
route
route
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)
distances.sort{|a,b| a.fetch(:distance) <=> b.fetch(:distance)}.first.fetch(:point)
end
end

end
9 changes: 5 additions & 4 deletions lib/map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ class Map

def self.search(terms)
Array(Geocoder.search(terms)).first
end
end

def self.distance_between(first, second)
Geocoder::Calculations.distance_between(first, second)
end
def self.distance_between(first, second)
Geocoder::Calculations.distance_between(first, second) #wrapping geocoder again
end
end

12 changes: 7 additions & 5 deletions lib/place.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
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|
p.name = name
p.coordinates = results.coordinates
p.coordinates = results.coordinates
end
end

def to_s
def to_s
name
end

def to_coordinates
coordinates
end
end

end
15 changes: 11 additions & 4 deletions lib/sales_person.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
class SalesPerson

attr_reader :cities

def initialize
@cities = []
@cities = []
end

def schedule_city(city)
@cities << city unless @cities.include?(city)
end

def route
CalculatesRoute.calculate(cities)
def find_point(start_name)
start = @cities.select {|city| city if city.name == start_name }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simplifiy this select to

start = @cities.select {|city| city.name == start_name }

The reason is that select works by keeping entries in the array where the block returns true. A simply example:

[1,4,5,6].select{|i| true}
=> [1,4,5,6]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further, since you are getting the first item, you can change to a find

def find_point(start_name)
  @cities.find {|city| city.name == start_name }
end

This works where it early escapes after finding a true element

[2,3,3,3,4,5].find {|i| i.odd?}
=> 3

start.first

end

def route(starting_point)
CalculatesRoute.calculate(cities, find_point(starting_point))
end
end
end
16 changes: 14 additions & 2 deletions salesperson.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
Dir["./lib/*.rb"].each {|file| require file }


phil = SalesPerson.new
phil.schedule_city(Place.build("Dallas, TX"))
phil.schedule_city(Place.build("El Paso, TX"))
phil.schedule_city(Place.build("Burbank, CA"))
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("Los Angeles, CA"))
phil.schedule_city(Place.build("San Diego, CA"))

starting_point = "Austin, TX"
puts phil.route(starting_point)








puts phil.route
22 changes: 12 additions & 10 deletions spec/calculates_route_spec.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
require_relative "../lib/calculates_route"
require_relative "../lib/place"
require_relative "../lib/calculates_route.rb"
require_relative "../lib/place.rb"

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")}
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)
starting_point = austin
inputs = [austin, dallas, el_paso, lubbock]
expected = [austin, dallas, lubbock, el_paso]
CalculatesRoute.calculate(inputs, starting_point).should eq(expected)

end
end
end
25 changes: 13 additions & 12 deletions spec/map_spec.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
require_relative "../lib/map"
require 'geocoder'
require_relative "../lib/map"
require 'geocoder'

describe Map do

describe ":search" do
describe Map do
describe ":search" do
it "should delegate search to geocoder" do
Geocoder.should_receive(:search).with("austin, tx")
Map.search("austin, tx")
Map.search("austin, tx") #wraping geocoder
end

it "should use the first item in the array" do
austin = stub("Austin")
austin = stub("Austin")
dallas = stub("Dallas")
Geocoder.stub(:search) {[austin, dallas]}
Map.search("austin, tx").should eq(austin)

end
end

describe ":distance" do
describe ":distance" do
it "should calculate distance between two sets of coordinates" do
alpha = stub
beta = stub
Geocoder::Calculations.should_receive(:distance_between).with(alpha, beta)
Map.distance_between(alpha, beta)
Map.distance_between(alpha, beta)
end
end
end
end
end
54 changes: 29 additions & 25 deletions spec/place_spec.rb
Original file line number Diff line number Diff line change
@@ -1,43 +1,47 @@
require_relative "../lib/place"
require_relative "../lib/map"


describe Place do

it "should have a name" 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])
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(: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 be place" do
Map.stub(:search).with(name).and_return(result)
Place.build(name).should be_a(Place)
end
it "should build from the map" do
Map.should_receive(:search).with(name).and_return(result)
Place.build(name)
end

describe "#to_s" do
it "should use the city as the to_s" do
subject.stub(:name) { "Boston" }
subject.to_s.should eq("Boston")
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.to_s.should eq("Boston")
end
end

describe "#to_coordinates" do
it "should use the coordinates as the to_s" do
subject.stub(:coordinates) {[29, -95]}
subject.to_coordinates.should eq([29, -95])

describe "#to_coordinates" do
it "should delegate to_coorinates to coordinates" do
subject.stub(:coordinates) { [5,5]}
subject.to_coordinates.should eq ([5,5])
end
end
end


end
67 changes: 41 additions & 26 deletions spec/sales_person_spec.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
require_relative "../lib/sales_person"
require_relative "../lib/calculates_route"
require_relative '../lib/sales_person'
require_relative '../lib/calculates_route'

describe SalesPerson do
it "should have many cities" do
city = stub
it "should have 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{
subject.schedule_city(city)
subject.cities.should include(city)
end

it "should keep the cities only scheduled once" do
city = stub
expect{
subject.schedule_city(city)
subject.schedule_city(city)
}.to change(subject.cities,:count).by(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)
end
subject.schedule_city(city)
}.to change(subject.cities,:count).by(1)

end

it "should find the starting_point" do
cities = [stub, stub, stub]
starting_point = [stub]
subject.find_point(starting_point).should eq(starting_point)

end

it "should calculate route via the CalculatesRoute" do
start = stub("Austin, TX")
point = stub("Los Angeles, CA")
cities = [start, point]
subject.stub(:cities) { cities }
CalculatesRoute.should_receive(:calculate).with(cities, start)
#subject.route(start)
end

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

end