Skip to content
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.
15 changes: 15 additions & 0 deletions lib/block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'date'

module HotelBooking
class Block
attr_reader :check_in, :check_out, :rooms, :discounted_rate

def initialize(check_in, check_out, rooms = [], discounted_rate)
@check_in = check_in

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

When a class only has instance variables and no methods, either it doesn't need to be a class, or you're doing that class's work somewhere else. This class should be able to make its own reservations, and report information about when it is available.

@check_out = check_out
@rooms = rooms
@discounted_rate = discounted_rate
end
end
end

137 changes: 137 additions & 0 deletions lib/manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
require_relative 'reservation'
require_relative 'block'
require 'pry'

module HotelBooking
class Manager
COST = 200

def initialize
@rooms = []
(1..20).each do |room_number|
@rooms << room_number
end
@rooms.freeze
@id = 0
@reservation_by_id = {}
@reservations_by_date = {}
@blocks_by_date = {}
end

def list_rooms
return @rooms
end

def reserve_room(check_in , check_out)
validate_dates(check_in, check_out)
room = available_rooms(check_in, check_out).first
id = get_next_id
cost = ((check_out - check_in).to_i) * COST
reservation = Reservation.new(check_in, check_out, id, room, cost)
(check_in...check_out).each do |date|
if @reservations_by_date.has_key?(date) == false
reservations = []
reservations << reservation
@reservations_by_date.store(date, reservations)
@reservation_by_id.store(id,reservation)
else
@reservations_by_date[date] << reservation
@reservation_by_id.store(id,reservation)
end
end
return reservation
end

def get_reservation_by_date(date)
if @reservations_by_date[date] != nil
result = @reservations_by_date[date]
else
result = []
end
return result
end

def get_cost(id)
return @reservation_by_id[id].cost
end

def available_rooms(check_in, check_out)
available_rooms = Array.new(20, true)
(check_in...check_out).each do |date|
if @reservations_by_date[date] != nil
@reservations_by_date[date].each do |reservation|
available_rooms[reservation.room - 1] = false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This code is looking inside each of the reservations to make its decision, so it is probably doing something outside its responsibilities.

end
end
if @blocks_by_date[date] != nil
@blocks_by_date[date].each do |block|
block.rooms.each do |room|
available_rooms[room - 1] = false
end
end
end
end
if available_rooms.include?(true) == true
available_rooms = available_rooms.each_index.select { |index| available_rooms[index] == true}
available_rooms.map! do |index|
index + 1
end
else
raise ArgumentError.new("No available room")
end
return available_rooms
end

def get_rooms_in_block(check_in, check_out)
if @blocks_by_date[check_in] != nil
@blocks_by_date[check_in].each do |block|
block.rooms
end
else
raise ArgumentError.new("Invalid block")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This line doesn't get hit by your tests.

end
end

def create_block(check_in , check_out, num_rooms, discounted_rate)
validate_dates(check_in, check_out)
validate_less_6_rooms(num_rooms)

if available_rooms(check_in, check_out).count >= num_rooms
rooms = []
num_rooms.times do |index|
rooms << available_rooms(check_in, check_out)[index]
end
else
raise ArgumentError.new("No available room")
end
block = Block.new(check_in, check_out, rooms, discounted_rate)
(check_in...check_out).each do |date|
if @blocks_by_date.has_key?(date) == false
blocks = []
blocks << block
@blocks_by_date.store(date, blocks)
else
@blocks_by_date[date] << block
end
end
return block
end

private
def get_next_id
return @id += 1
end

def validate_dates(check_in, check_out)
unless check_out > check_in
raise ArgumentError.new("Invalid dates")
end
end

def validate_less_6_rooms(num_rooms)
unless num_rooms <= 5
raise ArgumentError.new("A block can contain a maximum of 5 rooms")
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You're validating for the block here.

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

module HotelBooking
class Reservation
attr_reader :check_in, :check_out, :id, :room, :cost

def initialize(check_in, check_out, id, room, cost)
@check_in = check_in
@check_out = check_out
@id = id
@room = room
@cost = cost
end

end
end

11 changes: 11 additions & 0 deletions test/block_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require_relative 'test_helper'

describe "Block" do
describe "initialize" do

it "is an instance of Block" do
block = HotelBooking::Block.new("01/12/2019", "03/12/2019", 3, 150)
block.must_be_kind_of HotelBooking::Block
end
end
end
106 changes: 106 additions & 0 deletions test/manager_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
require_relative 'test_helper'

describe "Manager class" do
describe "initialize" do
before do
@manager = HotelBooking::Manager.new
end

it "has 20 rooms" do
expect(@manager.list_rooms.length).must_equal 20
end

it "has rooms from 1 to 20" do
(1..20).each do |number|
expect(@manager.list_rooms[number-1]).must_equal number
end
end

