Skip to content

Space - Yieni#25

Open
yieknee wants to merge 30 commits intoAda-C13:masterfrom
yieknee:master
Open

Space - Yieni#25
yieknee wants to merge 30 commits intoAda-C13:masterfrom
yieknee:master

Conversation

@yieknee
Copy link

@yieknee yieknee commented Mar 9, 2020

Assignment Submission: Hotel

Congratulations! You're submitting your assignment. Please reflect on the assignment with these questions.

Reflection

Question Answer
What was a design challenge that you encountered on this project? Figuring out how I want my classes to interact while decreasing the number of dependencies
What was a design decision you made that changed over time over the project? I originally had my room class having instance variables for block status, which returned in block or not in block. When I added a room to a block I would change to the status to in block. However, I realized that the status changed remained for the life of the room and not for the specific date range the room was in a block. I deleted that instance variable and handled checking for available rooms in a different way.
What was a concept you gained clarity on, or a learning that you'd like to share? I gained clarity on single responsibility, and tried to make sure my methods were only doing one thing.
What is an example of a nominal test that you wrote for this assignment? What makes it a nominal case? I wrote a nominal case to check that a Reservation object was created .
What is an example of an edge case test that you wrote for this assignment? What makes it an edge case? I wrote edge cases for scenarios where there are no available rooms
How do you feel you did in writing pseudocode first, then writing the tests and then the code? I think it helps me plan out what to test and how I will write the code that is being tested.

yieknee added 30 commits March 2, 2020 14:11
@dHelmgren
Copy link

Hotel

Section 1: Major Learning Goals

