-
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
Ports - Laneia #45
base: master
Are you sure you want to change the base?
Ports - Laneia #45
Changes from all commits
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,44 @@ | ||
require_relative "full_block" | ||
|
||
module Hotel | ||
class Block | ||
attr_reader :name, :check_in, :check_out, :rooms, :rate | ||
|
||
def initialize(name, check_in, check_out, block, rate) | ||
check_number_of_rooms(block) | ||
@name = name | ||
@check_in = check_in | ||
@check_out = check_out | ||
@rooms = block | ||
@rate = rate | ||
end | ||
|
||
def check_number_of_rooms(block) | ||
if block.length > 5 | ||
raise StandardError, "Maximum of 5 rooms per room block" | ||
end | ||
end | ||
|
||
def available | ||
available_rooms = rooms.find_all { |room| room.block_reserved == nil } | ||
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. Does this mean that a room can only be in one block at a time? What about two blocks on different dates? |
||
|
||
if available_rooms.empty? | ||
raise NoRoomsAvailableInBlock, "No rooms currently available in this block" | ||
else | ||
return available_rooms | ||
end | ||
end | ||
|
||
def set_blocked_room_rate | ||
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. This method doesn't make too much sense due to the fact that the room's rate only change for reservations within the block, not normal reservations. |
||
rooms.each do |room| | ||
room.cost = rate | ||
end | ||
end | ||
|
||
def reserve_room | ||
room = self.available.first | ||
room.block_reserved = true | ||
return room | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
module Calendar | ||
def Calendar.date_range_include?(reservation, date) | ||
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. It's good to have these methods, but wouldn't it make sense to make them instance methods of the my_reservation.includes(date)
my_reservation.does_not_overlap(other_reservation) |
||
if (reservation.check_in...reservation.check_out).cover?(date) | ||
return true | ||
else | ||
return false | ||
end | ||
end | ||
|
||
def Calendar.date_ranges_exclusive?( | ||
old_check_in, | ||
old_check_out, | ||
new_check_in, | ||
new_check_out) | ||
existing_range_array = date_range_array(old_check_in, old_check_out) | ||
|
||
new_range_array = date_range_array(new_check_in, new_check_out) | ||
|
||
intersecting_dates = existing_range_array & new_range_array | ||
|
||
if intersecting_dates.empty? | ||
return true | ||
else | ||
return false | ||
end | ||
end | ||
|
||
def Calendar.date_range_array(check_in, check_out) | ||
date_range = check_in...check_out | ||
return date_range.to_a | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class NoRoomsAvailableInBlock < StandardError | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class RoomNotAvailable < StandardError | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
module Hotel | ||
class Reservation | ||
attr_reader :room, :check_in, :check_out | ||
|
||
def initialize(room, check_in, check_out) | ||
check_date_range(check_in, check_out) | ||
@room = room | ||
@check_in = check_in | ||
@check_out = check_out | ||
end | ||
|
||
def check_date_range(check_in, check_out) | ||
if check_out <= check_in | ||
raise StandardError, "Invalid date range provided" | ||
end | ||
end | ||
|
||
def reservation_cost | ||
days_reserved = check_out - check_in | ||
return days_reserved.to_i * room.cost | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
require "date" | ||
require_relative "calendar" | ||
require_relative "reservation" | ||
require_relative "block" | ||
require_relative "full_room" | ||
|
||
module Hotel | ||
class RoomReservation | ||
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. This class seems like it would be better named something like |
||
Room = Struct.new(:id, :cost, :block_reserved) | ||
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. You don't seem to use this struct... |
||
|
||
attr_reader :rooms | ||
attr_accessor :reservations, :blocks | ||
|
||
def initialize | ||
@rooms = populate_rooms | ||
@reservations = [] | ||
@blocks = [] | ||
end | ||
|
||
def populate_rooms | ||
rooms_array = [] | ||
|
||
20.times do |id| | ||
room = Room.new((id + 1), 200) | ||
rooms_array << room | ||
end | ||
|
||
return rooms_array | ||
end | ||
|
||
def list_rooms | ||
return rooms | ||
end | ||
|
||
def find_room_by_id(room_id) | ||
return rooms.find { |room| room.id == room_id } | ||
end | ||
|
||
def list_reservations(date) | ||
list_of_reservations = [] | ||
|
||
reservations.each do |reservation| | ||
if Calendar.date_range_include?(reservation, date) | ||
list_of_reservations << reservation | ||
end | ||
end | ||
|
||
return list_of_reservations | ||
end | ||
|
||
def list_available_rooms(check_in, check_out) | ||
reserved_rooms = [] | ||
|
||
reservations.each do |reservation| | ||
unless Calendar.date_ranges_exclusive?( | ||
reservation.check_in, | ||
reservation.check_out, | ||
check_in, | ||
check_out | ||
) | ||
reserved_rooms << reservation.room | ||
end | ||
end | ||
|
||
unavailable_rooms = reserved_rooms + find_blocked_rooms(check_in, check_out) | ||
|
||
available_rooms = rooms.dup | ||
|
||
unavailable_rooms.each do |unavailable_room| | ||
available_rooms.delete_if { |room| room.id == unavailable_room.id } | ||
end | ||
|
||
return available_rooms | ||
end | ||
|
||
def new_reservation(room_id, check_in, check_out) | ||
room = find_room_by_id(room_id) | ||
room_unavailable?(room, check_in, check_out) | ||
new_reservation = Hotel::Reservation.new(room, check_in, check_out) | ||
reservations << new_reservation | ||
return new_reservation | ||
end | ||
|
||
def room_unavailable?(room, check_in, check_out) | ||
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 method, but I think it should be a private helper method. |
||
unless list_available_rooms(check_in, check_out).include?(room) | ||
raise RoomNotAvailable, "Room not available for the given dates" | ||
end | ||
end | ||
|
||
def find_block(name) | ||
found_block = blocks.find { |block| block.name == name } | ||
return found_block | ||
end | ||
|
||
def find_blocked_rooms(check_in, check_out) | ||
blocked_rooms = [] | ||
|
||
blocks.each do |block| | ||
unless Calendar::date_ranges_exclusive?( | ||
block.check_in, | ||
block.check_out, | ||
check_in, | ||
check_out | ||
) | ||
block.rooms.each do |room| | ||
blocked_rooms << room | ||
end | ||
end | ||
end | ||
|
||
return blocked_rooms | ||
end | ||
|
||
def block_available_rooms(check_in, check_out, number_of_rooms, rate) | ||
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. This should also be a private helper method. |
||
available_rooms = list_available_rooms(check_in, check_out) | ||
|
||
block = [] | ||
|
||
number_of_rooms.times do |i| | ||
block << available_rooms[i].dup | ||
end | ||
|
||
if block.length < number_of_rooms | ||
raise StandardError, "There are not enough available rooms for the given dates to create this room block" | ||
end | ||
|
||
return block | ||
end | ||
|
||
def new_block(name, check_in, check_out, number_of_rooms, rate) | ||
block_of_rooms = block_available_rooms( | ||
check_in, | ||
check_out, | ||
number_of_rooms, | ||
rate | ||
) | ||
|
||
new_block = Hotel::Block.new( | ||
name, | ||
check_in, | ||
check_out, | ||
block_of_rooms, | ||
rate | ||
) | ||
|
||
new_block.set_blocked_room_rate | ||
|
||
@blocks << new_block | ||
return new_block | ||
end | ||
|
||
def new_block_reservation(name) | ||
block = find_block(name) | ||
room = block.reserve_room | ||
new_reservation = Hotel::Reservation.new(room, block.check_in, block.check_out) | ||
reservations << new_reservation | ||
return new_reservation | ||
end | ||
|
||
def set_room_rate(room_id, custom_rate) | ||
room = rooms.find { |room| room.id == room_id } | ||
room.cost = custom_rate | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
1 - I would like to make a Room class because although it is unnecessary for this | ||
project I think it would lend itself to greater future proofing as new rooms could | ||
be added with new attributes as well (like cost differences) | ||
|
||
2 - Test data read from a CSV file could have been more thorough and led to better | ||
tests | ||
|
||
3 - I'm not sure that I like Calendar being a separate module but I'm not sure how | ||
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. Check out my comment above |
||
to better rework it | ||
|
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.
You should also do something to verify the dates here.