diff --git a/Rakefile b/Rakefile new file mode 100644 index 000000000..deb52f2cd --- /dev/null +++ b/Rakefile @@ -0,0 +1,9 @@ +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 diff --git a/lib/admin.rb b/lib/admin.rb new file mode 100644 index 000000000..28d70d0ae --- /dev/null +++ b/lib/admin.rb @@ -0,0 +1,36 @@ +require_relative './concerns/dateable' +require_relative './concerns/reserveable' +require_relative './concerns/blockable' +require_relative 'reservation' +require 'date' +require 'securerandom' +require 'pry' +module Hotel + + + class Admin + include Hotel::Dateable::InstanceMethods + include Hotel::Reserveable::InstanceMethods + include Hotel::Blockable::InstanceMethods + + attr_reader :reservations_list, :all_rooms, :block_list + # def get_date_range(check_in, check_out) + # return (check_in ... check_out).to_a + # end + + def initialize + @reservations_list = [] + @block_list = [] + @all_rooms = [] + make_hotel_rooms + end + #could possibly go back in here and use a rooms class + def make_hotel_rooms + (1..20).each do |num| + @all_rooms << num #Hotel::Room.new(num) I don't think I have to do this + end + end + + end #class Admin + +end diff --git a/lib/blocks.rb b/lib/blocks.rb new file mode 100644 index 000000000..00c3029b3 --- /dev/null +++ b/lib/blocks.rb @@ -0,0 +1,41 @@ +require_relative 'reservation' +require_relative './concerns/dateable' +require 'date' +require 'pry' +module Hotel + + + class Block < Reservation + include Hotel::Dateable::InstanceMethods + + + attr_accessor :date_range, :room, :name, :contact_info, :check_in, :check_out, :price, :discount, :num_rooms + + def initialize(check_in, check_out, name, contact_info, discount, num_rooms) + + super(check_in, check_out, room, name, contact_info) + @discount = discount + @price = (@date_range.length) * PRICE_PER_NIGHT * calculate_discount(@discount) + @num_rooms = num_rooms + end + + def change_discount(discount) + @discount = calculate_discount(discount) + end + + def price_all_rooms + @num_rooms * @price + end + + def change_rooms_block(number) + @num_rooms = number + end + + private + + + def calculate_discount(number) + (100 - number) * 0.01 + end + end +end diff --git a/lib/concerns/blockable.rb b/lib/concerns/blockable.rb new file mode 100644 index 000000000..4b34facfd --- /dev/null +++ b/lib/concerns/blockable.rb @@ -0,0 +1,62 @@ +module Hotel + module Blockable + module InstanceMethods + include Hotel::Dateable::InstanceMethods + + def create_block(check_in, check_out, name, contact_info, discount, num_rooms) + + available_rooms = rooms_available?(check_in, check_out) + num_rooms_in_range?(num_rooms, available_rooms) + #id_num = SecureRandom.uuid don't need it, but I like the idea + + @block_list << Hotel::Block.new(check_in, check_out, name, contact_info, discount, num_rooms) + + end + + + def convert_block_to_reservation(name) + being_converted = finder(name, :name, block_list) + @block_list = @block_list - being_converted + being_converted.each{ |block| block.num_rooms.times do |thing| + reserve(block.check_in, block.check_out, rooms_available?(block.check_in, block.check_out)[0], block.name, block.contact_info) + end + } + @block_list = @block_list - being_converted + end + + def delete_block(name) + being_deleted = finder(name, :name, block_list) + # binding.pry + @block_list = @block_list - being_deleted + end + + def find_block_name(name) + finder(name, :name, block_list) + end + + def find_block_by_date(date) + finder(date, :date_range, block_list) + + end + + def number_rooms_blocked_by_date_range(check_in, check_out) + num_rooms = 0 + date_range = get_date_range(check_in, check_out) + date_range.each do |date| + blocks_dates = @block_list.find_all{|block| (block.date_range & date_range).any?} + num_rooms = blocks_dates.sum{|block| block.num_rooms} + end + num_rooms + end + + private + def num_rooms_in_range?(num, rooms_available) + + raise ArgumentError.new("The number of rooms is out of range") if num > rooms_available.length + + end + + + end #blockable + end #InstanceMethods +end #Hotel diff --git a/lib/concerns/dateable.rb b/lib/concerns/dateable.rb new file mode 100644 index 000000000..2d8f92f5e --- /dev/null +++ b/lib/concerns/dateable.rb @@ -0,0 +1,13 @@ +module Hotel + module Dateable + module InstanceMethods + def get_date_range(check_in, check_out) + (check_in ... check_out).to_a + end + #ability to do searchy things + def finder(search_term, instance_variable, search_group) + search_group.find_all{|element| element.send(instance_variable).include?(search_term)} + end + end + end +end diff --git a/lib/concerns/reserveable.rb b/lib/concerns/reserveable.rb new file mode 100644 index 000000000..287cfd273 --- /dev/null +++ b/lib/concerns/reserveable.rb @@ -0,0 +1,55 @@ +module Hotel + module Reserveable + module InstanceMethods + include Hotel::Dateable::InstanceMethods + + + def reserve(check_in, check_out, room, name, contact_info) + #checks that the date hash't been previously reserved, and there are enough rooms for the blocks + + raise ArgumentError.new("This room is already reserved on these days") if rooms_available?(check_in, check_out).include?(room) == false + new_reservation = Hotel::Reservation.new(check_in, check_out, room, name, contact_info) + + @reservations_list << new_reservation + + + end#reserve + + def rooms_available?(check_in, check_out) + blocks_for_date = number_rooms_blocked_by_date_range(check_in, check_out) + wanted_dates = get_date_range(check_in, check_out) + reserved_rooms_for_dates = [] + + case + when @reservations_list == [] + return @all_rooms + else + @reservations_list.each do |reservation| + #needs to check if the room is included in this reservation on the day + + overlap = reservation.dates_reserved & wanted_dates + overlap.any? ? reserved_rooms_for_dates << reservation.room : false + + end + end + + available_rooms = @all_rooms - reserved_rooms_for_dates + if blocks_for_date >= available_rooms.length + raise ArgumentError.new("Blocks for this date prohibit us from reserving rooms") + else + available_rooms + end + end#rooms_available + + + def reservations_by_name(name_request) + finder( name_request, :name, reservations_list) + + end#reservations_by_date + + def reservations_by_date(date) + finder(date, :date_range, reservations_list ) + end#reservations_by_date + end + end +end diff --git a/lib/reservation.rb b/lib/reservation.rb new file mode 100644 index 000000000..89f4d3710 --- /dev/null +++ b/lib/reservation.rb @@ -0,0 +1,38 @@ +# require_relative 'hotel' +require_relative './concerns/dateable' +require 'date' +require 'pry' + +module Hotel + PRICE_PER_NIGHT = 200 + # + # def get_date_range(check_in, check_out) + # return (Date.new(check_in[0], check_in[1], check_in[2]) ... Date.new(check_out[0], check_out[1], check_out[2])).to_a + # end + + class Reservation + include Hotel::Dateable::InstanceMethods + + attr_accessor :date_range, :room, :name, :contact_info, :check_in, :check_out, :price + + def initialize(check_in, check_out, room, name, contact_info) + @check_in = check_in + @check_out = check_out + @date_range = populate_date_range(@check_in, @check_out) + @room = room + @name = name + @contact_info = contact_info + @price = (@date_range.length) * PRICE_PER_NIGHT + end + + def populate_date_range(check_in, check_out) + get_date_range(check_in, check_out) + end + + def dates_reserved + @date_range + end #end available? + + end#end class + # binding.pry +end#end module diff --git a/lib/room.rb b/lib/room.rb new file mode 100644 index 000000000..8c3c03ea5 --- /dev/null +++ b/lib/room.rb @@ -0,0 +1,12 @@ +module Hotel + + class Room + + attr_reader :number + def initialize( name ) + @number = number + end + end + + +end diff --git a/specs/admin_spec.rb b/specs/admin_spec.rb new file mode 100644 index 000000000..322d4c7e5 --- /dev/null +++ b/specs/admin_spec.rb @@ -0,0 +1,17 @@ +require_relative '../lib/admin' +require_relative 'spec_helper' +require 'pry' + +describe "class Admin" do + + describe "initialize" do + it "initializes all instance variables" do + admin_1 = Hotel::Admin.new + admin_1.all_rooms.length.must_equal 20 + admin_1.reservations_list.must_be_instance_of Array + admin_1.must_be_instance_of Hotel::Admin + admin_1.block_list.must_be_instance_of Array + end + end + +end#end describe Admin diff --git a/specs/blockable_spec.rb b/specs/blockable_spec.rb new file mode 100644 index 000000000..e1e738848 --- /dev/null +++ b/specs/blockable_spec.rb @@ -0,0 +1,60 @@ +require_relative '../lib/concerns/blockable' +require_relative 'spec_helper' + + describe "blockable" do + before do + @admin = Hotel::Admin.new + @admin.create_block(Date.new(2012, 07, 16), Date.new(2012, 07, 19), "Bill Murray", "Japan", 5, 14) + end + it "can create a block" do + + @admin.block_list[0].must_be_instance_of Hotel::Block + end + + it "won't take a room of blocks that is out of range" do + proc{@admin.create_block(Date.new(2012, 07, 16), Date.new(2012, 07, 19), "Bill Murray", "Japan", 5, 27)}.must_raise ArgumentError + end + + it "pushes the block into the block_list" do + @admin.block_list.length.must_equal 1 + end + + it "can delete a block" do + @admin.delete_block("Bill Murray") + @admin.block_list.length.must_equal 0 + end + + it "can find a block from the block_list by name" do + @admin.create_block(Date.new(2012, 07, 20), Date.new(2012, 07, 24), "Bill Murray", "Japan", 5, 3) + this_block = @admin.find_block_name("Bill Murray") + this_block.each do |block| + block.must_be_instance_of Hotel::Block + end + this_block.length.must_equal 2 + end + + it "can find a block from the block_list by date" do + this_block = @admin.find_block_by_date(Date.new(2012, 7, 18)) + this_block.each do |block| + block.must_be_instance_of Hotel::Block + end + this_block.length.must_equal 1 + this_other_block = @admin.find_block_by_date(Date.new(2012, 7, 30), ) + this_other_block.length.must_equal 0 + + end + + it "can convert a block to a reservation by name" do + + @admin.convert_block_to_reservation("Bill Murray") + @admin.rooms_available?(Date.new(2012, 7, 18), Date.new(2012, 7, 19)).length.must_equal 6 + @admin.block_list.length.must_equal 0 + end + + it "can find a number of rooms blocked by date range" do + num_blocked = @admin.number_rooms_blocked_by_date_range(Date.new(2012, 07, 16), Date.new(2012, 07, 19)) + num_blocked.must_equal 14 + + end + + end#end blockable diff --git a/specs/blocks_spec.rb b/specs/blocks_spec.rb new file mode 100644 index 000000000..0b3805264 --- /dev/null +++ b/specs/blocks_spec.rb @@ -0,0 +1,58 @@ +require_relative '../lib/blocks' +require_relative '../lib/reservation' +require_relative 'spec_helper' + +describe "block" do + + it "can initialize a block" do + block_1 = Hotel::Block.new( Date.new(2019, 11, 15), Date.new(2019, 11, 15), "T Payne", "8675309", 10, 15) + block_1.must_be_instance_of Hotel::Block + end + + it "can return the correct information" do + + block_1 = Hotel::Block.new( Date.new(1900, 02, 20), Date.new(1900, 02, 22), "Dr. Frankenstein", "8675309", 15 , 15) + block_1.check_in.must_be_instance_of Date + block_1.check_out.must_be_instance_of Date + block_1.date_range.must_be_instance_of Array + block_1.date_range.length.must_equal 2 + block_1.num_rooms.must_equal 15 + block_1.name.must_equal "Dr. Frankenstein" + block_1.contact_info.must_equal "8675309" + block_1.price.must_equal 340 + block_1.discount.must_equal 15 + block_1.discount.must_be_instance_of Integer + end + + + describe "nights_reserved method" do + it "can get dates from block" do + block_1 = Hotel::Block.new(Date.new(2019, 11, 15), Date.new(2019, 11, 17), "Dr. Frankenstein", "8675309", 20, 15) + range_dates = block_1.dates_reserved + range_dates[0].must_equal Date.new(2019, 11, 15) + end + end + + describe "change_discount" do + it "can change the discount on a block" do + block_1 = Hotel::Block.new( Date.new(1900, 02, 20), Date.new(1900, 02, 22), "Dr. Frankenstein", "8675309", 15, 20) + block_1.change_discount(70) + block_1.discount.must_equal 0.30 + end + end + + describe "price_all_rooms" do + it "calculates the price for all rooms" do + block_1 = Hotel::Block.new( Date.new(1976, 02, 20), Date.new(1976, 02, 22), "Norman Bates", "8675309", 15, 20) + block_1.price_all_rooms.must_equal 6800 + end + end + describe "change_rooms_block" do + it "can change the number of rooms in a block" do + block_1 = Hotel::Block.new( Date.new(1976, 02, 20), Date.new(1976, 02, 22), "Norman Bates", "8675309", 15, 20) + block_1.change_rooms_block(40) + block_1.num_rooms.must_equal 40 + end + end + +end diff --git a/specs/reservations_spec.rb b/specs/reservations_spec.rb new file mode 100644 index 000000000..9f8373784 --- /dev/null +++ b/specs/reservations_spec.rb @@ -0,0 +1,31 @@ +require_relative '../lib/reservation' +require_relative 'spec_helper' + +describe "reservation" do + + it "can initialize a reservation" do + reservation_1 = Hotel::Reservation.new( Date.new(2019, 11, 15), Date.new(2019, 11, 15), 4, "T Payne", "8675309" ) + reservation_1.must_be_instance_of Hotel::Reservation + end + + it "can return the correct information" do + + reservation_1 = Hotel::Reservation.new( Date.new(1900, 02, 20), Date.new(1900, 02, 22), 3, "Dr. Frankenstein", "8675309" ) + reservation_1.check_in.must_be_instance_of Date + reservation_1.check_out.must_be_instance_of Date + reservation_1.date_range.must_be_instance_of Array + reservation_1.date_range.length.must_equal 2 + reservation_1.room.must_equal 3 + reservation_1.name.must_equal "Dr. Frankenstein" + reservation_1.contact_info.must_equal "8675309" + reservation_1.price.must_equal 400 + end +end + +describe "nights_reserved method" do + it "can get dates from reservation" do + reservation_1 = Hotel::Reservation.new(Date.new(2019, 11, 15), Date.new(2019, 11, 17), 7, "Dr. Frankenstein", "8675309" ) + range_dates = reservation_1.dates_reserved + range_dates[0].must_equal Date.new(2019, 11, 15) + end +end diff --git a/specs/reserveable_spec.rb b/specs/reserveable_spec.rb new file mode 100644 index 000000000..4f5fee8ac --- /dev/null +++ b/specs/reserveable_spec.rb @@ -0,0 +1,100 @@ +require_relative '../lib/concerns/reserveable' +require_relative 'spec_helper' +require 'pry' + +describe "reserve" do + before do + @tim_curry = Hotel::Admin.new + + @reservation_1 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 4, "Kevin McCallister", "New York") + + @reservation_2 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 8, "Sticky Bandits", "New York") + + end + + it "create an instance of Hotel::Reservation" do + @tim_curry.reservations_list.each do |reservation| + reservation.must_be_instance_of Hotel::Reservation + end + end#end instance of Hotel::Reservation + + it "puts the correct number of reservations in the @reservations_list" do + @tim_curry.reservations_list.length.must_equal 2 + end + + it "can get the correct price" do + @tim_curry.reservations_list[0].price.must_equal 600 + end + + it "will raise error if you try to reserve taken room" do + proc{@tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 8, "Beetlejuice, Beetlejuice, Beetlejuice!", "New York")}.must_raise ArgumentError + end + +end#end "reserve" describe + +describe "checking for rooms_available?" do + before do + @tim_curry = Hotel::Admin.new + + @reservation_1 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 4, "Kevin McCallister", "New York") + + @reservation_2 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 8, "Sticky Bandits", "New York") + end + + it "should be able to check for vacancies" do + vacancies = @tim_curry.rooms_available?(Date.new(2019, 11, 15), Date.new(2019, 11, 18)) + + vacancies.length.must_equal 18 + vacancies.must_equal [1, 2, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] + end + +end#describe rooms available +describe "reservations_by_date" do + before do + @tim_curry = Hotel::Admin.new + + @reservation_1 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 4, "Kevin McCallister", "New York") + + @reservation_2 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 8, "Sticky Bandits", "New York") + end + + it "should be able to return empty array when no reservations" do + reservations = @tim_curry.reservations_by_date(Date.new(2019, 11, 30)) + reservations.must_be_instance_of Array + reservations[0].must_be_nil + end + + + it "should return all reservations for a date" do + reservations = @tim_curry.reservations_by_date(Date.new(2019, 11, 16)) + reservations.length.must_equal 2 + reservations[0].must_equal @tim_curry.reservations_list[0] + end +end + +describe "reservations_by_name" do + before do + @tim_curry = Hotel::Admin.new + + @reservation_1 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 4, "Kevin McCallister", "New York") + + @reservation_2 = @tim_curry.reserve(Date.new(2019, 11, 15), Date.new(2019, 11, 18), 8, "Sticky Bandits", "New York") + end + + it "can find reservations by name" do + found_name = @tim_curry.reservations_by_name("Sticky Bandits") + found_name.wont_be_nil + found_name[0].name.must_equal "Sticky Bandits" + end + + it "can find multiple entries with the same name" do + @tim_curry.reserve(Date.new(2019, 11, 22), Date.new(2019, 11, 30), 19, "Sticky Bandits", "New York") + + found_name = @tim_curry.reservations_by_name("Sticky Bandits") + + found_name.length.must_equal 2 + found_name[0].name.must_equal "Sticky Bandits" + found_name[1].name.must_equal "Sticky Bandits" + + end +end diff --git a/specs/room_spec.rb b/specs/room_spec.rb new file mode 100644 index 000000000..7bb11ccec --- /dev/null +++ b/specs/room_spec.rb @@ -0,0 +1,2 @@ +# require_relative '../lib/hotel.rb' +require_relative 'spec_helper' diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb new file mode 100644 index 000000000..ddcb9b545 --- /dev/null +++ b/specs/spec_helper.rb @@ -0,0 +1,16 @@ +require 'simplecov' +SimpleCov.start + +require 'minitest/autorun' +require 'minitest/reporters' +require 'minitest/skip_dsl' + +require_relative '../lib/admin' +require_relative '../lib/reservation' +require_relative '../lib/concerns/dateable' +require_relative '../lib/concerns/reserveable' +require_relative '../lib/room' + + + +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new