diff --git a/.gitignore b/.gitignore index 5e1422c9c..dfe0e1613 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,11 @@ build-iPhoneSimulator/ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: .rvmrc + +#simplecov + +coverage + +#system + +.DS_store diff --git a/lib/date_range.rb b/lib/date_range.rb new file mode 100644 index 000000000..0c8d292e0 --- /dev/null +++ b/lib/date_range.rb @@ -0,0 +1,23 @@ +require 'date' + +module Hotel + class DateRange + attr_reader :check_in, :check_out, :nights_spent + + def initialize(check_in, check_out) + raise ArgumentError, 'Invalid date range given.' unless check_out > check_in + @check_in = check_in + @check_out = check_out + @nights_spent = (@check_out - @check_in) + end + + def to_id + return (@check_in.year.to_s + @check_in.mon.to_s + @check_in.mday.to_s) + end + + def overlap? (other_check_in, other_check_out) + return ((@check_in..@check_out).cover? (other_check_in)) || ((@check_in-1...@check_out).cover? (other_check_out)) + 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..39341e03f --- /dev/null +++ b/lib/reservation.rb @@ -0,0 +1,21 @@ +require 'date' + +require_relative 'date_range' +require_relative 'room' + +module Hotel + class Reservation + attr_reader :id, :dates, :occupancy + + def initialize(type, dates, occupancy) + @id = type[0] + dates.to_id + @dates = dates + @occupancy = occupancy + end + + def total_price + return @occupancy.sum { |occupancy| occupancy[:room].price * @dates.nights_spent } + end + + end +end diff --git a/lib/reservation_manager.rb b/lib/reservation_manager.rb new file mode 100644 index 000000000..8b38b929c --- /dev/null +++ b/lib/reservation_manager.rb @@ -0,0 +1,67 @@ +require 'time' + +require_relative 'room' +require_relative 'reservation' + +module Hotel + class ReservationManager + attr_reader :rooms, :reservations + + def initialize(room_count) + @rooms = generate_rooms(room_count) + @reservations = [] + end + + # Parameters: + # -type: symbol (:SINGLE, :BLOCK) that indicates type of reservation + # -range: DateRange object + # -occupancy: Hash or String + # Returns: newly created Reservation object + def create_reservation(type, range, occupancy) + raise ArgumentError.new("Invalid reservation type (given #{type}, must be :SINGLE or :BLOCK)") unless + type == :SINGLE || type == :BLOCK + + occupancy = [{:room => @rooms.sample, :guest => occupancy}] if occupancy.class == String + + new_reservation = Reservation.new(type, range, occupancy) + @reservations << new_reservation + return new_reservation + end + + # Parameters: Date object + # Returns: an Array of all Reservation instances that contain that date + def find_reservations_by_date(check_in, check_out) + by_date = @reservations.select { |reservation| reservation.dates.overlap?(check_in, check_out)} + end + + def find_reservations_by_room(room) + by_room = @reservations.select { |reservation| reservation.occupancy.detect { |occupancy| occupancy[:room] == room }} + end + + def list_all_available(check_in, check_out) + reserved = find_reservations_by_date(check_in, check_out) + + if reserved.length > 0 + occupancies = reserved.map { |reservation| reservation.occupancy } + occupied_rooms = occupancies.flatten + occupied_rooms_ids = occupied_rooms.map { |occupancy| occupancy[:room].id } + end + + rooms = @rooms.map { |room| room.id } + + return (rooms - occupied_rooms_ids) + + end + + private + + def generate_rooms(room_count) + rooms = [] + room_count.times do |num| + rooms << Room.new(num+1) + end + return rooms + 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..4f3771ae1 --- /dev/null +++ b/lib/room.rb @@ -0,0 +1,12 @@ +module Hotel + class Room + attr_reader :id, :price, :type + + def initialize(id) + @id = id.to_s + @price = 200 + @type = "standard" + 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..50c650704 --- /dev/null +++ b/test/date_range_test.rb @@ -0,0 +1,28 @@ +require_relative 'test_helper' + +describe "DateRange class" do + describe "initialize" do + + before do + @dates = Hotel::DateRange.new(Date.new, Date.new + 2) + end + + it "creates an instance of DateRange" do + expect(@dates).must_be_kind_of Hotel::DateRange + end + + it "raises an error for invalid dates" do + expect{(Hotel::DateRange.new(Date.new+2, Date.new))}.must_raise ArgumentError + end + + it "returns accurate count of nights spent" do + expect(@dates.nights_spent).must_equal 2 + end + + it "returns accurate start Date" do + expect(@dates.check_in).must_be_kind_of Date + end + + end + +end \ No newline at end of file diff --git a/test/reservation_manager_test.rb b/test/reservation_manager_test.rb new file mode 100644 index 000000000..298fc95cc --- /dev/null +++ b/test/reservation_manager_test.rb @@ -0,0 +1,122 @@ +require_relative 'test_helper' + +describe "ReservationManager class" do + before do + @reservation_manager = Hotel::ReservationManager.new(20) + end + + describe "Initializer" do + it "is an instance of ReservationManager" do + expect(@reservation_manager).must_be_kind_of Hotel::ReservationManager + end + + it "initializes correct number of rooms" do + expect(@reservation_manager.rooms.length).must_equal 20 + end + + it "populates valid room objects" do + expect(@reservation_manager.rooms[1]).must_be_kind_of Hotel::Room + end + + it "initializes with zero reservations" do + expect(@reservation_manager.reservations.length).must_equal 0 + end + + it "manages a hotel with 0 rooms" do + reservation_manager = Hotel::ReservationManager.new(0) + expect(reservation_manager.rooms.length).must_equal 0 + + end + end + + describe "create reservation" do + before do + @room = Hotel::Room.new(100) + @occupancy = [{:room => @room, :guest => "Picchu"}] + @date = Hotel::DateRange.new(Date.new, Date.new + 2) + @reservation = @reservation_manager.create_reservation(:SINGLE, @date, @occupancy) + end + + it "creates an instance of Reservation object" do + expect(@reservation).must_be_kind_of Hotel::Reservation + end + + it "creates valid objects inside of a Reservation" do + expect(@reservation.occupancy).must_be_kind_of Array + end + + end + + describe "find_reservations_by_date" do + before do + date = Hotel::DateRange.new(Date.new, Date.new + 2) + @reservation_manager.create_reservation(:SINGLE, date, [{:room => Hotel::Room.new(100), :guest => "Elvy"}]) + @reservation_manager.create_reservation(:SINGLE, date, [{:room => Hotel::Room.new(200), :guest => "Picchu"}] ) + end + + it "has accurate number of reservations" do + expect(@reservation_manager.reservations.length).must_equal 2 + end + + it "finds all reservations for a date" do + results = @reservation_manager.find_reservations_by_date(Date.new, Date.new + 3) + expect(results).must_be_kind_of Array + expect(results.length).must_equal 2 + expect(results[0]).must_be_kind_of Hotel::Reservation + expect(results[0].occupancy).must_be_kind_of Array + expect(results[0].occupancy[0]).must_be_kind_of Hash + expect(results[0].occupancy[0][:room]).must_be_kind_of Hotel::Room + expect(results[0].occupancy[0][:room].id).must_equal "100" + expect(results[0].occupancy[0][:guest]).must_equal "Elvy" + + end + end + + describe "find_by_room" do + before do + @room = Hotel::Room.new(100) + @reservation_manager.create_reservation( + :SINGLE, + Hotel::DateRange.new(Date.new + 5, Date.new + 10), + [{:room => @room, :guest => "Picchu"}] + ) + @reservation_manager.create_reservation( + :SINGLE, + Hotel::DateRange.new(Date.new + 11, Date.new + 15), + [{:room => @room, :guest => "Elvy"}] + ) + @reservation_manager.create_reservation( + :SINGLE, + Hotel::DateRange.new(Date.new + 16, Date.new + 18), + [{:room => @room, :guest => "Tater Tot"}] + ) + @reservation_manager.create_reservation( + :BLOCK, + Hotel::DateRange.new(Date.new + 19, Date.new + 23), + [{:room => Hotel::Room.new(300), :guest => "Peaches"},{:room => @room, :guest => "Tater Tot"},{:room => Hotel::Room.new(200), :guest => "Finn"}] + ) + end + + it "finds all reservations for a given room" do + results = @reservation_manager.find_reservations_by_room(@room) + expect(results).must_be_kind_of Array + expect(results.length).must_equal 4 + expect(results.all? {|result| result.class == Hotel::Reservation}).must_equal true + end + end + + describe "list_all_available" do + before do + date = Hotel::DateRange.new(Date.new, Date.new + 2) + @reservation_manager.create_reservation(:SINGLE, date, [{:room => @reservation_manager.rooms[0], :guest => "Elvy"}]) + @reservation_manager.create_reservation(:SINGLE, date, [{:room => @reservation_manager.rooms[1], :guest => "Picchu"}] ) + @reservation_manager.create_reservation(:SINGLE, date, [{:room => @reservation_manager.rooms[2], :guest => "Brom"}] ) + end + + it "returns list of available rooms for a given date range" do + results = @reservation_manager.list_all_available(Date.new, Date.new + 2) + expect(results.length).must_equal 17 + end + + end +end diff --git a/test/reservation_test.rb b/test/reservation_test.rb new file mode 100644 index 000000000..73d2664d8 --- /dev/null +++ b/test/reservation_test.rb @@ -0,0 +1,34 @@ +require_relative 'test_helper' + +describe "Reservation class" do + before do + @date = Hotel::DateRange.new(Date.new, Date.new + 2) + @occupancy = [{:room => Hotel::Room.new(12), :guest => "Picchu"}] + @reservation = Hotel::Reservation.new(:SINGLE, @date, @occupancy) + end + + describe "initializer" do + + it "creates a valid Reservation" do + expect(@reservation.id).must_be_kind_of String + expect(@reservation.dates).must_be_kind_of Hotel::DateRange + end + + end + + describe "total_price" do + + it "calculates total price on single room" do + expect(@reservation.total_price).must_equal (400) + end + + it "calculates total price of a block" do + occupancy = [{:room => Hotel::Room.new(12), :guest => "Picchu"},{:room => Hotel::Room.new(14), :guest => "Elvy"}] + reservation = Hotel::Reservation.new(:BLOCK, @date, occupancy) + + expect(reservation.total_price).must_equal (800) + end + + 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..ced612872 --- /dev/null +++ b/test/room_test.rb @@ -0,0 +1,24 @@ +require_relative 'test_helper' + +describe "Room class" do + before do + @room = Hotel::Room.new(1) + end + + describe "initialize" do + it "creates a valid room object" do + expect(@room).must_be_kind_of Hotel::Room + end + end + + describe "Room methods" do + it "sets price to 200" do + expect(@room.price).must_equal 200 + end + + it "gives room a default type" do + expect(@room.type).must_equal "standard" + end + end + +end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index c3a7695cf..1010d7f14 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,4 +1,8 @@ -# Add simplecov +require 'simplecov' +SimpleCov.start do + add_filter 'test/' # Tests should not be checked for coverage. +end + require "minitest" require "minitest/autorun" require "minitest/reporters" @@ -6,3 +10,8 @@ Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new # require_relative your lib files here! +require_relative "../lib/reservation_manager.rb" +require_relative "../lib/room.rb" +require_relative "../lib/reservation.rb" +require_relative "../lib/date_range.rb" +