Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a2c2c4d
Build design scaffolding
Jul 25, 2019
22cee60
Merge branch 'master' of github.com:AdaGold/hotel into dpr/c12-scaffo…
Jul 25, 2019
df7c9b8
Update notes about design scaffolding
Jul 25, 2019
a673135
Add interface test for HotelController#available_rooms
Jul 25, 2019
d5489c4
Correct branch name for merge instructions
Jul 29, 2019
e9ec9b5
Merge pull request #20 from AdaGold/dpr/c12-scaffolding
Jul 29, 2019
b454eb1
spec -> test
kaidamasaki Sep 5, 2019
5717d12
conforms the text to imply more of an activity
tildeee Feb 25, 2020
e738121
direct link to this repo and branch
tildeee Feb 25, 2020
7e4e15f
Merge remote-tracking branch 'origin/design-scaffolding'
easternwashingaden Mar 5, 2020
c6c1817
Added all 4 classes and tests were passed
easternwashingaden Mar 5, 2020
71b8182
finished reserve_room methods, created tests, and passed all the tests
easternwashingaden Mar 6, 2020
2f86780
Finished wave 1
easternwashingaden Mar 6, 2020
b3956ec
make some changes on reserved_room method
easternwashingaden Mar 6, 2020
e33d9d6
Completed Wave 2 and passed all tests
easternwashingaden Mar 6, 2020
46bb794
saved before started wave 3
easternwashingaden Mar 7, 2020
d2430ce
Initialize the HotelBlock class and create a method called create_hot…
easternwashingaden Mar 7, 2020
a539e86
Created the room_list of hotel_block and worte tests and passed
easternwashingaden Mar 8, 2020
5e285d8
create available_rooms_of_block worte tests and passed
easternwashingaden Mar 8, 2020
7083f1b
finished Wave 3 before modifying the reserve_room method in Wave 2
easternwashingaden Mar 8, 2020
4244f69
Modified reserve_room method and test and passed all tests.
easternwashingaden Mar 8, 2020
3455f40
added more tests for wave 1 and wave 2
easternwashingaden Mar 8, 2020
9ab4b60
Finished Wave 3 and tests for wave 3 and all passed
easternwashingaden Mar 9, 2020
5564fb4
finished writing test for hotel_block_test and all passed
easternwashingaden Mar 9, 2020
ed6159a
Cleaned up and completed.
easternwashingaden Mar 9, 2020
36075da
added a nominal test for reservation_id
easternwashingaden Mar 9, 2020
2b36987
added refactor.txt
easternwashingaden Mar 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions design-scaffolding-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Hotel Design Scaffolding

## How to Read This Scaffolding to Create a Second Draft

This scaffolding is one solution that answers some of the initial questions about how project files can be laid out.

