diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..1ad899dbc Binary files /dev/null and b/.DS_Store differ diff --git a/lib/block.rb b/lib/block.rb new file mode 100644 index 000000000..94cb5f465 --- /dev/null +++ b/lib/block.rb @@ -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 + @check_out = check_out + @rooms = rooms + @discounted_rate = discounted_rate + end + end +end + diff --git a/lib/manager.rb b/lib/manager.rb new file mode 100644 index 000000000..e5d995138 --- /dev/null +++ b/lib/manager.rb @@ -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 + 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") + 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 + end + end +end \ No newline at end of file diff --git a/lib/reservation.rb b/lib/reservation.rb new file mode 100644 index 000000000..e7b586748 --- /dev/null +++ b/lib/reservation.rb @@ -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 + diff --git a/test/block_test.rb b/test/block_test.rb new file mode 100644 index 000000000..40d42361d --- /dev/null +++ b/test/block_test.rb @@ -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 \ No newline at end of file diff --git a/test/manager_test.rb b/test/manager_test.rb new file mode 100644 index 000000000..4bce5829a --- /dev/null +++ b/test/manager_test.rb @@ -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 diff --git a/test/reservation_test.rb b/test/reservation_test.rb new file mode 100644 index 000000000..d085b83e9 --- /dev/null +++ b/test/reservation_test.rb @@ -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 \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index c3a7695cf..8dd7e8efd 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,3 +1,6 @@ +require "simplecov" +SimpleCov.start + # Add simplecov require "minitest" require "minitest/autorun" @@ -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" \ No newline at end of file