-
Notifications
You must be signed in to change notification settings - Fork 40
Time - Sharon Cheung #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
701f1d0
783f7ff
01d9186
a8ec2fc
db0d468
efaabf4
882bef2
972aee5
aa6b83d
4e2ae84
0422f72
b374981
8273f9a
8221746
8d10957
2890eca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| require 'date' | ||
|
|
||
| module Hotel | ||
| class DateRange | ||
| attr_reader :start_date, :end_date | ||
|
|
||
| def initialize(start_date, end_date) | ||
| @start_date = start_date | ||
| @end_date = end_date | ||
| raise ArgumentError.new("This is not a valid date range!") if @end_date < @start_date | ||
| end | ||
|
|
||
| def overlap?(other) | ||
| # check to see if the date range itself is overlapping with "other"? | ||
| # A reservation is allowed start on the same day that another reservation for the same room ends | ||
| if self.start_date.between?(other.start_date, other.end_date - 1) || other.start_date.between?(self.start_date, self.end_date - 1) | ||
| return true | ||
| else | ||
| return false | ||
| end | ||
| end | ||
|
|
||
| def include?(date) | ||
| # see if the date provided is in between the date range | ||
| if date.between?(self.start_date, self.end_date - 1) | ||
| return true | ||
| else | ||
| return false | ||
| end | ||
| end | ||
|
|
||
| def duration | ||
| return @end_date - @start_date | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| require 'date' | ||
| require 'time' | ||
| require_relative 'reservation' | ||
| require_relative 'date_range' | ||
|
|
||
|
|
||
| module Hotel | ||
| class BlockReservation | ||
| attr_reader :date_range, :status | ||
| attr_accessor :room_num , :no_of_rooms, :block_reservations | ||
|
|
||
| def initialize(date_range, no_of_rooms) | ||
| @date_range = date_range | ||
| @no_of_rooms = no_of_rooms | ||
| @block_reservations = Array.new | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| require 'date' | ||
|
|
||
| require_relative 'reservation' | ||
| require_relative 'date_range' | ||
| require_relative 'hotel_block' | ||
|
|
||
| module Hotel | ||
| class HotelController | ||
| attr_reader :reservation_list | ||
| attr_accessor :room_list, :specific_date_reservation, :hotel_block_list | ||
|
|
||
| # Wave 1 | ||
| # default number of room in the hotel is 20 | ||
| def initialize(number_of_room = 20) | ||
| @reservation_list = Hash.new | ||
| @room_list = Array.new | ||
| @hotel_block_list = Hash.new | ||
|
|
||
| # added flexibilty to the number of room to have in the future | ||
| n = 1 | ||
| number_of_room.times do | ||
| @room_list << "Room #{n}" | ||
| n += 1 | ||
| end | ||
|
|
||
| end | ||
|
|
||
| # to get the list of rooms in the hotel | ||
| def get_room_list | ||
| return @room_list | ||
| end | ||
|
|
||
| def reserve_room(start_date, end_date, customer_name) | ||
| # start_date and end_date should be instances of class Date | ||
| # new data range and reservation created | ||
| # first available room assigned to the new reservation | ||
| raise ArgumentError.new("They are not the valid Date class for start_date and end_date") if (start_date.class != Date || end_date.class != Date) | ||
| resevation_duration = DateRange.new(start_date, end_date) | ||
| new_reservation = Reservation.new(resevation_duration, customer_name) | ||
| new_reservation.cost | ||
| reservation_id = @reservation_list.length + 1 | ||
| if self.available_rooms(start_date, end_date)[0] == nil | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor note: consider finding the available room before creating a new reservation and using this available room when instantiating the new reservation. |
||
| raise ArgumentError.new("Opps! There is no room availiable for this date range!") | ||
| else | ||
| new_reservation.room_num = self.available_rooms(start_date, end_date)[0] | ||
| end | ||
| @reservation_list[reservation_id] = new_reservation | ||
| end | ||
|
|
||
| def reservations(date) | ||
| specific_date_reservation = Array.new | ||
| @reservation_list.each_value do |reservation| | ||
| if reservation.date_range.include?(date) | ||
| specific_date_reservation << reservation | ||
| end | ||
| end | ||
|
|
||
| if specific_date_reservation.empty? | ||
| raise ArgumentError.new("There is no reservation on this day!") | ||
| else | ||
| return specific_date_reservation | ||
| end | ||
| end | ||
|
|
||
|
|
||
| def get_list_of_reservations(specific_room, start_date, end_date) | ||
| date_range_reservation_list = Array.new | ||
| check_date_range = Hotel::DateRange.new(start_date, end_date) | ||
| @reservation_list.each_value do |reservation| | ||
| if (reservation.date_range.overlap?(check_date_range) ) && (reservation.room_num == specific_room) | ||
| date_range_reservation_list << reservation | ||
| end | ||
| end | ||
| return date_range_reservation_list | ||
| end | ||
|
|
||
|
|
||
|
|
||
| def get_reservation_cost(reservation_id) | ||
| return self.reservation_list[reservation_id].cost | ||
| end | ||
|
|
||
| # Wave 2 | ||
| def available_rooms(start_date, end_date) | ||
| # start_date and end_date should be instances of class Date | ||
| available_rooms_list = Array.new | ||
| occupied_rooms_list = Array.new | ||
| perferred_date_range = Hotel::DateRange.new(start_date, end_date) | ||
| @reservation_list.each_value do |reservation| | ||
| if reservation.date_range.overlap?(perferred_date_range) | ||
| occupied_rooms_list << reservation.room_num | ||
| end | ||
| end | ||
| if occupied_rooms_list.empty? | ||
| return @room_list | ||
| else | ||
| available_rooms_list = @room_list - occupied_rooms_list | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider the fact that you don't necessarily need to check if occupied rooms are empty. |
||
| if available_rooms_list.empty? | ||
| raise ArgumentError.new("There is no more room for you!") | ||
| else | ||
| return available_rooms_list | ||
| end | ||
| end | ||
| end | ||
|
|
||
| #Wave 3 Hotel Block | ||
| def create_hotel_block(start_date, end_date, number_of_rooms) | ||
| raise ArgumentError.new("They are not the valid Date class for start_date and end_date") if (start_date.class != Date || end_date.class != Date) | ||
| raise ArgumentError.new("There is not enough room!") if number_of_rooms > 5 || number_of_rooms > self.available_rooms(start_date, end_date).length | ||
| block_duration = DateRange.new(start_date, end_date) | ||
| new_hotel_block = BlockReservation.new(block_duration, number_of_rooms) | ||
| number_of_rooms.times do | ||
| block_room = self.reserve_room(block_duration.start_date, block_duration.end_date, "Hotel Block Reserve") | ||
| block_room.status = :open_hotel_block | ||
| new_hotel_block.block_reservations << block_room | ||
| end | ||
| hotel_block_id = hotel_block_list.length + 1 | ||
| hotel_block_list[hotel_block_id] = new_hotel_block | ||
| return new_hotel_block | ||
| end | ||
|
|
||
| # check if a given block has any rooms available | ||
| # if there is available room - will return the list of rooms that are open | ||
| # else will raise argument | ||
|
|
||
| def check_hotel_block_list_availability(hotel_block_id) | ||
| raise ArgumentError.new("Not a valid Hotel Block ID!") if !(hotel_block_list.keys.include? hotel_block_id) | ||
| available_rooms_in_block = Array.new | ||
| hotel_block_list[hotel_block_id].block_reservations.each do |reservation| | ||
| if reservation.check_status | ||
| available_rooms_in_block << reservation.room_num | ||
| end | ||
| end | ||
|
|
||
| if available_rooms_in_block == [] | ||
| raise ArgumentError.new("No room available in this hotel block anymore!") | ||
| else | ||
| return available_rooms_in_block | ||
| end | ||
| end | ||
|
|
||
| def reserve_room_hotel_block(hotel_block_id, customer_name, specific_room) | ||
| raise ArgumentError.new("Not a valid Hotel Block ID!") if !(hotel_block_list.keys.include? hotel_block_id) | ||
|
|
||
| error_status = true | ||
|
|
||
| hotel_block_list[hotel_block_id].block_reservations.each do |reservation| | ||
| # check if the specific room requested in within the hotel block and not booked by another guests | ||
| #if hotel_block_list[hotel_block_id].check_valid_room(specific_room) && reservation.check_status | ||
| if (reservation.check_valid_room(specific_room)) && (reservation.check_status) | ||
| booking_room = reservation | ||
| booking_room.customer_name = customer_name | ||
| booking_room.status = :reserved_hotel_block | ||
| error_status = false | ||
| end | ||
| end | ||
| if error_status | ||
| raise ArgumentError.new("This is not a reserved room for the hotel block guest! Or it is already reserved by another guest!") | ||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| require 'date' | ||
| require 'time' | ||
| require_relative 'reservation' | ||
| require_relative 'date_range' | ||
| require_relative 'hotel_block' | ||
|
|
||
| module Hotel | ||
| class Reservation | ||
| attr_reader :date_range | ||
| attr_accessor :room_num, :status, :customer_name | ||
|
|
||
| def initialize(date_range, customer_name) | ||
| @date_range = date_range | ||
| @room_num = nil | ||
| @customer_name = customer_name | ||
| @status = :comfirmed | ||
| @cost = nil | ||
| end | ||
|
|
||
| def cost | ||
| # offering discount to hotel block customers | ||
| if @customer_name == "Hotel Block Reserve" | ||
| @cost = ((@date_range.duration)* 150).to_f | ||
| elsif | ||
| # how many night times 200 per night | ||
| @cost = ((@date_range.duration)* 200).to_f | ||
| end | ||
| return @cost | ||
| end | ||
|
|
||
| # for hotel blocks - to check if request room is within the block | ||
| def check_valid_room(request_room) | ||
| return self.room_num == request_room | ||
| end | ||
|
|
||
| # for hotel blocks - to make sure it is still open for hotel block guests | ||
| def check_status | ||
| return self.status == :open_hotel_block | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| To refactor: | ||
| - I think some of my methods are too complicated and too much dependency within methods. | ||
| I would love to spend some time to clean that up | ||
| - try to follow the single responsibility | ||
| - Dry it up! | ||
| - would like to add more stuff in each class so it would be small methods | ||
| - maybe I should have a room class? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| require_relative 'test_helper' | ||
|
|
||
| describe "Date Range class" do | ||
| before do | ||
| @data_range = Hotel::DateRange.new( | ||
| start_date = Date.new(2010,03,02), | ||
| end_date = Date.new(2010,03,05) | ||
| ) | ||
| @date_range_two = Hotel::DateRange.new( | ||
| start_date = Date.new(2010,03,8), | ||
| end_date = Date.new(2010,03,10) | ||
| ) | ||
| @date_range_three = Hotel::DateRange.new( | ||
| start_date = Date.new(2010,03,8), | ||
| end_date = Date.new(2010,03,10) | ||
| ) | ||
| end | ||
|
|
||
| it "is an instance of Date Range" do | ||
| expect(@data_range).must_be_kind_of Hotel::DateRange | ||
| end | ||
|
|
||
| describe "overlap?" do | ||
| it "will return false if the time is not overlapping" do | ||
| expect(@date_range_two.overlap?(@data_range)).must_equal false | ||
| end | ||
|
|
||
| it "will return true if the time is overlapping" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are good nominal case tests. It is important to thoroughly test the different ways that dates can overlap. See this pseudo code from the design-scaffold |
||
| expect(@date_range_two.overlap?(@date_range_three)).must_equal true | ||
| end | ||
| end | ||
| end | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider putting this exception raising functionality into the DateRange class.