Use [this view of our branch on GitHub.com](https://github.com/AdaGold/hotel/tree/design-scaffolding) to explore the files that exist on this repo.
- What classes exist?
- Why? What are they named, what do they represent, and what state and behavior do they have?
- What tests exist?
- What parts of this design inspires you, and you want to steal?
- What parts of this design are you unsure about, and need to consider again later?
- What parts of this design do you think you can do without?

Spend **no more than 1 hour** answering those questions and adjusting your project's first draft design. After one hour, get started; don't forget that a useful skill for the programmer is the ability to get started, and adjust in small ways often.

### What it includes

- Three class stubs, `HotelController`, `Reservation` and `DateRange`
- Stubs for public methods of each class from waves 1 and 2, as described in the user stories
- "Interface" tests for each class method that invoke it with the right parameters and verify the return type
- Full test stubs for the `DateRange` class

### What it does not include

- Opinions about how classes should interact or data should be stored
- Opinions about whether there should be a `Room` class, or whether it should know about `Reservation`s
- Private helper methods to keep code organized

Students should feel free to modify any code as they see fit, including changing method signatures, adding new classes and methods, reordering things, not looking at the `DateRange` tests because they want to give it a shot on their own, etc.

## How to use this code

Design scaffolding code lives on the `design-scaffolding` branch.

You can use this code either as inspiration, or as a starting point. If using it as an inspiration, it follows our standard project layout, with product code under `lib/` and tests under `test/`.

If you choose to use the code on this branch as a starting point, you can either:

1. Copy and paste each file from this project into your existing `hotel` folder
2. Or start your project anew with the following steps:

```
$ git clone <paste forked repo URL>
$ cd hotel
$ git merge origin/design-scaffolding
```

- Note: You can try to merge in the design scaffolding after you've started, but you'll probably end up with merge conflicts. See an instructor if you're not able to resolve them yourself.
44 changes: 44 additions & 0 deletions lib/date_range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Hotel
class DateRange
attr_accessor :start_date, :end_date

def initialize(start_date, end_date)
unless start_date.instance_of?(Date) || end_date.instance_of?(Date)
raise ArgumentError.new("start_date and end_date have to be a date type")
end

if end_date < start_date
raise ArgumentError.new("The end_date cannot be less than start_end")
end

if start_date == end_date
raise ArgumentError.new("The start_date cannot be the same as end_date")
end
@start_date = start_date
@end_date = end_date

end

# define exactly what it means for two instances of its own class to be equal.
def ==(other)
self.start_date == other.start_date && self.end_date == other.end_date
end

def overlap?(other) #other is another instance of date_range
start_date < other.end_date && other.start_date < end_date
end

def include?(date) # date is a date
start_date <= date && end_date > date
end

# def include?(date_range) # other is an instance of date_range
# start_date <= date_range.start_date && end_date > date_range.end_date
# end

def count_nights
total_nights = (end_date - start_date).to_i
return total_nights
end
end
end
14 changes: 14 additions & 0 deletions lib/hotel_block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Hotel
class HotelBlock
attr_reader :date_range , :rooms , :discounted_rate
def initialize(date_range, rooms, discounted_rate)
@date_range = date_range
raise ArgumentError.new("A block can contain a maximum of 5 rooms") if rooms.length > 5
raise ArgumentError.new("The hotel block cannot be made without having a room") if rooms.empty?
@rooms = rooms
@discounted_rate = 0.1
end
Comment on lines +2 to +10

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A class that only has an initialize method is usually a sign that this didn't need to be a fully fledged class. With this method, it seems like you could have done the work of the HotelBlock class using a hash instead.

Sometimes what this means is that you are letting the wrong class take on responsibilities that belong to this data.

end
end


228 changes: 228 additions & 0 deletions lib/hotel_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
module Hotel
class HotelController
attr_reader :rooms
attr_accessor :reservations, :hotel_blocks
def initialize
@rooms = Array.new(20){|i| Hotel::Room.new(i+1)}
@reservations = []
@hotel_blocks = [] #contain a number of rooms and a specific set of days
end

################# Wave 1

# Access the list of all of the rooms in the hotel
def self.rooms
room_list = HotelController.rooms
return room_list
end

# Access the list of reservations for a specified room and a given date range
def reservations_list_room_and_date(given_room, given_date_range)
reservations_list_of_given_room_date_range = reservations.select do |res|
res.date_range.overlap?(given_date_range) && res.room == given_room
end
return reservations_list_of_given_room_date_range
end

# Add reservation to the list of the reservations
def add_reservation(reservation)
@reservations << reservation
end

# Access the list of reservations for a specific date, so that I can track reservations by date
def reservations_list(date)
reservation_list = reservations.select do |res|
res.date_range.include?(date)
end
return reservation_list
end

# Can get the total cost for a given reservation
def total_cost(reservation)
total_cost = reservation.cost
return total_cost
end

##################### Wave 2
# Get reservations_list for a given date range
def reservations_list_by_date_range(start_date, end_date)
given_date_range = Hotel::DateRange.new(start_date, end_date)
# Get the reservations_list for the given date range
reservations_list_by_date_range = reservations.select do |res|
res.date_range.overlap?(given_date_range)
end
end

def reserved_rooms_list(start_date, end_date)
given_date_range = Hotel::DateRange.new(start_date, end_date)
# Get reservations_list for a given date range
reservations_list_by_date_range = reservations_list_by_date_range(start_date, end_date)

# Get all the room that have been reserved for the given date range
all_reserved_rooms = reservations_list_by_date_range.map do |res|
res.room
end
return all_reserved_rooms
end

# I can view a list of rooms that are not reserved for a given date range,
# so that I can see all available rooms for that day
def available_rooms(start_date, end_date)
given_date_range = Hotel::DateRange.new(start_date, end_date)

# get all the room that have been reserved for the given date range
all_reserved_rooms = reserved_rooms_list(start_date, end_date)
# get all rooms that are in the hotel blocks
all_rooms_hotel_block = rooms_list_for_hotel_block(start_date, end_date)

# get the aviable_rooms_list
available_rooms_list = rooms.reject do |room|
all_reserved_rooms.any? {|res_room| res_room.id == room.id} || all_rooms_hotel_block.any? {|block_room| block_room.id == room.id}
end
return available_rooms_list
end

# I can make a reservation of a room for a given date range,
# and that room will not be part of any other reservation overlapping that date range
# done already in wave 1

def reserve_room(start_date, end_date)
given_date_range = Hotel::DateRange.new(start_date, end_date)
avialable_rooms_list = available_rooms(start_date, end_date)
if avialable_rooms_list.empty?
raise NoRoomAvailableError.new("there is no available room.")
end
id = reservations.length + 1
reservation = Hotel::Reservation.new(id,given_date_range, avialable_rooms_list.first)
add_reservation(reservation)
return reservation
end

############## Wave 3

# Add hotel_block method
def add_hotel_block(hotel_block)
@hotel_blocks << hotel_block
end
# Get the hotel_block_list for a given date (not exact match date range)
def hotel_block_list(start_date, end_date)
given_date_range = Hotel::DateRange.new(start_date, end_date)
# get the list of the hotel_block for the given date
hotel_block_list = hotel_blocks.select do |hotel_block|
hotel_block.date_range.overlap?(given_date_range)
end
return hotel_block_list
end

# Get the rooms_list_for_hotel_block
def rooms_list_for_hotel_block(start_date, end_date)
hotel_block_list = hotel_block_list(start_date, end_date)
# get all arrays of rooms from the hotel_block_list for the given date
rooms_hotel_block_arrays = hotel_block_list.map do |hotel_block|
hotel_block.rooms
end
# get all the rooms from the list of
all_rooms_hotel_block = rooms_hotel_block_arrays.flatten
return all_rooms_hotel_block
end

# Create a hotel_block
def create_hotel_block(date_range, rooms_array, discount_rate)
# all rooms of rooms_array must be available (not in the reservations list) during the given date range
all_reserved_rooms = reserved_rooms_list(date_range.start_date, date_range.end_date)

# Cannot create another hotel block that any existing block includes that specific room for that specific date
all_rooms_hotel_block = rooms_list_for_hotel_block(date_range.start_date, date_range.end_date)
# an exception raised if I try to create a Hotel Block
# and at least one of the rooms is unavailable for the given date range

rooms_array.each do |room|
if all_reserved_rooms.any? {|r|r == room} || all_rooms_hotel_block.any? {|r| r == room}
raise ArgumentError.new("There is reservation conflict")
end
end
hotel_block = Hotel::HotelBlock.new(date_range, rooms_array, discount_rate)
add_hotel_block(hotel_block)
return hotel_block
end

# check whether a given block has any rooms available
def available_rooms_of_block(hotel_block)
if hotel_block.rooms.empty?
raise ArgumentError.new("The hotel block cannot be made without having a room")
else
return hotel_block.rooms
end
end
Comment on lines +150 to +156

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method also seems like something the HotelBlock should be in charge of. if it were in the HotelBlock, it might look like this

Suggested change
def available_rooms_of_block(hotel_block)
if hotel_block.rooms.empty?
raise ArgumentError.new("The hotel block cannot be made without having a room")
else
return hotel_block.rooms
end
end
def available_rooms
if self.rooms.empty?
raise ArgumentError.new("The hotel block cannot be made without having a room")
else
return rooms
end
end

Moving this code both makes HotelController easier to read, and makes for fewer chained method calls.


# Get the list of the hotel_block for a specific full date range (exact match the full date range)
def hotel_blocks_for_specific_date_range(start_date, end_date)
specific_date_range = Hotel::DateRange.new(start_date, end_date)
hotel_blocks_for_specific_date_range = hotel_blocks.select do |hotel_block|
hotel_block.date_range == specific_date_range
end
return hotel_blocks_for_specific_date_range
end

# Get available_rooms_of_hotel_blocks for a specific full date range (exact match the full date range)
def available_rooms_of_hotel_blocks(start_date, end_date)
hotel_blocks_for_specific_date_range = hotel_blocks_for_specific_date_range(start_date, end_date)
if hotel_blocks_for_specific_date_range.empty?
raise ArgumentError.new ("no hotel_block for the given date range.")
end
available_rooms_of_hotel_blocks = hotel_blocks_for_specific_date_range.map do |hotel_block|
hotel_block.rooms
end
all_available_rooms_of_hotel_blocks = available_rooms_of_hotel_blocks.flatten
end

# Get specific hotel_block with a given room, start_date, and end_date
def specific_hotel_block(room, start_date, end_date)
specific_date_range = Hotel::DateRange.new(start_date, end_date)
# Check to see which hotel_block the room lives in (one room can be assigned to only one hotel_block for a specific date range )
specific_hotel_block_list = hotel_blocks.select do |hotel_block|
hotel_block.date_range == specific_date_range && hotel_block.rooms.any? {|r| r.id == room.id}
end
if specific_hotel_block_list.empty?
raise ArgumentError.new("there is no hotel_block for the given room or date range.")
end
specific_hotel_block = specific_hotel_block_list[0]
return specific_hotel_block
end

# remove the room from the hotel_block for a specific date_range
def remove_room_from_hotel_block(room, start_date, end_date)
specific_hotel_block = specific_hotel_block(room, start_date, end_date)
specific_hotel_block.rooms.delete(room)
return specific_hotel_block
end
Comment on lines +194 to +198

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like something the HotelBlock should be in charge of to me.


# remove/delete the whole hotel block
def delete_hotel_block(hotel_block)
hotel_blocks.delete(hotel_block)
end

# I can reserve a specific room from a hotel block
# I can only reserve that room from a hotel block for the full duration of the block
# I can see a reservation made from a hotel block from the list of reservations for that date (see wave 1 requirements)
def reserve_room_from_hotel_block(room,start_date, end_date)
given_date_range = Hotel::DateRange.new(start_date, end_date)
all_available_rooms_of_hotel_blocks = available_rooms_of_hotel_blocks(start_date, end_date)
if all_available_rooms_of_hotel_blocks.empty?
raise NoRoomAvailableError.new("there is no available room.")
end
if all_available_rooms_of_hotel_blocks.any?(room)
id = reservations.length + 1
reservation = Hotel::Reservation.new(id,given_date_range,room)
# Add the reservation to the reservation list
add_reservation(reservation)
# remove the room from the all_available_rooms_of_hotel_blocks
hotel_block_after_reservation = remove_room_from_hotel_block(room, start_date, end_date)
if hotel_block_after_reservation.rooms.empty?
delete_hotel_block(hotel_block_after_reservation)
end
end
return reservation
end
end
end
4 changes: 4 additions & 0 deletions lib/no_room_available_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Hotel
class NoRoomAvailableError < StandardError
end
Comment on lines +2 to +3

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't have to be in it's own file! :)

end
18 changes: 18 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'date'
module Hotel
class Reservation
attr_reader :id, :room, :date_range
def initialize(id,date_range,room)
unless id.instance_of?(Integer) && id >0
raise ArgumentError.new("Id must be a positive integer")
end
@id = id
@date_range = date_range
@room = room
end

def cost
total_cost = date_range.count_nights * 200
end
end
end
19 changes: 19 additions & 0 deletions lib/room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Hotel
class Room
attr_reader :id, :cost
def initialize(id, cost = 200)
unless id.instance_of?(Integer) && id >0
raise ArgumentError.new("Id must be a positive integer")
end
unless cost.instance_of?(Integer) && cost >= 0
raise ArgumentError.new("cost must be a positive value")
end
@id = id
@cost = cost
end

def ==(other)
self.id == other.id
end
Comment on lines +15 to +17

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work overwriting this method!

end
end
Loading