diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..ec1f5adfb Binary files /dev/null and b/.DS_Store differ diff --git a/lib/date_range.rb b/lib/date_range.rb new file mode 100644 index 000000000..ecad70450 --- /dev/null +++ b/lib/date_range.rb @@ -0,0 +1,26 @@ +module HotelSystem + class DateRange + attr_accessor :start_date, :end_date + + def initialize(start_date, end_date) + @start_date = start_date + @end_date = end_date + end + + def overlap?(other) + return false + end + + def include?(date) + return false + end + + def nights + return 3 + end + + end + + + +end \ No newline at end of file diff --git a/lib/hotel.rb b/lib/hotel.rb new file mode 100644 index 000000000..778e5b5c2 --- /dev/null +++ b/lib/hotel.rb @@ -0,0 +1,163 @@ +require_relative 'room' +require_relative 'reservation' + +module HotelSystem + class Hotel + attr_accessor :rooms + + def initialize + @rooms = [] + 20.times do |i| + @rooms << HotelSystem::Room.new(i+1, 200) + end + end + #the block can only be the last 5 rooms 15-20 + # def make_reservation_block(start_date, end_date, rooms_numbers, rate) + # rooms = [] + # rooms_numbers.each do |num| + # if num > 20 || num < 15 + # raise ArgumentError.new("you can only reserve rooms 15-20 for a block reservation") + # end + # rooms << find_room(num) + # end + + # rooms.each do |room| + # room.cost_per_night = cost_with_discount(rate, room) + # make_reservation(room.room_number, start_date, end_date) + # end + # end + + def find_reservations_with_room_number(room_number, start_date, end_date) + room = find_room(room_number) + list_reservations = [] + room.reservations.each do |reservation| + if is_between_two_dates([start_date, end_date], reservation.start_date) || is_between_two_dates([start_date, end_date], reservation.end_date) + list_reservations << reservation + end + end + return list_reservations + end + + def list_reservations_dates(start_date, end_date) + list_reservations = [] + @rooms.each do |room| + room.reservations.each do |reservation| + if is_between_two_dates([start_date, end_date], reservation.start_date) || is_between_two_dates([start_date, end_date], reservation.end_date) + list_reservations << reservation + end + end + end + return list_reservations + end + + def find_room(room_number) + @rooms.each do |room| + if room_number == room.room_number + return room + end + end + end + + def find_reservation(reservation_number) + @rooms.each do |room| + room.reservations.each do |reservation| + if reservation.reservation_number == reservation_number + return reservation + end + end + end + end + + def total_cost(reservation_number) + return find_reservation(reservation_number).total_cost + end + + def available_rooms(start_date, end_date) + list_rooms = [] + @rooms.each do |room| + if room.reservations.length == 0 || room.reservations == nil + list_rooms << room + elsif no_shared_days?(start_date, end_date, room.reservations.last) === true + list_rooms << room + end + end + return list_rooms + end + + + def make_reservation(room_number, start_date, end_date) + room = find_room(room_number) + + true_for_all = [] + + if room.reservations.length == 0 + room.reservations << HotelSystem::Reservation.new(next_reservation_number, start_date, end_date) + else + room.reservations.each do |res| + if no_shared_days?(start_date, end_date, res) === true + true_for_all << true + end + end + end + + if true_for_all.length == room.reservations.length + room.reservations << HotelSystem::Reservation.new(next_reservation_number, start_date, end_date) + else + raise ArgumentError.new("you can't overlap reservations") + end + end + + + #there may be some cases where a reservation starts when one ends, but trust me it still works the method name isn't very accurate + def no_shared_days?(start_date, end_date, reservation) + count = 0 + reservation_start = reservation.start_date + reservation_end = reservation.end_date + while start_date < end_date + while reservation_start < reservation_end + if start_date == reservation_start + count += 1 + end + reservation_start = reservation_start + 1 + end + reservation_start = reservation.start_date + start_date += 1 + end + if (reservation.end_date - reservation.start_date == 1) && reservation_start == start_date + return false + else + return count < 2 + end + end + + private + + #used for fine_reservations_for_room and list_reservations_with_date + def is_between_two_dates(range_wanted, date) + return date >= range_wanted[0] && date <= range_wanted[1]; + end + + def next_reservation_number + max = 0 + @rooms.each do |room| + room.reservations.each do |reservation| + if max < reservation.reservation_number + max = reservation.reservation_number + end + + end + end + return max + 1 + end + + def cost_with_discount(rate, room) + return room.cost_per_night - (room.cost_per_night*(rate/100)) + end + end +end + + +def main +end + +main diff --git a/lib/reservation.rb b/lib/reservation.rb new file mode 100644 index 000000000..f0742d142 --- /dev/null +++ b/lib/reservation.rb @@ -0,0 +1,26 @@ +require 'date' + +module HotelSystem + class Reservation + attr_reader :start_date, :end_date, :total_cost + attr_accessor :reservation_number + + def initialize(reservation_number, start_date, end_date) + @reservation_number = reservation_number + check_dates(start_date, end_date) + @start_date = start_date + @end_date = end_date + @total_cost = ((@end_date - @start_date)) * 200 + end + + def get_total_cost + return @total_cost + end + + def check_dates(start_date, end_date) + if Date.today > start_date || Date.today > end_date + raise ArgumentError.new("Invalid date, you can't start or end a reservation in the past") + end + end + end +end \ No newline at end of file diff --git a/lib/room.rb b/lib/room.rb new file mode 100644 index 000000000..9ca2be0a4 --- /dev/null +++ b/lib/room.rb @@ -0,0 +1,26 @@ + +require 'awesome_print' + +module HotelSystem + class Room + + attr_accessor :reservations,:room_number, :cost_per_night + + def initialize(room_number, cost_per_night, reservations=[]) + @room_number = room_number + @cost_per_night = cost_per_night + @reservations = [] + end + + def add_reservation(reservation) + @reservations << reservation + end + + def list_reservations + return @reservations + end + + end + +end + diff --git a/lib/roomblock.rb b/lib/roomblock.rb new file mode 100644 index 000000000..f3f18f383 --- /dev/null +++ b/lib/roomblock.rb @@ -0,0 +1,17 @@ +module HotelSystem + class RoomBlock + + attr_accessor :block + + def initialize(block, discount_rate) + if @block.length > 5 + raise ArgumentError.new("you can't reserve more than 5 rooms in a block") + end + @block = block #array or rooms + @cost_per_night = (@block.length * 200) - ((@block.length) * 200) * ((@discount_rate/100) ) + end + end + + + +end \ No newline at end of file diff --git a/test/date_range_test.rb b/test/date_range_test.rb new file mode 100644 index 000000000..e69de29bb diff --git a/test/hotel_test.rb b/test/hotel_test.rb new file mode 100644 index 000000000..8a6307a4e --- /dev/null +++ b/test/hotel_test.rb @@ -0,0 +1,282 @@ + + + +require_relative 'test_helper' + + + +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + +describe "initialize" do + it "I can access the list of all of the rooms in the hotel" do + hotel = HotelSystem::Hotel.new + hotel.must_be_instance_of HotelSystem::Hotel + end + it "an element in Hotel object must be a room" do + hotel = HotelSystem::Hotel.new + room = hotel.rooms[1] + room.must_be_instance_of HotelSystem::Room + + end + +end + + +describe "other instance methods" do + + it "finds a room " do + hotel = HotelSystem::Hotel.new + room = hotel.find_room(1) + room.must_be_instance_of HotelSystem::Room + + end + + it "finds an array of reservations" do + + hotel = HotelSystem::Hotel.new + + room = hotel.find_room(1) + + res1 = HotelSystem::Reservation.new(1, Date.today, Date.new(2020,03,29)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 29), Date.new(2020, 04,02)) + + room.add_reservation(res1) + room.add_reservation(res2) + reservation = room.reservations[1] + + reservation.must_be_instance_of HotelSystem::Reservation + + end + + + it "I access the list of reservations for a specified room and a given date range" do + res1 = HotelSystem::Reservation.new(1, Date.today, Date.new(2020,03,29)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 29), Date.new(2020, 04,02)) + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 04, 06), Date.new(2020,04,18)) + + + hotel = HotelSystem::Hotel.new + + hotel.rooms[1].add_reservation(res1) + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res3) + + + array = hotel.find_reservations_with_room_number(2 , Date.new(2020, 03, 07), Date.new(2020, 03, 13)) + + array.must_be_instance_of Array + + end + + + it "outputs the correct reservations" do + + + res1 = HotelSystem::Reservation.new(1, Date.new(2020,04,03), Date.new(2020,04,06)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 10), Date.new(2020, 03,11)) + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 31), Date.new(2020,04,02)) + + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res3) + hotel.rooms[2].add_reservation(res1) + + array = hotel.list_reservations_dates(Date.new(2020, 03, 07), Date.new(2020, 03, 31)) + + array.must_equal [res2, res3] + end + + + it "finds the correct reservations given a room number" do + + res1 = HotelSystem::Reservation.new(1, Date.new(2020,04,03), Date.new(2020,04,06)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 10), Date.new(2020, 03,11)) + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 31), Date.new(2020,04,02)) + + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res1) + hotel.rooms[10].add_reservation(res3) + + + array = hotel.find_reservations_with_room_number(11, Date.new(2020, 03, 07), Date.new(2020, 03, 31)) + + array.must_equal [res3] + + end + + + it "finds the correct reservations given a room number - test 2" do + + res1 = HotelSystem::Reservation.new(1, Date.new(2020,04,03), Date.new(2020,04,06)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 10), Date.new(2020, 03,12)) + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 31), Date.new(2020,04,02)) + + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res1) + hotel.rooms[10].add_reservation(res3) + + + array = hotel.find_reservations_with_room_number(2, Date.new(2020, 03, 07), Date.new(2020, 03, 31)) + + array.must_equal [res2] + + end + + it "finds the available rooms" do + res1 = HotelSystem::Reservation.new(1, Date.new(2020,04,03), Date.new(2020,04,06)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 10), Date.new(2020, 03,18)) + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 31), Date.new(2020,04,02)) + + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res1) + hotel.rooms[10].add_reservation(res3) + + avail_rooms = hotel.available_rooms(Date.new(2020, 03, 06), Date.new(2020, 03, 18)) + + avail_rooms.must_be_instance_of Array + + + end + + it "evaluates overlapping correcty " do + hotel = HotelSystem::Hotel.new + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 10), Date.new(2020, 03,29)) + answer = hotel.no_shared_days?(Date.new(2020, 03, 18), Date.new(2020, 04, 18), res3) + + + answer.must_equal false + + end + + it "must raise argument error if there is an invalid reservation" do + + hotel = HotelSystem::Hotel.new + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 10), Date.new(2020, 03,29)) + hotel.rooms[1].add_reservation(res3) + #make_reservation(room_number, start_date, end_date) + + expect{hotel.make_reservation(2, Date.new(2020, 03, 07), Date.new(2020, 04, 1))}.must_raise ArgumentError + end + + it "must make a reservation inside of specified room" do + hotel = HotelSystem::Hotel.new + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 10), Date.new(2020, 03, 18)) + hotel.rooms[1].add_reservation(res3) + + + hotel.make_reservation(2, Date.new(2020, 03, 18), Date.new(2020, 04, 01)) + + hotel.rooms[1].reservations.length.must_equal 2 + end + + it "finds the total cost of a reservation" do + + res1 = HotelSystem::Reservation.new(1, Date.new(2020,04,03), Date.new(2020,04,06)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 10), Date.new(2020, 03,11)) + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 31), Date.new(2020,04,02)) + + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res1) + hotel.rooms[10].add_reservation(res3) + + + cost = hotel.total_cost(1) + + + cost.must_equal 600 + + end + + it " can make a reservation the same day one ends" do + #make_reservation(room_number, start_date, end_date) + res1 = HotelSystem::Reservation.new(1, Date.new(2020,03, 10), Date.new(2020,03,12)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 18), Date.new(2020, 03,20)) + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 20), Date.new(2020,04,02)) + + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res1) + hotel.make_reservation(2, Date.new(2020, 03, 12), Date.new(2020, 03, 15)) + + hotel.rooms[1].reservations.length.must_equal 3 + + + end + + it " can raise argument error if days are overlapped" do + + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 18), Date.new(2020, 03,20)) + + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 03, 20), Date.new(2020,04,02)) + + + #should raise argument error + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res3) + expect{hotel.make_reservation(2, Date.new(2020, 03, 10), Date.new(2020, 04, 01))}.must_raise ArgumentError + + end + + it "can return the right answer for no_shared_days?" do + res1 = HotelSystem::Reservation.new(1, Date.new(2020,03,10), Date.new(2020,03,12)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 14), Date.new(2020, 03,17)) + + #should raise argument error + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + #hotel.rooms[1].add_reservation(res1) + ans = hotel.no_shared_days?(Date.new(2020, 03, 25), Date.new(2020, 03, 30), res2) + ans.must_equal true + + + end + + it "can return the right answer for no_shared_days?" do + res1 = HotelSystem::Reservation.new(1, Date.new(2020,03,9), Date.new(2020,03,12)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 14), Date.new(2020, 03,17)) + + #should raise argument error + hotel = HotelSystem::Hotel.new + hotel.rooms[1].add_reservation(res2) + hotel.rooms[1].add_reservation(res1) + ans = hotel.no_shared_days?(Date.new(2020, 03, 10), Date.new(2020, 03, 30), res2) + ans.must_equal false + + + end + + # it "raises argument error when given invalid rooms" do + # hotel = HotelSystem::Hotel.new + # expect{hotel.make_reservation_block(Date.new(2020, 03, 14), Date.new(2020, 03, 18), [1, 2, 3], 15)}.must_raise ArgumentError + # end + + # it "makes a reservation block" do + # hotel = HotelSystem::Hotel.new + + # hotel.make_reservation_block(Date.new(2020, 05, 28), Date.new(2020, 05, 30), [19, 18], 15) + # puts hotel.rooms[18].reservations.to_s + # hotel.rooms[18].reservations.length.must_equal 1 + # end + + + + # it "will not make a reservation from reservation block if room is booked" do + # hotel = HotelSystem::Hotel.new + # expect{hotel.make_reservation_block(Date.new(2020, 03, 14), Date.new(2020, 03, 18), [19, 18, 20], 15)}.must_raise ArgumentError + + # end +end \ No newline at end of file diff --git a/test/reservation_test.rb b/test/reservation_test.rb new file mode 100644 index 000000000..370cd53fa --- /dev/null +++ b/test/reservation_test.rb @@ -0,0 +1,26 @@ + +require_relative 'test_helper' + + + +describe "reservation" do + it "initializes a reservation correctly" do + reservation = HotelSystem::Reservation.new(500, Date.new(2020, 03, 18), Date.new(2020, 03, 20)) + + reservation.must_be_instance_of HotelSystem::Reservation + + end + + it "total cost must be correct " do + reservation = HotelSystem::Reservation.new(500, Date.new(2020, 03, 18), Date.new(2020, 03, 21)) + cost = reservation.get_total_cost + cost.must_equal 600 + + end + + it "must raise arguemnt error for invalid date " do + expect{HotelSystem::Reservation.new(500, Date.new(2020, 03, 01), Date.new(2020, 03, 06))}.must_raise ArgumentError + end + + +end \ No newline at end of file diff --git a/test/room_test.rb b/test/room_test.rb new file mode 100644 index 000000000..1178fc555 --- /dev/null +++ b/test/room_test.rb @@ -0,0 +1,55 @@ + + +require_relative 'test_helper' + + + +describe "room" do + + it "creates an instance of room" do + room = HotelSystem::Room.new(7, 100) + room.must_be_instance_of HotelSystem::Room + room.room_number.must_be_instance_of Integer + end + + it "I access the list of reservations for a specified room" do + res1 = HotelSystem::Reservation.new(1, Date.today, Date.new(2020,03,29)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 29), Date.new(2020, 04,02)) + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 04, 06), Date.new(2020,04,18)) + + room = HotelSystem::Room.new(5, 200) + room.add_reservation(res1) + room.add_reservation(res2) + room.add_reservation(res3) + + res = room.reservations + res.must_be_instance_of Array + + end + + + +end + +describe "class methods" do + + + + it "lists reservations" do + + res1 = HotelSystem::Reservation.new(1, Date.today, Date.new(2020,03,29)) + res2 = HotelSystem::Reservation.new(2, Date.new(2020, 03, 29), Date.new(2020, 04,02)) + res3 = HotelSystem::Reservation.new(3, Date.new(2020, 04, 06), Date.new(2020,04,18)) + + room = HotelSystem::Room.new(5, 200) + room.add_reservation(res1) + room.add_reservation(res2) + room.add_reservation(res3) + + room.list_reservations.must_be_instance_of Array + + + end + + +end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index c3a7695cf..f8840cea3 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,8 +1,18 @@ -# Add simplecov +require "simplecov" +SimpleCov.start do + add_filter 'test/' +end +require 'date' require "minitest" require "minitest/autorun" require "minitest/reporters" Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new -# require_relative your lib files here! + require_relative '../lib/hotel' + require_relative '../lib/room' + require_relative '../lib/reservation' + + + +