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

Bianca Fernandez <Pipes> Hotel #34

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c4c35ba
Set up files - rake, spec_helper, date range, room, and reservation
biciclista22 Sep 5, 2017
05cdb21
Initialize method on DateRange with passing tests
biciclista22 Sep 7, 2017
a0addab
Changed Date.new to date parse to be able to take in strings and crea…
biciclista22 Sep 7, 2017
50b6952
create total cost method - learned how to call an instance method fro…
biciclista22 Sep 7, 2017
94a24d7
add tests to understand what is in the reservation array, beginfleshi…
biciclista22 Sep 8, 2017
e489640
Add #make_reservation Hotel class method with passing tests - lots of…
biciclista22 Sep 8, 2017
ab0ddc7
wave 1 complete with passing tests
biciclista22 Sep 9, 2017
3e183d5
remove instance variable of date list in hotel class to local variable
biciclista22 Sep 9, 2017
45e0568
create #room availability given a date range
biciclista22 Sep 9, 2017
9bbc3fa
add sort and uniq method call to room availaibility array
biciclista22 Sep 9, 2017
9e33f2b
availability functionality with passing tests - draft 2
biciclista22 Sep 9, 2017
f558bd9
wave 2 complete with passing tests - may need more scrutinizing tests
biciclista22 Sep 10, 2017
23c7790
add block and block spec and initial framework of block class and int…
biciclista22 Sep 10, 2017
fff14fd
Create two arrays - booked and available within Blockroom
biciclista22 Sep 10, 2017
c3f3211
Passing make block reservation method
biciclista22 Sep 10, 2017
a49f9f7
Can book rooms in a given block
biciclista22 Sep 10, 2017
3489cb0
Can check if block has any available rooms
biciclista22 Sep 11, 2017
729c650
Correction to availability logic to go into actual room array within …
biciclista22 Sep 11, 2017
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
9 changes: 9 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'rake/testtask'

Rake::TestTask.new do |t|
t.libs = ["lib"]
t.warning = true
t.test_files = FileList['specs/*_spec.rb']
end

task default: :test
48 changes: 48 additions & 0 deletions lib/block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require_relative 'date_range'
require_relative 'reservation'
require_relative 'hotel'

module Hotel

class BlockRoom < Reservation

attr_reader :check_in, :check_out, :num_of_rooms, :discount, :block_of_rooms

attr_accessor :available_rooms, :booked_rooms

## just creating a block of rooms that have not been booked yet##
def initialize(check_in, check_out, num_of_rooms = 5, client = nil, discount = 15, cost = 200)

super(check_in, check_out, cost)
@discount = discount
@reservation_array << @discount

if num_of_rooms > 5
return raise ArgumentError.new("You cannot reserve a block with more than 5 rooms")
end

@num_of_rooms = num_of_rooms
@reservation_array << @num_of_rooms

@block_of_rooms = []
@reservation_array << block_of_rooms

@available_rooms = @block_of_rooms
@reservation_array << @available_rooms

@booked_rooms = []
@reservation_array << @booked_rooms


end #initialize

def check_if_block_has_available_rooms
if @available_rooms.length >= 1
return true
else
return raise ArgumentError.new("It appears there are no available rooms in block")
end
end

end #class
end#module
21 changes: 21 additions & 0 deletions lib/date_range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

module Hotel

class DateRange

attr_reader :check_in, :check_out

def initialize(check_in, check_out)
@check_in = Date.parse(check_in)
@check_out = Date.parse(check_out)

if @check_in > @check_out
raise ArgumentError.new("Invalid date range")
end

Choose a reason for hiding this comment

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

Would it be an error to have the checkin and checkout on the same day?

end



end #class

end #hotel
189 changes: 189 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
require_relative 'reservation'
require_relative 'block.rb'
require_relative 'date_range'

module Hotel

class Hotel

attr_reader :rooms, :price, :reservation_collection, :block_reservation_collection, :reservation_made

def initialize(num_of_rooms, price)
@rooms = []
room_num = 0
num_of_rooms.times do |room|
room_num += 1

Choose a reason for hiding this comment

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

Why not something like

@rooms = (1..num_of_rooms).to_a

@rooms << room_num
end #loop

@price = price
@reservation_collection = []
@block_reservation_collection = []
end #initialize

def make_reservation(check_in, check_out, room_num)
if room_availability(check_in, check_out).include?(room_num)
@reservation_made = Reservation.new(check_in, check_out, room_num)
@reservation_collection << @reservation_made

Choose a reason for hiding this comment

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

This method looks good! Very clear what's going on.

else
raise ArgumentError.new("It appears the room you requested is booked during that date range")
end
# @reservation_collection << @reservation_made
end


