Skip to content
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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
44 changes: 44 additions & 0 deletions lib/block.rb
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

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.

@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 }

Choose a reason for hiding this comment

The 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

Choose a reason for hiding this comment

The 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
32 changes: 32 additions & 0 deletions lib/calendar.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module Calendar
def Calendar.date_range_include?(reservation, date)

Choose a reason for hiding this comment

The 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 Reservation class or pulled into instance method of a DateRange class? that way you could do?

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
2 changes: 2 additions & 0 deletions lib/full_block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class NoRoomsAvailableInBlock < StandardError
end
2 changes: 2 additions & 0 deletions lib/full_room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class RoomNotAvailable < StandardError
end
23 changes: 23 additions & 0 deletions lib/reservation.rb
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
165 changes: 165 additions & 0 deletions lib/room_reservation.rb
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

Choose a reason for hiding this comment

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

This class seems like it would be better named something like ReservationManager. Something that describes it's function.

Room = Struct.new(:id, :cost, :block_reserved)

Choose a reason for hiding this comment

The 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)

Choose a reason for hiding this comment

The 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)

Choose a reason for hiding this comment

The 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
10 changes: 10 additions & 0 deletions refactors.txt
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

Choose a reason for hiding this comment

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

Check out my comment above

to better rework it

Loading