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

Tanja Stroble -- Hotel -- Carets #29

Open
wants to merge 14 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
Binary file added .DS_Store
Binary file not shown.
11 changes: 11 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
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
26 changes: 26 additions & 0 deletions lib/block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Property

class Block < Range

attr_reader :rooms, :price, :availability, :reservations

def initialize(rooms, check_in, check_out, price)

raise ArgumentError.new "Cannot accomodate block reservation
for more than five rooms at a time." if rooms.length > 5
raise ArgumentError.new "Must specify at least one room." if rooms.empty?
super(check_in, check_out)
@rooms = []
@available = rooms.clone
@reservations = []
@price = 150 #discounted
end

def reserve_block(room)
raise ArgumentError.new "No availability" if @availability.empty?
reservation = @available.pop(room)
@reservations << reservation
return reservation
end
end
end
82 changes: 82 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
require_relative 'reservation'
require_relative 'block'
require_relative 'range'
require 'date'

module Property

class Hotel

attr_reader :reservations, :rooms, :room_price

def initialize
@rooms = (1..20).to_a
@room_price = 200
@reservations = []
@reserved_blocks = []
end

def list_reservations(dates)
@reservations.select { |rez| rez.contains(dates) }
end


def available(check_in, check_out)
dates = Range.new(check_in, check_out)
available = @rooms

overlap_blocks = @reserved_blocks.select do |block|
block.overlap?(dates)
end
blocked_rooms = overlap_blocks.reduce([]) do |memo, block|
memo += block.rooms
end
available -= blocked_rooms

overlap = @reservations.select do |rez|
rez.overlap?(dates)
end
already_reserved = overlap.map do |rez|
rez.room
end
available -= already_reserved
return available
end


def reserve_room(room, check_in, check_out)
raise ArgumentError.new "Room unavailable." unless @rooms.include? room
raise ArgumentError.new "Room #{room}is booked between
# #{check_in} and #{check_out}" unless available(check_in, check_out).include? room

room_rez = Reservation.new(room, check_in, check_out, @room_price)
@reservations << room_rez

return room_rez
end


def hotel_block(room_qty, check_in, check_out, price)
rooms = available(check_in, check_out)

raise ArgumentError "Insufficient room availability" if rooms.length < room_qty

block = Property::Block.new(rooms.first(room_qty), check_in, check_out, price)
rooms = available(check_in, check_out)

if rooms.length < room_qty
raise ArgumentError("Not enough rooms available")
end

@reserved_blocks << block
return block
end


def reserve_from_block(block)
room = block.reserve_room
room_rez = Reservation.new(room, block.check_in, block.check_out, block.price)
end

end
end
41 changes: 41 additions & 0 deletions lib/range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'date'

module Property

class Range

class InvalidDateRange < StandardError ; end

attr_reader :check_in, :check_out

def initialize(check_in, check_out)

unless check_in < check_out
raise InvalidDateRange.new("Invalid date range") #return true ?
end

@check_in = check_in
@check_out = check_out
end

# def valid?
# unless @check_in < @check_out
# raise ArgumentError.new "Invalid date range" #return true ?
# end
# return true
# end

def overlap?(date)
if @check_in < date.check_in && @check_out > date.check_out ||
@check_in < date.check_in && @check_out < date.check_out
return false
else
return true
end
end

def num_nights
return @check_out - @check_in
end
end
end
21 changes: 21 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require_relative 'range'

module Property

class Reservation < Range

attr_reader :room, :price

def initialize(room, check_in, check_out, price)
@room = room
@price = 200
# @dates = Property::Range.new(check_in, check_out)
# @total_price = @dates.num_nights * 200
super(check_in, check_out)
end

def total_price
return num_nights * @price
end
end
end
Binary file added specs/.DS_Store
Binary file not shown.
35 changes: 35 additions & 0 deletions specs/block_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require_relative 'spec_helper'
require_relative '../lib/block'

describe 'Block' do

before do
@check_in = Date.new(2017, 5, 5)
@check_out = @check_in + 3
@price = 150
end

it "block is a subclass of Range"do
@rooms = [5, 12, 15]
@reserved_block = Property::Block.new(@rooms, @check_in, @check_out, @price)
@reserved_block.must_be_kind_of Property::Range
end