def make_block_reservation(check_in, check_out, num_of_rooms)
available_rooms = room_availability(check_in, check_out)
if available_rooms.length >= num_of_rooms
block_reservation = BlockRoom.new(check_in, check_out, num_of_rooms)
block_reservation.block_of_rooms << available_rooms.pop(num_of_rooms)
@block_reservation_collection << block_reservation
return block_reservation.block_of_rooms
else
return raise ArgumentError.new("We do not have enough rooms to reserve a block")
end
end

# ability to reserve a room within a block of rooms
#needs to match the date range of the block
def reserve_room_in_block(check_in, check_out, num_of_rooms)

Choose a reason for hiding this comment

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

I'm not sure I'm convinced by this method signature. What if two blocks have the same checkin/checkout dates and the same number of rooms? Instead, you should pass in either some sort of ID for the block, or the BlockRoom instance itself.

check_in = Date.parse(check_in)
check_out = Date.parse(check_out)

@block_reservation_collection.each do |entry|
if check_in == entry.check_in && check_out == entry.check_out
if entry.available_rooms[0].length >= num_of_rooms
num_of_rooms.times do
entry.booked_rooms << entry.available_rooms[0].pop
end
return entry.booked_rooms
end
end
end
end

def blocked_rooms_availability(check_in, check_out)
check_in = Date.parse(check_in)
check_out = Date.parse(check_out)

@block_reservation_collection.each do |entry|
if check_in == entry.check_in && check_out == entry.check_out
if entry.available_rooms[0].length >= 0
return true
else false
end
end
end
end

def date_list_of_reservations(date)
date_list = []
date = Date.parse(date)
@reservation_collection.each do |entry|
# binding.pry
if entry.check_in <= date && entry.check_out >= date
date_list << [entry.room_num, entry.check_in.to_s, entry.check_out.to_s]
end

Choose a reason for hiding this comment

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

This check, that the date falls within the reservation, would be a great candidate for an instance method on DateRange. Then you could say something like if entry.date_range.contains?(date).

end
return date_list
end #def

def room_availability(check_in, check_out)
#can be string with dates
rooms_available = @rooms.clone

Choose a reason for hiding this comment

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

I like that you've made getting a list of available rooms its own method - this both DRYs up your code and makes testing easier.

# [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
check_in = Date.parse(check_in)
check_out = Date.parse(check_out)

if check_in > check_out
raise ArgumentError.new("Invalid date range")
end

@reservation_collection.each do |entry|
if check_in < entry.check_in && check_in < entry.check_out && check_out < entry.check_out && check_out > entry.check_in

Choose a reason for hiding this comment

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

Woah, this logic is super complicated! I have a few thoughts about it:

  • You ought to be able to take advantage of the bounds checking in DateRange to simplify this logic, since you know check_in < check_out
  • This is pretty hard to read - my eyes immediately start to glaze over just looking at it. Might be a good place to leave a big comment explaining what you intended.
  • You have almost exactly the same logic repeated a little lower for room blocks.
  • This logic seems like it's more related to a DateRange than it is to a Hotel. Maybe you could add it there as an instance method DateRange#overlap?(checkin, checkout). Then this big complex block could be shortened to
    if entry.date_range.overlap?(check_in, check_out)
      rooms_available.delete(entry.room_num)
    end
    That would also let you DRY out the repeated code below.

Choose a reason for hiding this comment

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

Making it an instance method would also make it way easier to test!

rooms_available.delete(entry.room_num)
elsif check_in > entry.check_in && check_in < entry.check_out && check_out < entry.check_out && check_out > entry.check_in
rooms_available.delete(entry.room_num)
elsif check_in > entry.check_in && check_in < entry.check_out && check_out == entry.check_out && check_out > entry.check_in
rooms_available.delete(entry.room_num)
elsif check_in < entry.check_in && check_in < entry.check_out && check_out > entry.check_in && check_out == entry.check_out
rooms_available.delete(entry.room_num)
elsif check_in > entry.check_in && check_in < entry.check_out && check_out > entry.check_out
rooms_available.delete(entry.room_num)
elsif check_in == entry.check_in && check_in < entry.check_out && check_out > entry.check_in && check_out > entry.check_in
rooms_available.delete(entry.room_num)
end
end

@block_reservation_collection.each do |entry|
if check_in < entry.check_in && check_in < entry.check_out && check_out < entry.check_out && check_out > entry.check_in
entry.block_of_rooms[0].each do |room|
rooms_available.delete(room)
end
elsif check_in > entry.check_in && check_in < entry.check_out && check_out < entry.check_out && check_out > entry.check_in
entry.block_of_rooms[0].each do |room|
rooms_available.delete(room)
end
elsif check_in > entry.check_in && check_in < entry.check_out && check_out == entry.check_out && check_out > entry.check_in
entry.block_of_rooms[0].each do |room|
rooms_available.delete(room)
end
elsif check_in < entry.check_in && check_in < entry.check_out && check_out > entry.check_in && check_out == entry.check_out
entry.block_of_rooms[0].each do |room|
rooms_available.delete(room)
end
elsif check_in > entry.check_in && check_in < entry.check_out && check_out > entry.check_out
entry.block_of_rooms[0].each do |room|
rooms_available.delete(room)
end
elsif check_in == entry.check_in && check_in < entry.check_out && check_out > entry.check_in && check_out > entry.check_in
entry.block_of_rooms[0].each do |room|
rooms_available.delete(room)
end
end
end
return rooms_available
end #room_availability

