forked from AdaGold/hotel
-
Notifications
You must be signed in to change notification settings - Fork 45
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
Amy Lee -- Carets #31
Open
ayjlee
wants to merge
27
commits into
Ada-C8:master
Choose a base branch
from
ayjlee: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
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
681579e
Setup of project structure for Hotel project
ayjlee 86e2d67
Created and tested initialize methods for Hotel::Room class
ayjlee 09030e3
First draft of reserve room method and tests written, passing; placeh…
ayjlee 75897f5
added Room.find_by_id method to find a room by it's room number
ayjlee b2cd5f1
tested that I could have multiple reservations on the same room
ayjlee 9b1783a
get a list of all reservations on a certain date; wrote basic functio…
ayjlee 531f35e
Added test for checking that each room has a nightly rate of 00
ayjlee 3638f06
Wrote cost method that returns the total cost of a reservation, basic…
ayjlee 100fffe
BENCHMARK: Wave 1 test requirements with basic test passing. More tho…
ayjlee f60aab0
Added a Room helper method, available_all_days?, which will be used t…
ayjlee 107fd3a
can view a list of available rooms for a given date range and reserve…
ayjlee 8d8ca89
Refactored reservations and making reservations to have guest_id as a…
ayjlee b884efd
added basic tests for making a reservation
ayjlee 420fb74
Created Block class, which currently inherits from Reservation class.…
ayjlee 5de0cd9
Created make_block method in BookingProgram and block_room method in …
ayjlee 729b56f
made the reservation id a required argument to initialize a Reservati…
ayjlee b56ae49
Added Block to required files
ayjlee 57c76a9
Added new BlockReservation subclass of Reservation. Block is now an i…
ayjlee f4a8494
Added code and logic for handling block reservations, untested.
ayjlee 3b43cc3
Major refactor- Reservations, BlockReservation, and Blocks all hold R…
ayjlee 7aa52b8
Renamed the Module to be the HotelBooking, and the class to Hotel to …
ayjlee 35e687f
All waves passing, basic tests passing. Need to fix logic for Room's …
ayjlee 6e20e8c
Refactored Room - Rooms only keep track of the IDS for reservations a…
ayjlee ed4d23c
Refactored all files so that all error handling happened in the Hotel…
ayjlee af12b8a
Finished Evaluating Responsibility Activity
ayjlee a4779d8
Refactored to make sure responsibility/logic to reserve a room in a b…
ayjlee aa4b0dd
Added comments about Hotel Design changes made to improve Single Resp…
ayjlee 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
This file contains 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,9 @@ | ||
require 'rake/testtask' | ||
|
||
Rake::TestTask.new do |t| | ||
t.libs = ["lib"] | ||
t.warning = false | ||
t.test_files = FileList['specs/*_spec.rb'] | ||
end | ||
|
||
task default: :test |
This file contains 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,74 @@ | ||
__Hotel Design Changes Made__ | ||
I refactored my Hotel program so that all logic and responsibility for reserving a room in a block was in the Block Class instead of the Room class. This is an improvement because Blocks are a special class that have specific rooms, from which a guest can select to create a Block reservation. Room instances do not need to know if they are in a Block, but a Block must know what Rooms it includes, and which are available for booking. Rooms in a Block have special conditions under which they can be reserved, so it makes more sense to have the responsibility and logic to reserve rooms in a block reside in the more specific Block class rather than the general Room class. | ||
|
||
|
||
|
||
1. What classes does each implementation include? Are the lists the same? | ||
|
||
Each of the implementations has three classes: CartEntry, ShoppingCart, and Order. The lists are the same. | ||
|
||
|
||
2. Write down a sentence to describe each class. | ||
|
||
CartEntry seems to be any item/purchase you want to put in your cart, and must have a unit price and quantity. A ShoppingCart holds zero or more CartEntries in an array. Orders have a Shopping Cart, and calculate the total price (including Sales Tax) of all of the Cart Entries in the Cart. | ||
|
||
3. How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper. | ||
Orders have a ShoppingCart which can hold zero or more CartEntries. | ||
|
||
4. What data does each class store? How (if at all) does this differ between the two implementations? | ||
|
||
__A__ | ||
Cart Entry: @unit_price & @quantity instance variables | ||
ShoppingCart: @entries array | ||
Order: SALES_TAX constant, @cart variable that is an instance of ShoppingCart. | ||
|
||
__B__ | ||
Cart Entry: @unit_price and @quantity instance variables | ||
ShoppingCart: @entries array | ||
Order: Constant SALES_TAX, @cart variable that is an instance of ShoppingCart | ||
|
||
|
||
5. What methods does each class have? How (if at all) does this differ between the two implementations? | ||
|
||
__A__ | ||
CartEntry: Initialize method, accessors for @unit_price and @quantity | ||
ShoppingCart: Initialize method, accessor for @entries | ||
Order: Initialize method, total_price method that calculates the sum of the prices of each entry in the @cart, and returns the total_price including SALEX_TAX. | ||
|
||
__B__ | ||
CartEntry: Initialize method, price method that returns the price of each CartEntry | ||
ShoppingCart: Initialize method, price method that returns the sum of the prices of each entry in the @cart. | ||
Order: Initialize method, total_price method that returns the total price, including sales tax, of all of the items in the cart. | ||
|
||
|
||
6. Consider the Order#total_price method. In each implementation: | ||
|
||
Is logic to compute the price delegated to "lower level" classes like ShoppingCart and CartEntry, or is it retained in Order? | ||
|
||
__A__ | ||
The logic to compute the price is retained in Order. | ||
|
||
__B__ | ||
The logic to compute the price is delegated to "lower level" classes like ShoppingCart and CartEntry. | ||
|
||
Does total_price directly manipulate the instance variables of other classes? | ||
|
||
__A__ | ||
If I'm reading the question correctly, total_price directly manipulates instance variables of other classes in implementation A. It must access the entries array of the @cart instance, then iterate over each CartEntry instance to access the unit_price and quantity of each to calculate the price, sum up the prices of each CartEntry instance, then add the SALES_TAX to get the total_price. | ||
|
||
__B__ | ||
No; Implementation B calls the .price method on the @cart, then adds the SALES_TAX to calculate the total_price. | ||
|
||
7. If we decide items are cheaper if bought in bulk, how would this change the code? | ||
|
||
We would have to add logic for the discounted bulk price (e.g. a lower unit_price or some kind of discount that is applied) if someone places a bulk order. We would also have to determine how a bulk order is placed, whether it's a subclass, or if we just add conditionals to our existing | ||
|
||
8. Which implementation is easier to modify? | ||
|
||
Implementation B- classes better follow single responsibility principle and logic is delegated to "low level" classes, and we can better target only the relevant classes and methods for modification without fear of messing up some other code. | ||
|
||
9. Which implementation better adheres to the single responsibility principle? | ||
|
||
Implementation B | ||
|
||
10. Bonus question once you've read Metz ch. 3: Which implementation is more loosely coupled? |
This file contains 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 HotelBooking | ||
class Block | ||
attr_accessor :id, :guest, :check_in, :check_out, :room_ids, :available_rooms | ||
attr_reader :discounted_rate | ||
|
||
def initialize(check_in,check_out,room_ids,discounted_rate,block_id) | ||
@check_in = check_in #ruby Date object | ||
@check_out = check_out #ruby Date object | ||
@room_ids = room_ids | ||
@available_rooms = room_ids.dup | ||
@discounted_rate = discounted_rate | ||
@id = block_id | ||
end | ||
|
||
def reserve_block_room(room_id) | ||
raise ArgumentError.new("This Block room is not available for this block reservation") if !(@available_rooms.include?(room_id)) | ||
|
||
@available_rooms.delete(room_id) | ||
end | ||
|
||
|
||
end | ||
|
||
end |
This file contains 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,19 @@ | ||
require_relative 'Reservation' | ||
|
||
module HotelBooking | ||
class BlockReservation < HotelBooking::Reservation | ||
attr_accessor :id, :guest, :check_in, :check_out, :room, :block_id | ||
attr_reader :all_reservations, :type | ||
|
||
def initialize(check_in,check_out,room_id, b_res_id, block_discount, guest = nil) | ||
super(check_in,check_out,room_id, b_res_id,block_discount, guest = nil) | ||
@rate = block_discount | ||
@block_id = nil | ||
@type= :block | ||
end #end initialize | ||
|
||
def cost | ||
num_nights_charged * @rate | ||
end | ||
end | ||
end |
This file contains 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,150 @@ | ||
|
||
require 'date' | ||
require_relative 'Reservation' | ||
require_relative 'Room' | ||
require_relative 'Block' | ||
module HotelBooking | ||
|
||
class Hotel | ||
|
||
#The Hotel class holds the data of all rooms, all reservations, and all blocks in the Hotel. It checks for valid dates before creating new reservations, block reservations, and blocks. | ||
attr_reader :all_rooms, :all_reservations, :all_blocks | ||
NUM_STANDARD_ROOMS = 20 | ||
|
||
def initialize | ||
@all_rooms = HotelBooking::Hotel.setup_rooms | ||
@all_reservations = [] | ||
@all_blocks = [] | ||
end | ||
|
||
def available_rooms(check_in,check_out, block_id = nil) | ||
check_valid_dates(check_in,check_out) | ||
@all_rooms.select {|room| room.available_all_days?(check_in, check_out)} | ||
end | ||
|
||
def make_block(check_in,check_out,room_ids,discounted_rate) | ||
check_in_date = Date.parse(check_in) | ||
check_out_date = Date.parse(check_out) | ||
|
||
|
||
#checks valid dates | ||
check_valid_dates(check_in_date,check_out_date) | ||
|
||
#makes sure all rooms intended for the block are available for the date range provided | ||
check_valid_block(check_in_date,check_out_date,room_ids) | ||
|
||
block_id = "B" + "#{@all_blocks.count + 1}" | ||
|
||
block = HotelBooking::Block.new(check_in_date,check_out_date,room_ids,discounted_rate,block_id) | ||
|
||
room_ids.each do |room_id| | ||
room= find_room_by_id(room_id) | ||
room.block_room(check_in_date,check_out_date,block_id) | ||
end | ||
|
||
@all_blocks << block | ||
|
||
end | ||
|
||
def make_reservation(check_in,check_out,room_id, guest_id=nil) | ||
|
||
reservation_id = (@all_reservations.count + 1) | ||
room= find_room_by_id(room_id) | ||
check_in_date = Date.parse(check_in) | ||
check_out_date = Date.parse(check_out) | ||
|
||
check_valid_dates(check_in_date,check_out_date) | ||
|
||
if available_rooms(check_in_date,check_out_date).include?(room) | ||
|
||
reservation = HotelBooking::Reservation.new(check_in_date,check_out_date,room_id, reservation_id) | ||
|
||
room.reserve_room(check_in_date,check_out_date,reservation_id, guest_id) | ||
|
||
@all_reservations << reservation | ||
else | ||
raise ArgumentError.new("This room is already reserved for these dates") | ||
end | ||
|
||
end | ||
|
||
def make_block_reservation(block_id,room_id,guest_id = nil) | ||
block= find_block_by_id(block_id) | ||
reservation_id = "B" + (@all_reservations.count + 1).to_s | ||
|
||
raise ArgumentError.new("This room is not in the block") if !(block.room_ids.include?(room_id)) | ||
raise ArgumentError.new("This Block room has already been reserved") if !(block.available_rooms.include?(room_id)) | ||
|
||
block_reservation = HotelBooking::BlockReservation.new(block.check_in,block.check_out,room_id, reservation_id, block.discounted_rate) | ||
block_reservation.block_id = block_id | ||
|
||
block.reserve_block_room(room_id) | ||
|
||
@all_reservations << block_reservation | ||
|
||
end | ||
|
||
def find_room_by_id(room_id) | ||
@all_rooms.each {|room| return room if room.id == room_id} | ||
|
||
raise ArgumentError.new "Sorry, we don't have a room matching that ID number." | ||
end | ||
|
||
def find_res_by_date(date_str) | ||
date_object= Date.parse(date_str) | ||
@all_reservations.select {|reservation| ((reservation.check_in)..(reservation.check_out)).include?(date_object)} | ||
end | ||
|
||
def find_block_by_id(block_id) | ||
|
||
@all_blocks.each {|block| return block if block.id == block_id} | ||
raise ArgumentError.new "Sorry, we don't have a block matching that ID number." | ||
end | ||
|
||
def find_available_rooms_by_block(block_id) | ||
block= find_block_by_id(block_id) | ||
block.available_rooms | ||
end | ||
|
||
def check_valid_block(check_in,check_out,room_ids) | ||
raise ArgumentError.new("Number of rooms in a block must be 5 or under") if room_ids.count > 5 | ||
|
||
available_rooms_ids = available_rooms(check_in,check_out).map {|room| room.id} | ||
|
||
room_ids.each do |room_id| | ||
raise ArgumentError.new("This room is already reserved for the dates provided") if !(available_rooms_ids.include?(room_id)) | ||
end | ||
|
||
return true | ||
|
||
end | ||
|
||
def check_valid_dates(check_in, check_out) | ||
if check_in < Date.today || check_out < Date.today | ||
raise ArgumentError.new("Can't make reservations for days earlier than today") | ||
end | ||
|
||
if check_in.class != Date ||check_out.class != Date | ||
raise ArgumentError.new("Please provide a valid date") | ||
end | ||
|
||
if check_out < check_in | ||
raise ArgumentError.new("Invalid Date Range: Check out date is earlier than check-in date.") | ||
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. You might want to pick a different Error besides |
||
end | ||
|
||
end | ||
|
||
def self.setup_rooms | ||
standard_rooms = [] | ||
|
||
(1..NUM_STANDARD_ROOMS).each do |num| | ||
room = HotelBooking::Room.new(num) | ||
standard_rooms << room | ||
end | ||
|
||
return standard_rooms | ||
end | ||
|
||
end | ||
|
||
end |
This file contains 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,7 @@ | ||
### OPTIONAL CLASS | ||
|
||
module Hotel | ||
class Guest | ||
|
||
end | ||
end |
This file contains 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,28 @@ | ||
require 'date' | ||
module HotelBooking | ||
|
||
class Reservation | ||
attr_accessor :id, :guest, :check_in, :check_out, :room_id | ||
attr_reader :all_reservations, :type, :rate | ||
|
||
def initialize(check_in,check_out,room_id, res_id, rate = 200, guest = nil) | ||
@id = res_id | ||
@check_in = check_in #ruby Date object | ||
@check_out = check_out #ruby Date object | ||
@room_id= room_id | ||
@guest = guest | ||
@rate = rate | ||
@type= :standard | ||
end #end initialize | ||
|
||
def cost | ||
num_nights_charged * @rate | ||
end | ||
|
||
def num_nights_charged | ||
(check_out.mjd - check_in.mjd) | ||
end | ||
|
||
end | ||
|
||
end |
This file contains 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,49 @@ | ||
require 'date' | ||
|
||
module HotelBooking | ||
|
||
class Room | ||
attr_reader :id, :nightly_rate, :type, :reserv_ids, :all_dates, :block_ids, :blocks_available | ||
|
||
def initialize(id_number, nightly_rate = 200) | ||
@id = id_number | ||
@nightly_rate = nightly_rate | ||
@type = :standard | ||
@reserv_ids = [] | ||
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. What are |
||
@block_ids = [] | ||
@all_dates = [] | ||
@blocks_available = [] | ||
end | ||
|
||
def reserve_room(check_in,check_out,reservation_id, guest_id=nil) | ||
|
||
(check_in...check_out).each do |date| | ||
@all_dates << date | ||
end | ||
|
||
@reserv_ids << reservation_id | ||
end | ||
|
||
|
||
def block_room(check_in,check_out,block_id) | ||
if available_all_days?(check_in, check_out) | ||
@blocks_available << block_id | ||
|
||
(check_in...check_out).each do |date| | ||
@all_dates << date | ||
end | ||
end | ||
|
||
end | ||
|
||
def available_all_days?(check_in, check_out) | ||
(check_in..check_out).each do |date| | ||
return false if @all_dates.include?(date) | ||
end | ||
|
||
return true | ||
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.
I love all the small helper methods you made :D I wish that there were a better place to put this specific helper method about checking if it's a valid date that wasn't in
Hotel
, but I can't think of a better place at the moment.