-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sockets-Chantal #29
base: master
Are you sure you want to change the base?
Sockets-Chantal #29
Changes from 8 commits
765037d
57c9d5f
9c577cd
08780ba
b5ef8bb
93116a9
cc6da63
0efa9aa
8775738
4d6ddf5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
require 'set' | ||
|
||
require_relative 'reservation' | ||
|
||
class Hotel | ||
NUM_ROOMS = 20 | ||
|
||
# rooms 1-20, reservations | ||
def initialize() | ||
@reservations = [] | ||
end | ||
|
||
# Access the list of all of the rooms in the hotel. | ||
def get_rooms | ||
(1..NUM_ROOMS).to_set | ||
end | ||
|
||
def make_reservation(start_date, end_date) | ||
# Validate the date range. | ||
validate_date_range(start_date, end_date) | ||
# Find room that's available. | ||
available_rooms = find_available_rooms(start_date, end_date) | ||
raise RuntimeError.new("there are no rooms available") if available_rooms.empty? | ||
room_number = available_rooms.to_a.sample | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call raising an error here - that seems like an appropriate way to indicate that the method can't continue. Instead of raising a |
||
# Create reservation. | ||
reservation = Reservation.new(room_number, start_date, end_date) | ||
# Store the reservation. | ||
@reservations << reservation | ||
# Return the reservation. | ||
return reservation | ||
end | ||
|
||
def find_available_rooms(start_date, end_date) | ||
available_rooms = get_rooms | ||
@reservations.each do |reservation| | ||
if reservation.start_date < end_date && reservation.end_date > start_date | ||
available_rooms.delete(reservation.room_number) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here, A cleaner approach might be to define a method @reservations.each do |reservation|
if reservation.overlap?(start_date, end_date)
available_rooms.delete(reservation.room_number)
end
end I know we hadn't read POODR ch 4 yet when you wrote this code, but this is what Metz is talking about when she says you should "ask for what instead of telling how". |
||
end | ||
return available_rooms | ||
end | ||
|
||
def validate_date_range(start_date, end_date) | ||
raise ArgumentError.new("the end date is before start date") unless end_date >= start_date | ||
end | ||
|
||
def get_reservations_inclusive(date) | ||
@reservations.find_all {|reservation| reservation.end_date >= date && reservation.start_date <= date} | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
class Reservation | ||
attr_reader :room_number, :start_date, :end_date | ||
|
||
ROOM_PRICE = 200 | ||
|
||
#room association, date range | ||
def initialize(room_number, start_date, end_date) | ||
@room_number = room_number #integer | ||
@start_date = start_date #time | ||
@end_date = end_date #time | ||
end | ||
|
||
def calculate_total_cost() | ||
total_nights = @end_date - @start_date #probably convert to integer after test | ||
total_nights = total_nights.to_i / (24 * 60 * 60) | ||
ROOM_PRICE * total_nights | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the decision to make this a method rather than storing the cost as an instance variable. That way if the number of nights or the cost per night were to change (say in a future version of the program), the total cost will automatically be correct. |
||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
require_relative 'spec_helper' | ||
|
||
describe "hotel" do | ||
NUM_BOOKED_ROOMS = Hotel::NUM_ROOMS - 5 | ||
|
||
before do | ||
@seventh = Time.parse("2018-07-07") | ||
@eleventh = Time.parse("2018-07-11") | ||
end | ||
|
||
let(:empty_hotel) do | ||
empty_hotel = Hotel.new | ||
end | ||
|
||
let(:booked_hotel) do | ||
booked_hotel = Hotel.new | ||
(NUM_BOOKED_ROOMS).times do | ||
booked_hotel.make_reservation(@seventh, @eleventh) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like this organization - having all of an empty, a mostly-booked and a fully-booked hotel available for your tests up front makes the process of testing much simpler. |
||
end | ||
booked_hotel | ||
end | ||
|
||
let(:fully_booked_hotel) do | ||
fully_booked_hotel = Hotel.new | ||
Hotel::NUM_ROOMS.times do | ||
fully_booked_hotel.make_reservation(@seventh, @eleventh) | ||
end | ||
fully_booked_hotel | ||
end | ||
|
||
it "get rooms" do | ||
rooms = empty_hotel.get_rooms | ||
expect(rooms.length).must_equal Hotel::NUM_ROOMS | ||
end | ||
|
||
describe "makes reservation" do | ||
it "make reservation for hotel with no reservations" do | ||
reservation = empty_hotel.make_reservation(@seventh, @eleventh) | ||
end | ||
|
||
it "make reservation for hotel with several reservations" do | ||
reservation = booked_hotel.make_reservation(@seventh, @eleventh) | ||
end | ||
|
||
it "make reservation for fully booked hotel" do | ||
expect{fully_booked_hotel.make_reservation(@seventh, @eleventh)}.must_raise RuntimeError | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are a number of questions around when specifically a room is available that these tests don't cover. In particular, if a hotel is fully booked for one range of dates and you get another request... No room is available if the dates:
The room is available if the dates:
|
||
|
||
it "make reservation with invalid dates" do | ||
expect{fully_booked_hotel.make_reservation(@eleventh, @seventh)}.must_raise ArgumentError | ||
end | ||
end | ||
|
||
describe "finds available rooms" do | ||
it "find available rooms when some are available" do | ||
available_rooms = booked_hotel.find_available_rooms(@seventh, @eleventh) | ||
expect(available_rooms.length).must_equal Hotel::NUM_ROOMS - NUM_BOOKED_ROOMS | ||
end | ||
|
||
it "find available rooms when none are available" do | ||
available_rooms = fully_booked_hotel.find_available_rooms(@seventh, @eleventh) | ||
expect(available_rooms.empty?).must_equal true | ||
end | ||
end | ||
|
||
it "get reservations inclusive" do | ||
inclusive_reservations = booked_hotel.get_reservations_inclusive(@eleventh) | ||
expect(inclusive_reservations.length).must_equal NUM_BOOKED_ROOMS | ||
end | ||
|
||
describe 'validate date range' do | ||
it 'invalid date range throws exception' do | ||
expect{empty_hotel.validate_date_range(@eleventh, @seventh)}.must_raise ArgumentError | ||
end | ||
|
||
it "valid date range throws no exception" do | ||
empty_hotel.validate_date_range(@seventh, @eleventh) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
require_relative 'spec_helper' | ||
|
||
describe "reservation" do | ||
it 'calculate_total_cost' do | ||
reservation = Reservation.new(2, Time.parse("2018-07-23"), Time.parse("2018-07-28")) | ||
expect(reservation.calculate_total_cost).must_equal 1000 | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this class be in a module?