Criteria yes/no, and optionally any details/lines of code to reference
Practices SRP by having at least two separate classes with distinct responsibilities, and test files for these two classes ✔️
Overall, demonstrates understanding instance variables vs. local variables. (There aren't unnecessarily too many instance variables, when it should be a local variable) ✔️
For each test file, tests demonstrate an understanding of instantiating objects properly, and using Arrange-Act-Assert ✔️
Practices pseudocode and TDD, and reflected on it by filling out the reflection questions ✔️
Practices git with at least 15 small commits and meaningful commit messages ✔️

Section 2: Code Review and Testing Requirements

Criteria yes/no, and optionally any details/lines of code to reference
There is a class that represents a reservation, and a second class that holds/manages a collection of reservations through composition (instance variable) ✔️
The logic for checking if a reservation's date overlaps with another reservation's date is complex logic that is separated into method(s) (and potentially class(es)) ✔️
The logic for checking if a reservation's date overlaps with another reservation's date has unit tests ✔️
All of the given tests run and pass ✔️
A test coverage tool is installed and used, and shows 95% test coverage ✔️

Section 3: Feature Requirements

Feature Requirement: There is a method that... yes/no
gives back a list of rooms, and it's tested ✔️
creates a specific reservation for a room for a given date range, and it has nominal test cases ✔️
creates a specific reservation for a room for a given date range, and it tests an edge case, such as no available room, or invalid date range ✔️
gives back a list of reservations on a given date. Its tests include a test that makes several reservations for a given date ✔️
calculates the total price for a reservation ✔️
gives back a list of available rooms for a given date range, and it has nominal test cases ✔️
gives back a list of available rooms for a given date range, and it has edge test cases, such as no available room, or invalid date range ✔️
creates a block of rooms ✔️
reserves a room from a block ✔️

Overall Feedback

Overall Feedback Criteria yes/no
Green (Meets/Exceeds Standards) 14+ total in all sections ✔️
Yellow (Approaches Standards) 9-13 total in all sections
Red (Not at Standard) 0-8 total in all sections, or assignment is breaking/doesn’t run with less than 5 minutes of debugging

Additional Feedback

Great work overall! You've built your first project with minimal starting code. This represents an incredible milestone in your journey, and you should be proud of yourself!

I am particularly impressed by the way that you cleaned up your code for submission and made lots of small, solid commits! You seem to have double checked and gotten rid of any warnings that your code threw, which is really nice to see! I also love that you were constantly committing code as you worked on it! It will totally save your bacon in the future!

I do see some room for improvement around separating class responsibilities. Your code has a lot of classes that only initialize themselves. Thing is, if all a class does is initialize itself, why couldn't it just be a hash? See my comments for where this could be improved!

Code Style Bonus Awards

Was the code particularly impressive in code style for any of these reasons (or more...?)

Quality Yes?
Descriptive/Readable
Logical/Organized

Comment on lines +4 to +29
class DateRange
attr_reader :start_date, :end_date, :range

def initialize(start_date:, end_date:)
raise ArgumentError.new("start and end dates must be Date objects") if start_date.class != Date && end_date.class != Date
@start_date = start_date
@end_date = end_date
@range = (@start_date .. @end_date).to_a
raise ArgumentError.new("End date can not be before start date") if @end_date < @start_date
raise ArgumentError.new("Reservation can not be before today") if @end_date < Date.today || @start_date < Date.today

end

def overlap?(date_range)
# if the array of the combined arrays is empty, there is no overlap, so return false
# if the array is not empty, return true
overlap = (self.range & date_range.range).empty? || (date_range.start_date >= self.end_date) || (date_range.end_date <= self.start_date) ? false : true
return overlap
end

def nights
return @range.count - 1
end


end

Choose a reason for hiding this comment

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

A thought you might enjoy chewing on: how would your code change if class DateRange < Range?

Comment on lines +2 to +18
class HotelBlock
attr_reader :block_count, :date_range, :discount_cost
attr_accessor :rooms

def initialize(block_count:, date_range:, discount_cost:)
@block_count = block_count # I interpreted the user story "collection of rooms" to mean I can pass it a
#count and the count determines how many rooms to request for the block.
@date_range = date_range
@discount_cost = discount_cost
@rooms = []

raise ArgumentError.new("Block count must be an integer between 2 and 5 inclusive") if @block_count.between?(2,5) == false

end

end

Choose a reason for hiding this comment

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

I tend to get suspicious when a class only has initialize as a method. Usually, this means that another class is managing the data that belongs to this class.

Comment on lines +56 to +99
def check_block_status(date_range)
available_rooms = available_rooms(date_range)
@hotel_blocks.each do |hotel_block|
if hotel_block.date_range.overlap?(date_range) == true
hotel_block.rooms.each do |block_room|
available_rooms.delete(block_room)
end
end
end
return available_rooms
end

def request_block(block_count, date_range, discount_cost)
available_rooms = check_block_status(date_range)
raise NoAvailableRoomError.new("Not enough available rooms to fulfill block") if available_rooms.count < block_count

hotel_block = Hotel::HotelBlock.new(block_count: block_count, date_range: date_range, discount_cost: discount_cost)

x = 0
until x == block_count do
available_room = available_rooms[x]
available_room.change_cost(discount_cost)
hotel_block.rooms << available_room
x += 1
end
@hotel_blocks << hotel_block
return hotel_block
end

def available_rooms_in_block(hotel_block)
available_rooms = hotel_block.rooms.select{|room| room.reservations.empty? == true || room.reservations.any?{|reservation| reservation.date_range.overlap?(hotel_block.date_range) == false}}
return available_rooms
end

def add_reservation_to_room_in_block(hotel_block)
available_rooms = available_rooms_in_block(hotel_block)
raise NoAvailableRoomError.new("there are no available rooms left in this block")if available_rooms.empty? == true
chosen_room = available_rooms[0]
new_reservation = Hotel::Reservation.new(date_range: hotel_block.date_range, room: chosen_room)
new_reservation.block_reservation = true
@reservations << new_reservation
chosen_room.add_room_reservation(new_reservation)
return new_reservation
end

Choose a reason for hiding this comment

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

At least a couple of these methods probably belong to HotelBlock

Comment on lines +31 to +52
it "returns true if there is overlap between date ranges" do
date_range2 = Hotel::DateRange.new(start_date: Date.today + 2, end_date: Date.today + 4)
date_range3 = Hotel::DateRange.new(start_date: Date.today + 3, end_date: Date.today + 6)
date_range4 = Hotel::DateRange.new(start_date: Date.today + 1, end_date: Date.today + 9)
date_range5 = Hotel::DateRange.new(start_date: Date.today + 1, end_date: Date.today + 6)
expect(@date_range.overlap?(date_range2)).must_equal true
expect(@date_range.overlap?(date_range3)).must_equal true
expect(@date_range.overlap?(date_range4)).must_equal true
expect(@date_range.overlap?(date_range5)).must_equal true
end

it "returns false if the date is not within the range" do
date_range2 = Hotel::DateRange.new(start_date: Date.today + 6, end_date: Date.today + 9)
date_range3 = Hotel::DateRange.new(start_date: Date.today + 7, end_date: Date.today + 13)
date_range4 = Hotel::DateRange.new(start_date: Date.today + 1, end_date: Date.today + 2)
date_range5 = Hotel::DateRange.new(start_date: Date.today + 19, end_date: Date.today + 20)
date_range5 = Hotel::DateRange.new(start_date: Date.today , end_date: Date.today + 1)
expect(@date_range.overlap?(date_range2)).must_equal false
expect(@date_range.overlap?(date_range3)).must_equal false
expect(@date_range.overlap?(date_range4)).must_equal false
expect(@date_range.overlap?(date_range5)).must_equal false
end

Choose a reason for hiding this comment

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

I would give these date ranges more explicit names, so that others can check your work more easily.

Comment on lines +4 to +9
before do
@front_desk = Hotel::FrontDesk.new
@dates = Hotel::DateRange.new(start_date: Date.today + 2, end_date: Date.today + 6)
@block_count = 3
@discount_cost = 0.2
end

Choose a reason for hiding this comment

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

Are you using all of these for each test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants