Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
70dcbcc
added simplecov
thenora Mar 2, 2020
8b3e435
tested guard with room instantiation
thenora Mar 2, 2020
c55bccd
included framework from Ada
thenora Mar 2, 2020
b6a5f71
Added initialize to reservation & test
thenora Mar 3, 2020
d560747
added user stories for wave 1 in line
thenora Mar 4, 2020
a4b07d0
date_range tests for initalize and nights
thenora Mar 4, 2020
e4e57f6
tests start & end dates must be dates
thenora Mar 4, 2020
03aebc0
hotel_controller - added initialize and tests
thenora Mar 4, 2020
6854cef
hotel_controller - 1st version reserve_room method
thenora Mar 4, 2020
252baa3
moved methods around
thenora Mar 5, 2020
e0ae660
moved variables
thenora Mar 5, 2020
c51a21f
small changes
thenora Mar 5, 2020
2fd31ba
what am I even doing?
thenora Mar 6, 2020
31a03e0
test broken in hotel controler
thenora Mar 6, 2020
3368bbb
changed fikle names & added methods
thenora Mar 7, 2020
43dfd5f
changed file name for test
thenora Mar 7, 2020
82efcb2
updated variable names in tests
thenora Mar 7, 2020
05ee43a
updating tests
thenora Mar 7, 2020
f8a8697
wrote populate_calendar & tests
thenora Mar 7, 2020
b3e818f
added date_reservations method and tests
thenora Mar 7, 2020
abf10d6
Wave 1 complete
thenora Mar 8, 2020
fefa070
added date check
thenora Mar 8, 2020
7494369
added include? tests
thenora Mar 8, 2020
1a692d1
added more date range tests
thenora Mar 9, 2020
533fa64
redid available rooms to use @calendar
thenora Mar 9, 2020
bcb9fd6
more work on front desk tests
thenora Mar 9, 2020
eaf2905
more test updates
thenora Mar 9, 2020
4609df7
wave 2 complete
thenora Mar 9, 2020
4a0867d
deleted unused classes
thenora Mar 9, 2020
9bb1251
updated test helper to remove rooms
thenora Mar 9, 2020
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
Binary file added .DS_Store
Binary file not shown.
35 changes: 35 additions & 0 deletions lib/date_range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Hotel
class DateRange
attr_reader :start_date, :end_date
attr_accessor :dates

def initialize(start_date:, end_date:)
@start_date = start_date
@end_date = end_date
@dates = Array(@start_date .. @end_date)

# User: I want an exception raised when an invalid date range is provided, so that I can't make a reservation for an invalid date range

Choose a reason for hiding this comment

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

I like including the user stories as comments. 😄

if @end_date < @start_date || @start_date == @end_date
raise ArgumentError.new("Your check-out date must be after your check-in.")

Choose a reason for hiding this comment

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

It's helpful to include the bad arguments in your error messages:

Suggested change
raise ArgumentError.new("Your check-out date must be after your check-in.")
raise ArgumentError.new("Your check-out date (#{@start_date}) must be after your check-in (#{end_date}).")

end
end

def overlap?(daterange_instance)
overlap = !(daterange_instance.start_date >= end_date || daterange_instance.end_date <= start_date)
return overlap
Comment on lines +18 to +19

Choose a reason for hiding this comment

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

You don't have to assign this to a variable before you return it:

Suggested change
overlap = !(daterange_instance.start_date >= end_date || daterange_instance.end_date <= start_date)
return overlap
return !(daterange_instance.start_date >= end_date || daterange_instance.end_date <= start_date)

Also, you can simplify/clarify this using DeMorgan's Law and reversing the comparisons:

Suggested change
overlap = !(daterange_instance.start_date >= end_date || daterange_instance.end_date <= start_date)
return overlap
return daterange_instance.start_date < end_date && daterange_instance.end_date > start_date

end

def include?(date)
if date >= @start_date && date < @end_date
return true
else
return false
end
Comment on lines +23 to +27

Choose a reason for hiding this comment

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

You can directly return the condition here:

Suggested change
if date >= @start_date && date < @end_date
return true
else
return false
end
return date >= @start_date && date < @end_date

end

# calculate the number of nights for a reservation (end date is not a night)
def nights
return @dates.length - 1
end
end
end
105 changes: 105 additions & 0 deletions lib/front_desk.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
require_relative 'reservation'
require_relative 'date_range'

module Hotel
class FrontDesk
attr_accessor :reservations, :rooms, :calendar

def initialize
@rooms = (1..20).map { |i| i }

Choose a reason for hiding this comment

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

It looks like you're just using map to convert this to an array. You can use to_a for that:

Suggested change
@rooms = (1..20).map { |i| i }
@rooms = (1..20).to_a

@reservations = []
@calendar = {}
end

def populate_calendar(reservation)
temp = reservation.date_range.dates
temp.pop
temp.each do |date|
if !@calendar.key?(date)
@calendar[date] =[]
end
@calendar[date] << reservation
end
return @calendar
end
Comment on lines +14 to +24

Choose a reason for hiding this comment

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

I think you probably meant to copy the array here. This doesn't do that so you wind up changing dates.

Cleaner would be to ask for a range that excludes the end of dates (you can also use an unless to tidy up your condition):

Suggested change
def populate_calendar(reservation)
temp = reservation.date_range.dates
temp.pop
temp.each do |date|
if !@calendar.key?(date)
@calendar[date] =[]
end
@calendar[date] << reservation
end
return @calendar
end
def populate_calendar(reservation)
reservation.date_range.dates[0...-1].each do |date|
unless @calendar.key?(date)
@calendar[date] = []
end
@calendar[date] << reservation
end
return @calendar
end

Choose a reason for hiding this comment

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

Also, since this method doesn't directly address a user story I'd recommend making it private.


# User: I can access the list of all of the rooms in the hotel
def list_rooms
return @rooms
end
Comment on lines +27 to +29

Choose a reason for hiding this comment

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

You don't need this and the attr_accessor for @rooms. I'd recommend picking one or the other.


# User: I can make a reservation of a room for a given date range, and that room will not be part of any other reservation overlapping that date range
def reserve_room(requested_dates)
available_rooms = available_rooms(requested_dates)

book_room = available_rooms.first
new_reservation = Hotel::Reservation.new(
room: book_room,
date_range: requested_dates,
)
@reservations.push(new_reservation)
populate_calendar(new_reservation)
return new_reservation
end

# User: I can access the list of reservations for a specific date, so that I can track reservations by date
def date_reservations(date)
date_resv = @calendar[date]
return date_resv
end

# User: I access the list of reservations for a specified room and a given date range
# I split this user story into a handful of separate methods to perform different parts of the request

# returns an array of reservations for requested dates
def range_reservations(requested_dates)
range_resv = []
requested_dates.dates.each do |date|
if @calendar.key?(date)
range_resv.push(*@calendar[date])
end
end
range_resv = range_resv.uniq

return range_resv
end
Comment on lines +55 to +65

Choose a reason for hiding this comment

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

You can clean this up using select and flat_map:

Suggested change
def range_reservations(requested_dates)
range_resv = []
requested_dates.dates.each do |date|
if @calendar.key?(date)
range_resv.push(*@calendar[date])
end
end
range_resv = range_resv.uniq
return range_resv
end
def range_reservations(requested_dates)
return requested_dates.dates.select do |date|
@calendar.key?(date)
end.flat_map do |date|
@calendar[date]
end.uniq
end

(Since it's kind of obscure: flat_map is equivalent to doing a map followed by a flatten. It basically says "go through the input and produce an array out of the little arrays this block outputs".)


# search an array of reservations and return only the reservations for the specified room
def find_room_res(room_num, range_resv)
room_res = []
range_resv.each do |res|
if res.room == room_num
room_res.push(res)
end
end
room_res = room_res.uniq
return room_res
end

# User: I can view a list of rooms that are not reserved for a given date range, so that I can see all available rooms for that day
def available_rooms(requested_dates)
occupied_rooms = []
select_res = range_reservations(requested_dates)

select_res.each do |reservation|
occupied_rooms << reservation.room
end

empty_rooms = []
@rooms.each do |room|
unless occupied_rooms.include?(room)
empty_rooms << room
end
end
empty_rooms = empty_rooms.uniq

# User: I want an exception raised if I try to reserve a room during a date range when all rooms are reserved, so that I cannot make two reservations for the same room that overlap by date
if empty_rooms.length > 0
return empty_rooms
else
raise ArgumentError.new("Sorry, there are no rooms available. Please try other dates.")
end

end
end
end
20 changes: 20 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require_relative "date_range"

module Hotel
class Reservation
attr_reader :room, :date_range

def initialize(date_range:, room: nil)
@room = room
@date_range = date_range

end

# User: I can get the total cost for a given reservation
def cost
room_rate = 200
cost = @date_range.nights * room_rate
return cost
end
end
end
36 changes: 36 additions & 0 deletions refactor.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
TO DO:

Front Desk:

date_reservations
* Add raise argument error if date is not a date
* Add raise argument error if there are no reservations for the date

range_reservations
* Add raise argument error if date range is not a date range
* Add raise argument error if there are no reservations for the date range

available_rooms
* argument error if no rooms available isn't working in test

Front Desk Test:

available_rooms
* argument error if no rooms available isn't working in test

reserve_room
* add more nominal and edge tests

date_reservations
* add more nominal and edge tests

range_reservations
* add more nominal and edge tests

find_room_res
* add more nominal and edge tests

available_rooms
* raise argument error test not working - currently skipped


162 changes: 162 additions & 0 deletions test/date_range_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
require_relative "test_helper"


describe Hotel::DateRange do
before do
@start_date = Date.new(2021, 01, 01)
@end_date = Date.new(2021, 01, 03)
@start_date2 = Date.new(2021, 01, 01)
@end_date2 = Date.new(2021, 01, 02)
@range_inst = Hotel::DateRange.new(start_date: @start_date, end_date: @end_date)
@range_inst2 = Hotel::DateRange.new(start_date: @start_date2, end_date: @end_date2)
end

describe "constructor" do
it "is an instance of DateRange" do
expect(@range_inst).must_be_kind_of Hotel::DateRange
end

it "start_date is a Date" do
expect(@range_inst.start_date).must_be_kind_of Date
end

it "end_date is a Date" do
expect(@range_inst.end_date).must_be_kind_of Date
end

it "dates is an array" do
expect(@range_inst.dates).must_be_kind_of Array
end

it "can be initialized with two dates" do
expect(@range_inst.start_date).must_equal @start_date
expect(@range_inst.end_date).must_equal @end_date
end

it "raises an error if the end date is before the start date" do
expect { Hotel::DateRange.new(
start_date: Date.new(2021, 01, 01),
end_date: Date.new(2020, 12, 31)
) }.must_raise ArgumentError
end

it "raises an error if the end date is the same as the start date" do
expect { Hotel::DateRange.new(
start_date: Date.new(2021, 01, 01),
end_date: Date.new(2021, 01, 01)
) }.must_raise ArgumentError
end
end

describe "overlap?" do
it "returns true for the same range" do
start_date = Date.new(2021, 01, 01)
end_date = Date.new(2021, 01, 03)
test_range = Hotel::DateRange.new(
start_date: start_date,
end_date: end_date
)

expect(@range_inst.overlap?(test_range)).must_equal true
end

it "returns true for a contained range" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2021, 01, 01),
end_date: Date.new(2021, 01, 02)
)

expect(@range_inst.overlap?(test_range)).must_equal true
end

it "returns true for a range that overlaps in front" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2020, 12, 01),
end_date: Date.new(2021, 01, 02)
)

expect(@range_inst.overlap?(test_range)).must_equal true
end

it "returns true for a range that overlaps in the back" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2021, 1, 02),
end_date: Date.new(2021, 01, 06)
)

expect(@range_inst.overlap?(test_range)).must_equal true
end

it "returns true for a containing range" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2020, 12, 01),
end_date: Date.new(2021, 01, 12)
)

expect(@range_inst.overlap?(test_range)).must_equal true
end

it "returns false for a range starting on the end_date date" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2021, 01, 03),
end_date: Date.new(2021, 01, 06)
)

expect(@range_inst.overlap?(test_range)).must_equal false
end

it "returns false for a range ending on the start_date date" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2020, 12, 03),
end_date: Date.new(2021, 01, 01)
)

expect(@range_inst.overlap?(test_range)).must_equal false
end

it "returns false for a range completely before" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2020, 01, 03),
end_date: Date.new(2020, 01, 06)
)

expect(@range_inst.overlap?(test_range)).must_equal false
end

it "returns false for a date completely after" do
test_range = Hotel::DateRange.new(
start_date: Date.new(2022, 01, 03),
end_date: Date.new(2022, 01, 06)
)

expect(@range_inst.overlap?(test_range)).must_equal false
end
end

describe "include?" do
it "returns false if the date is clearly out" do
date = Date.new(2022,1,1)
expect(@range_inst.include?(date)).must_equal false
end

it "returns true for dates in the range" do
date = @start_date
expect(@range_inst.include?(date)).must_equal true
end

it "returns false for the end_date date" do
date = @end_date
expect(@range_inst.include?(date)).must_equal false
end
end

describe "nights" do
it "returns the correct number of nights" do
expect(@range_inst.nights).must_equal 2
end

it "returns a number" do
expect(@range_inst.nights).must_be_kind_of Numeric
end
end
end
Loading