it "A block can contain a maximum of 5 rooms" do
@rooms = [1, 2, 3, 4, 5, 6]
proc {@reserved_block = Property::Block.new(@rooms, @check_in, @check_out, @price)}.must_raise ArgumentError
end

it "block cannot be booked if no rooms available" do
@rooms = []
proc {@reserved_block = Property::Block.new(@rooms, @check_in, @check_out, @price)}.must_raise ArgumentError
end

it "block rooms must appear in reservations once booked" do
@rooms = [5, 12, 15]
@reserved_block = Property::Block.new(@rooms, @check_in, @check_out, @price)
@reserved_block.rooms.each do |room|
@reservations.must_include room
end
end
end
114 changes: 114 additions & 0 deletions specs/hotel_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
require_relative 'spec_helper'
require_relative '../lib/hotel'

describe 'Hotel' do

before do
@test_hotel = Property::Hotel.new
end

it "can be initialized" do
@test_hotel.must_be_instance_of Property::Hotel
end
it "responds to its attr_reader" do
@test_hotel.must_respond_to :reservations
@test_hotel.must_respond_to :rooms
@test_hotel.must_respond_to :room_price
end

it "can access the list of all of the rooms in the hotel" do
@test_hotel.rooms.must_equal (1..20).to_a
end

it "there should be 20 total rooms" do
@test_hotel.rooms.count.must_equal 20
end

it "room always costs $200/night" do
@test_hotel.room_price.must_equal 200
end
end

describe "reserve_room" do

before do
@test_hotel = Property::Hotel.new
@check_in = Date.new(2017, 05, 05)
@check_out = @check_in + 3
end


it "cannot book invalid room number" do
room = "garbage"
proc {@test_hotel.reserve_room(room, @check_in, @check_out)}.must_raise ArgumentError
end

it "raises an error if tried to double-book room " do
room = 5
@test_hotel.reserve_room(room, @check_in, @check_out)
proc {@test_hotel.reserve_room(room, @check_in, @check_out)}.must_raise ArgumentError
end

it "adds the reservation to @reservations" do
test_rez = @test_hotel.reserve_room(10, @check_in, @check_out)
@test_hotel.reservations.must_include test_rez
end

it "can access the list of reservations for a specific date" do
rez = @test_hotel.reserve_room(15, @check_in, @check_out)
@test_hotel.reservations.must_include rez
end

it "I can get the total cost for a given reservation" do
rez = @test_hotel.reserve_room(20, @check_in, @check_out)
rez.total_price.must_equal 600
end

it "I can view a list of rooms that are not reserved for a given date range" do
@test_hotel.reserve_room(3, @check_in, @check_out)
@test_hotel.available(@check_in, @check_out).include?(3).must_equal false
end

it "can book a room that is available" do
excluding_one_room = @test_hotel.reserve_room(2, @check_in, @check_out)
available_room = @test_hotel.available(@check_in, @check_out).first
booking_available_room = @test_hotel.reserve_room(available_room, @check_in, @check_out)
@test_hotel.reservations.must_include booking_available_room
@test_hotel.reservations.length.must_equal 2
end
end

describe "block functionality" do
before do
@test_hotel = Property::Hotel.new
@room_qty = 3
@check_in = Date.new(2017, 5, 5)
@check_out = @check_in + 3
@price = 150
# @block = @test_hotel.hotel_block(@room_qty, @check_in, @check_out, @price)
end

it "cannot book zero rooms " do
proc {@test_hotel.hotel_block(0, @check_in, @check_out, @price)}.must_raise ArgumentError
end
end
# it "correct number of rooms booked in a block " do
# @block = @test_hotel.hotel_block(@room_qty, @check_in, @check_out, @price)
# @block.rooms.length.must_equal @room_qty
# end

# it "once block booked, reserved_blocks reflects it" do
# @block = @test_hotel.hotel_block(@room_qty, @check_in, @check_out, @price)
# @reserved_blocks.must_include @block
# end


# it "reservation cannot be made for room when check in and checkout dates overlap" do
# rez = @test_hotel.reserve_room(3, @check_in, @check_out)
# rez2 = @test_hotel.reserve_room(3, @check_out, (@check_out+ 3))
# @test_hotel.reservations.include?(rez2).must_equal false
# end
#this test fails. I need to strategize and decide how I'll make sure check in is
#not available on the day of check out for the same room.
#one way I am thinking of doing this is to set time, but that just introduces more
#complexity ...
Loading