end #class
end #module




















### second round of logic ### does not work because it will list rooms that are available for a given date range and not couple if the room is taken for another date


# if check_in == entry.check_in && check_in < entry.check_out && check_out > entry.check_in && check_out < entry.check_out
# false
# binding.pry
#
# elsif check_in< entry.check_in && check_out == entry.check_in && check_in < entry.check_out
# rooms_available << entry.room_num
# # elsif check_in < entry.check_in && check_in < entry.check_out && check_out == entry.check_in
# # rooms_available << entry.room_num
# elsif check_in == entry.check_out && check_out > entry.check_out
# rooms_available << entry.room_num
# elsif check_in > entry.check_out
# rooms_available << entry.room_num
# # elsif check_in < entry.check_in && check_out < entry.check_in && check_in < entry.check_out
# # rooms_available << entry.room_num
# end
33 changes: 33 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require_relative 'date_range'#take note this needs to be included at the top
# require 'Date'

module Hotel

class Reservation

attr_reader :check_in, :check_out, :date_range, :room_num, :cost, :reservation_array

def initialize(check_in, check_out, room_num, cost = 200)
@reservation_array = []

Choose a reason for hiding this comment

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

I'm not sure I understand what the reservation_array is for. Looks like you just put all the attributes for the reservation in it? I don't see that it's used by any of the rest of your code.

Choose a reason for hiding this comment

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

The more I think about this the more it concerns me. Next time we've got project time, come see me - I want to hear what you're thinking.


@date_range = DateRange.new(check_in, check_out)
@check_in = @date_range.check_in
@check_out = @date_range.check_out

Choose a reason for hiding this comment

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

If you're encapsulating the checkin and checkout dates in a DateRange, the you should not also store them as individual instance variables. If someone wants access to a reservation's dates, they'll have to go through the date range.



@reservation_array << @date_range

@room_num = room_num
@reservation_array << @room_num

@cost = cost
@reservation_array << @cost
end #initialize

def total_cost
num_nights = (@date_range.check_out - @date_range.check_in).to_i
return num_nights * @cost
end

end #reservation
end #module
48 changes: 48 additions & 0 deletions specs/block_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require_relative 'spec_helper'

describe "Block child class" do

describe "initialization" do
before do
@block = Hotel::BlockRoom.new('sept 1 2017', 'sept 2 2017', 3, "Fernandez", 10)
end

it "Can create an instance of block" do
@block.must_be_instance_of Hotel::BlockRoom
end

it "Can call methods regarding instance methods created" do
@block.reservation_array.must_be_instance_of Array
@block.num_of_rooms.must_equal 3
@block.discount.must_equal 10
@block.check_in.must_be_instance_of Date
@block.check_out.must_be_instance_of Date
@block.block_of_rooms.must_be_instance_of Array
@block.cost.must_equal 200
@block.booked_rooms.must_be_instance_of Array
@block.available_rooms.must_be_instance_of Array
end

it "Will return error message if try to book more than 5 rooms in a block" do
proc {Hotel::BlockRoom.new('today', 'tomorrow', 6)}.must_raise ArgumentError
end

end

describe "check if block has rooms available" do
before do
@block = Hotel::BlockRoom.new('sept 1 2017', 'sept 2 2017', 3, "Fernandez", 10)
end

it "Can raise an argument if there aren't rooms available" do
@block.available_rooms = []
proc {@block.check_if_block_has_available_rooms}.must_raise ArgumentError
end

it "Can return an array of available rooms" do
@block.available_rooms = [2,3,4]
@block.check_if_block_has_available_rooms.must_equal true
end
end

end #block describe
24 changes: 24 additions & 0 deletions specs/date_range_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require_relative 'spec_helper'

describe "DateRange class" do
let(:check_in) {"Sept 9 2017"}
let(:check_out) {"Sept 15 2017"}

it "Can be instantiated" do
Hotel::DateRange.new(check_in, check_out).must_be_instance_of Hotel::DateRange
end

it "Allows access to check_in instance variable" do
new_hotel = Hotel::DateRange.new(check_in, check_out)
new_hotel.check_in.must_be_instance_of Date
new_hotel.check_out.must_be_instance_of Date
end

it "Checks for invalid date entry - if check in is after check out date" do
check_in_1 = "Sept 9 2017"
check_out_1 = "Sept 8 2017"

Choose a reason for hiding this comment

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

You might include an explicit check here for when the dates are the same. Whether or not it's a legal range, I feel like it's an interesting case.

proc {Hotel::DateRange.new(check_in_1, check_out_1)}.must_raise ArgumentError
end


end
Loading