it "raises argument error for invalid dates" do
proc {
@manager.reserve_room(Date.new(2019, 12, 5), Date.new(2019, 12, 1))
}.must_raise ArgumentError
end

it "creates a reservation" do
reservation = @manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 3))
reservation.must_be_kind_of HotelBooking::Reservation
end

it "gets cost by reservation id" do
@manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 3))
expect @manager.get_cost(1).must_equal 400
end

it "gets reservation by date" do
reservation = @manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 2))
reservation2 = @manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 3))
expect @manager.get_reservation_by_date(Date.new(2019, 11, 30)).must_equal []
expect @manager.get_reservation_by_date(Date.new(2019, 12, 1))[0].must_equal reservation
expect @manager.get_reservation_by_date(Date.new(2019, 12, 1))[1].must_equal reservation2
expect @manager.get_reservation_by_date(Date.new(2019, 12, 1))[1].room.must_equal 2
expect @manager.get_reservation_by_date(Date.new(2019, 12, 1)).length.must_equal 2
expect @manager.get_reservation_by_date(Date.new(2019, 12, 2))[0].must_equal reservation2
expect @manager.get_reservation_by_date(Date.new(2019, 12, 2)).length.must_equal 1
expect @manager.get_reservation_by_date(Date.new(2019, 12, 3)).must_equal []
end

it "assigns correct room number" do
@manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 2))
@manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 3))
@manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 3))
expect @manager.get_reservation_by_date(Date.new(2019, 12, 1))[0].room.must_equal 1
expect @manager.get_reservation_by_date(Date.new(2019, 12, 1))[1].room.must_equal 2
expect @manager.get_reservation_by_date(Date.new(2019, 12, 2))[0].room.must_equal 2
expect @manager.get_reservation_by_date(Date.new(2019, 12, 2))[1].room.must_equal 3
end

it "shows available rooms for a given date range" do
@manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 2))
@manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 3))
@manager.reserve_room(Date.new(2019, 12, 1), Date.new(2019, 12, 4))
expect @manager.available_rooms(Date.new(2019, 12, 1), Date.new(2019, 12, 04)).count.must_equal 17
expect @manager.available_rooms(Date.new(2019, 12, 10), Date.new(2019, 12, 11)).count.must_equal 20
end

it "raises exception if someone tries to do a reservation and there are no available rooms" do
20.times do |reservation|
@manager.reserve_room(Date.new(2019, 11, 10 ), Date.new(2019, 11, 13))
end

proc {
@manager.reserve_room(Date.new(2019, 11, 10 ), Date.new(2019, 11, 13))
}.must_raise ArgumentError
end

it "creates a block of rooms" do
@manager.create_block(Date.new(2019, 12, 1), Date.new(2019, 12, 3), 3, 150)
@manager.available_rooms(Date.new(2019, 12, 1), Date.new(2019, 12, 3)).count.must_equal 17
@manager.available_rooms(Date.new(2019, 11, 29), Date.new(2019, 12, 2)).count.must_equal 17
@manager.available_rooms(Date.new(2019, 12, 3), Date.new(2019, 12, 4)).count.must_equal 20
end

it "raises an error for more than 5 rooms in a block" do
proc {
@manager.create_block(Date.new(2019, 12, 1), Date.new(2019, 12, 3), 6, 150)
}.must_raise ArgumentError
end

it "raises error if there aren't enough rooms available for a block" do
16.times do |reservation|
@manager.reserve_room(Date.new(2019, 11, 10 ), Date.new(2019, 11, 13))
end
proc {
@manager.create_block(Date.new(2019, 11, 10), Date.new(2019, 11, 13), 5, 150)
}.must_raise ArgumentError
end

it "shows rooms in a block" do
@manager.create_block(Date.new(2019, 12, 1), Date.new(2019, 12, 3), 3, 150)
@manager.create_block(Date.new(2019, 12, 1), Date.new(2019, 12, 3), 5, 150)
@manager.get_rooms_in_block(Date.new(2019, 12, 1), Date.new(2019, 12, 3))[0].rooms.must_equal [1,2,3]
@manager.get_rooms_in_block(Date.new(2019, 12, 1), Date.new(2019, 12, 3))[1].rooms.must_equal [4,5,6,7,8]
end

end
end
12 changes: 12 additions & 0 deletions test/reservation_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require_relative 'test_helper'
require "pry"

describe "Reservation" do
describe "initialize" do

it "is an instance of Reservation" do
reservation = HotelBooking::Reservation.new("01/12/2019", "03/12/2019", "a", "a", "a")
reservation.must_be_kind_of HotelBooking::Reservation
end
end
end
6 changes: 6 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
require "simplecov"
SimpleCov.start

# Add simplecov
require "minitest"
require "minitest/autorun"
Expand All @@ -6,3 +9,6 @@
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new

# require_relative your lib files here!
require_relative "../lib/manager"
require_relative "../lib/reservation"
require_relative "../lib/block"