forked from AdaGold/hotel
-
Notifications
You must be signed in to change notification settings - Fork 40
Time - Nataliya #18
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
Open
npogodina
wants to merge
35
commits into
Ada-C13:master
Choose a base branch
from
npogodina:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Time - Nataliya #18
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
919217f
Created Room class and test file for it.
npogodina e84382d
Added ReservationDesk class with #rooms method and its tests.
npogodina 808a723
Added Reservation class and its tests.
npogodina a19a52c
Added ReservationDesk#new_reservation and add_reservation methods.
npogodina 3daf2a3
Updated arguments to be keyword in Reservation constructor.
npogodina fbd6f3d
Added ReservationDesk#find_reservations.
npogodina 92fd3e5
Added ReservationDesk#find_room_by_id.
npogodina d1f4381
Fixed bug when ReservationDesk#rooms was creating a new array each ti…
npogodina f09559e
Moved ReservationDesk#make_rooms to private.
npogodina 7b6b246
Added ReservationDesk#add_reservation method.
npogodina 9c03227
Added ReservationDesk#find_reservations method.
npogodina 4667767
Added test outlines for ReservationDesk#find_reservations.
npogodina 7a2130b
Changed all ReservationDesk#find_reservations arguments to be require…
npogodina 1627956
Added DateRange class and DateRange#overlap?.
npogodina 4bb0daf
Updated Reservation class and ReservationDesk#find_reservations to us…
npogodina e4faec3
Updated ReservationDesk#find_reservations: room_id is optional.
npogodina 1054cdc
Added DateRange#nights.
npogodina 517de12
Added Reservation#cost.
npogodina b8b358c
Added ReservationDesk#find_available_room.
npogodina 296d1e7
Added ReservationDesk#make_reservation.
npogodina f9687ca
Added SimpleCov.
npogodina 1b758d8
Filtered tests to be excluded out of SimpleCov report.
npogodina f230fa3
Added ReservationDesk#find_reservations.
npogodina 2691071
Replaced ReservationDesk#find_available_room with check_availability.
npogodina aa5b820
Added Room#available? and Room#reserve, refactored ReservationDesk.
npogodina f8e561b
Fixed tests for ReservationDesk#find_reservations.
npogodina ad95773
Added Room#select_reservations.
npogodina 1bd279c
Added ReservationDesk#make_block and Room#add_block_participation.
npogodina ca06712
Added functionality to specify rate when making reservation/block.
npogodina ee4a5ad
Added helper methods Room#reserved? and Room#in_block?.
npogodina cb44c5f
Added ReservationDesk#reserve_from_block.
npogodina afdbe86
Added ReservationDesk#check_block_availability.
npogodina 586eef5
Added more tests.
npogodina 47056a5
Cleaned up files, added TODOs.
npogodina 3007f63
Added refactors.txt.
npogodina File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| module Hotel | ||
| class DateRange | ||
| attr_reader :start_date, :end_date | ||
|
|
||
| def initialize(start_date:, end_date:) | ||
| #TODO: validate dates' input | ||
| #TODO: add defaults (for example, one year from/before Date.today) | ||
| @start_date = Date.parse(start_date) | ||
| @end_date = Date.parse(end_date) | ||
|
|
||
| raise ArgumentError.new("End date cannot be equal to or come before start date.") if @end_date <= @start_date | ||
| end | ||
|
|
||
| def overlap?(date_range) | ||
| raise ArgumentError.new("Must provide a date range.") unless date_range.is_a? DateRange | ||
|
|
||
| #TODO: efficient date checking (first compare years? months?) | ||
| start_date < date_range.end_date && end_date > date_range.start_date | ||
| end | ||
|
|
||
| def nights | ||
| (end_date - start_date).to_i | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| require "date" | ||
|
|
||
| module Hotel | ||
| class Reservation | ||
| attr_reader :date_range, :room_id, :rate | ||
|
|
||
| def initialize(room_id: , start_date:, end_date:, rate: :default) | ||
| unless (rate == :default || rate.respond_to?(:>) && rate >= 0) | ||
| raise ArgumentError.new("Invalid rate.") | ||
| end | ||
|
|
||
| @date_range = DateRange.new(start_date: start_date, end_date: end_date) | ||
| @room_id = room_id | ||
| @rate = (rate == :default) ? 200 : rate | ||
| end | ||
|
|
||
| def cost | ||
| date_range.nights * rate | ||
| end | ||
| end | ||
| end | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| module Hotel | ||
| class ReservationDesk | ||
| # Class responsibility: to organize reservations across hotel | ||
| attr_reader :room_num, :rooms, :reservations, :blocks | ||
|
|
||
| def initialize(room_num: 20) | ||
| @room_num = room_num | ||
| @rooms = make_rooms | ||
| @blocks = {} | ||
| end | ||
|
|
||
| def find_room_by_id(id) | ||
| rooms.find {|room| room.id == id} | ||
| end | ||
|
|
||
| def find_reservations(room_id: nil , start_date: , end_date: ) | ||
| date_range = DateRange.new(start_date: start_date, end_date: end_date) | ||
|
|
||
| if room_id | ||
| room = rooms.find { |room| room.id == room_id} | ||
| return nil if room == nil | ||
| reservations = room.select_reservations(date_range) | ||
| else | ||
| reservations = [] | ||
| rooms.each do |room| | ||
| room_reservations = room.select_reservations(date_range) | ||
| reservations += room_reservations | ||
| end | ||
| end | ||
| return reservations | ||
| end | ||
|
|
||
| def find_available_rooms(start_date:, end_date:) | ||
| available_rooms = [] | ||
| rooms.each do |room| | ||
| available_rooms << room if room.available?(start_date: start_date, end_date: end_date) | ||
| end | ||
| return available_rooms.empty? ? nil : available_rooms | ||
| end | ||
|
|
||
| def make_reservation(room_id: nil, start_date:, end_date:, rate: :default) | ||
| if room_id | ||
| room = find_room_by_id(room_id) | ||
| raise ArgumentError.new("Invalid room ID.") if room == nil | ||
| else | ||
| room = find_available_rooms(start_date: start_date, end_date: end_date)[0] | ||
| raise StandardError.new("No rooms available for these dates.") if room == nil | ||
| end | ||
| room.reserve(start_date: start_date, end_date: end_date, rate: rate) | ||
| end | ||
|
|
||
| def make_block(room_ids:, start_date:, end_date:, rate: :default) | ||
| #TODO: add no rooms given scenario | ||
| raise ArgumentError.new("Blocks should contain 2-5 rooms.") if (room_ids.length > 5 || room_ids.length < 2) | ||
|
|
||
| block_id = create_block(start_date: start_date, end_date: end_date) | ||
| room_ids.each do |id| | ||
| room = find_room_by_id(id) | ||
| raise ArgumentError.new("Invalid room ID.") if room == nil | ||
| room.reserve(start_date: start_date, end_date: end_date, block: block_id, rate: rate) | ||
| blocks[block_id][:rooms] << room | ||
| end | ||
| end | ||
|
|
||
| def reserve_from_block(room_id: , block_id: ) | ||
| raise ArgumentError.new("Invalid block ID.") unless blocks[block_id] | ||
|
|
||
| blocks[block_id][:rooms].each do |room| | ||
| if room.id == room_id | ||
| start_date = blocks[block_id][:date_range][0] | ||
| end_date = blocks[block_id][:date_range][1] | ||
| unless room.reserved?(start_date: start_date, end_date: end_date) | ||
| room.block_participation.each do |block_part| | ||
| if block_part.date_range.start_date == Date.parse(start_date) | ||
| room.reservations << block_part | ||
| return true | ||
| end | ||
| end | ||
| end | ||
| raise StandardError.new("This room has already been reserved.") | ||
| end | ||
| end | ||
| raise ArgumentError.new("Invalid room ID.") | ||
| end | ||
|
|
||
| def check_block_availability(block_id) | ||
| raise ArgumentError.new("Invalid block ID.") unless blocks[block_id] | ||
| available_rooms = [] | ||
| start_date = blocks[block_id][:date_range][0] | ||
| end_date = blocks[block_id][:date_range][1] | ||
|
|
||
| blocks[block_id][:rooms].each do |room| | ||
| available_rooms << room unless room.reserved?(start_date: start_date, end_date: end_date) | ||
| end | ||
| return available_rooms | ||
| end | ||
|
|
||
| private | ||
| def make_rooms | ||
| rooms = [] | ||
| room_num.times do |i| | ||
| rooms << Room.new(i+1) | ||
| end | ||
| return rooms | ||
| end | ||
|
|
||
| def generate_block_id | ||
| blocks.length + 1 | ||
| end | ||
|
|
||
| def create_block(start_date:, end_date:) | ||
| block_id = generate_block_id | ||
| blocks[block_id] = {} | ||
| blocks[block_id][:date_range] = [start_date, end_date] | ||
| blocks[block_id][:rooms] = [] | ||
| return block_id | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| module Hotel | ||
|
|
||
| class Room | ||
| # Class responsibility: to reserve individual rooms | ||
| attr_reader :id, :reservations, :block_participation | ||
|
|
||
| def initialize(id) | ||
| @id = id | ||
| @reservations = [] | ||
| @block_participation = [] | ||
| end | ||
|
|
||
| # available? helper method / public interface | ||
| def reserved?(start_date:, end_date:) | ||
| date_range = DateRange.new(start_date: start_date, end_date: end_date) | ||
| reservations.each do |reservation| | ||
| if reservation.date_range.overlap? (date_range) | ||
| return true | ||
| end | ||
| end | ||
| return false | ||
| end | ||
|
|
||
| # available? helper method / public interface | ||
| def in_block?(start_date:, end_date:) | ||
| date_range = DateRange.new(start_date: start_date, end_date: end_date) | ||
| block_participation.each do |block_reservation| | ||
| if block_reservation.date_range.overlap? (date_range) | ||
| return true | ||
| end | ||
| end | ||
| return false | ||
| end | ||
|
|
||
| def available?(start_date:, end_date:) | ||
| (reserved?(start_date: start_date, end_date: end_date) || in_block?(start_date: start_date, end_date: end_date)) ? false : true | ||
| end | ||
|
|
||
| def reserve(start_date:, end_date:, block: nil, rate: :default) | ||
| unless available?(start_date: start_date, end_date: end_date) | ||
| raise StandardError.new("Room #{id} is unavailabe for requested dates.") | ||
| end | ||
| reservation = new_reservation(start_date: start_date, end_date: end_date, rate: rate) | ||
| block ? add_block_participation(reservation) : add_reservation(reservation) | ||
| end | ||
|
|
||
| def select_reservations(date_range) | ||
| reservations.select { |reservation| reservation.date_range.overlap? (date_range)} | ||
| end | ||
|
|
||
| private | ||
| def new_reservation(start_date:, end_date:, rate: :default) | ||
| reservation = Reservation.new(room_id: id, start_date: start_date, end_date: end_date, rate: rate) | ||
| end | ||
|
|
||
| def add_reservation(reservation) | ||
| reservations << reservation | ||
| end | ||
|
|
||
| def add_block_participation(reservation) | ||
| block_participation << reservation | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| 1. Consider adding Block Class instead of hash structure in ReservationDesk | ||
| - ReservationDesk will have a blocks array of Block objects. | ||
| - ReservationDesk will have find_block_by_id method. | ||
| - Block object will have block_id, rooms (array of Room objects), date_range variables. | ||
| - Block object will have reserve_from_block and check_room_availability methods which will be called from inside current ReservationDesk methods. | ||
|
|
||
| 2. Add date input validation. | ||
|
|
||
| 3. Add defaults for start and end dates. | ||
| (gives functionality to select all reservations from/until specific date) | ||
|
|
||
| 4. Find a more efficient way to compare dates. | ||
| (sort and compare years/months first?..) | ||
|
|
||
| 5. Consider moving away from having start and end_date as arguments towards using date_range. | ||
|
|
||
| 6. Implement "no rooms given" scenario for make_block. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| require_relative "test_helper" | ||
|
|
||
| describe "DateRange class" do | ||
| describe "DateRange instatiation" do | ||
| # before do | ||
| # date_range = Hotel::DateRange.new() | ||
| # end | ||
| it "is an instance of DateRange" do | ||
| expect(Hotel::DateRange.new(start_date: "2020-3-1", end_date: "2020-3-10")).must_be_kind_of Hotel::DateRange | ||
| end | ||
|
|
||
| it "converts its start_date and end_date attributes to Date objects" do | ||
| date_range = Hotel::DateRange.new(start_date: "2020-3-1", end_date: "2020-3-10") | ||
| expect(date_range.start_date).must_be_kind_of Date | ||
| expect(date_range.end_date).must_be_kind_of Date | ||
| end | ||
|
|
||
| it "raises an ArgumentError if end_date is equal to or comes before start_date" do | ||
| expect {Hotel::DateRange.new(start_date: "2020-3-1", end_date: "2020-2-10")}.must_raise ArgumentError | ||
| expect {Hotel::DateRange.new(start_date: "2020-3-1", end_date: "2020-3-1")}.must_raise ArgumentError | ||
| end | ||
|
|
||
| # TODO | ||
| # it "can be instantiated with no arguments" do | ||
| # expect(Hotel::DateRange.new()).must_be_kind_of Hotel::DateRange | ||
| # end | ||
| end | ||
|
|
||
| describe "overlap?" do | ||
| let (:date_range) { | ||
| Hotel::DateRange.new(start_date: "2020-3-1", end_date: "2020-3-20") | ||
| } | ||
|
|
||
| it "expects a DateRange as an argument" do | ||
| expect {date_range.overlap?(50)}.must_raise ArgumentError | ||
| end | ||
|
|
||
| it "returns true if the dates overlap and false if not" do | ||
| # TODO: each one should be a new test? | ||
|
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. Since each other this |
||
| second_date_range = Hotel::DateRange.new(start_date: "2020-3-2", end_date: "2020-3-10") | ||
| expect(date_range.overlap?(second_date_range)).must_equal true | ||
|
|
||
| third_date_range = Hotel::DateRange.new(start_date: "2020-3-13", end_date: "2020-3-25") | ||
| expect(date_range.overlap?(third_date_range)).must_equal true | ||
|
|
||
| forth_date_range = Hotel::DateRange.new(start_date: "2020-2-10", end_date: "2020-2-26") | ||
| expect(date_range.overlap?(forth_date_range)).must_equal false | ||
|
|
||
| fifth_date_range = Hotel::DateRange.new(start_date: "2020-3-23", end_date: "2020-3-25") | ||
| expect(date_range.overlap?(fifth_date_range)).must_equal false | ||
|
|
||
| six_date_range = Hotel::DateRange.new(start_date: "2020-3-20", end_date: "2020-3-21") | ||
| expect(date_range.overlap?(six_date_range)).must_equal false | ||
| end | ||
|
|
||
| # TODO: | ||
| # it "expects a DateRange provided as an argument to have start_date and end_date rather than nil" do | ||
| # other_date_range_1 = Hotel::DateRange.new(end_date: "2020-5-10") | ||
| # expect {date_range.overlap? (other_date_range_1)}.must_raise ArgumentError | ||
|
|
||
| # other_date_range_2 = Hotel::DateRange.new(start_date: "2020-5-10") | ||
| # expect {date_range.overlap? (other_date_range_2)}.must_raise ArgumentError | ||
| # end | ||
| end | ||
|
|
||
| describe "nights" do | ||
| it "calculates the number of nights for the date range" do | ||
| date_range = Hotel::DateRange.new(start_date: "2020-3-1", end_date: "2020-3-10") | ||
| expect(date_range.nights).must_equal 9 | ||
|
|
||
| date_range = Hotel::DateRange.new(start_date: "2020-3-1", end_date: "2020-3-2") | ||
| expect(date_range.nights).must_equal 1 | ||
| end | ||
| end | ||
|
|
||
| end | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Nice use of a ternary, and an optional keyword argument