Skip to content
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

Branches - Brianna K #35

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
68c32d2
Initial files created for classes
brikemp Sep 3, 2019
71e3bc8
Added test files for each class to teset folder
brikemp Sep 3, 2019
1e1d64d
Test helper file updated to include simplecov and tests added for ini…
brikemp Sep 3, 2019
76d75ed
Wave 1 complete
brikemp Sep 4, 2019
808c962
Initial date check method set up
brikemp Sep 6, 2019
4361289
Date check method completetd in reservation class, restructuring proj…
brikemp Sep 9, 2019
17bff67
finished converting date check method to hotel, removed all class var…
brikemp Sep 9, 2019
13fe08a
Wave 2 Reserveation complete, added tests
brikemp Sep 9, 2019
fbc2154
added missed requirement, find reservations by date - method and test…
brikemp Sep 9, 2019
43bd611
Updated reservation_id tracking to incremental number
brikemp Sep 9, 2019
682a058
Hotel block class file added
brikemp Sep 9, 2019
b18b079
Block booking added to hotel class and intiaties new instance of block
brikemp Sep 10, 2019
5fd6105
finished implementing block method, confirming all tests pass
brikemp Sep 11, 2019
c96075b
All tests passing refactoring class structure
brikemp Sep 11, 2019
c8f8183
Added block test file and required file in test helper, refactoring d…
brikemp Sep 11, 2019
dfa94af
Added refactors.txt file
brikemp Sep 11, 2019
f78e349
Added missed requirement to check block availability
brikemp Sep 11, 2019
df1e341
Updated future changes in refactors.txt
brikemp Sep 11, 2019
889597a
Added design activity file
brikemp Sep 29, 2019
a48cec1
Hotel method refactoring
brikemp Oct 2, 2019
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
coverage

*.gem
*.rbc
/.config
Expand Down
53 changes: 53 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
- What classes does each implementation include? Are the lists the same?

Implementations A and B have the same classes: CartEntry, ShoppingCart, and Order.

- Write down a sentence to describe each class.

CartEntry: This object is a specific item, it's price and quantity are stored
ShoppingCart: A list of all items in a cart
Order: A shopping cart of items

- How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper.

The Order class is instantiated with a ShoppingCart class. The ShoppingCart stores an array of entries made up of the CartEntry class.

Order is one-to-one with ShoppingCart
ShoppingCart is one-to-many with CartEntry

- What data does each class store? How (if at all) does this differ between the two implementations?

There is no difference in the data stored, the initialize methods are unchanged between the implementation:
CartEntry stores unit_price and quantity
ShoppingCart stores entries
Order stores cart

- What methods does each class have? How (if at all) does this differ between the two implementations?

CartEntry: has a price method in implementation B and no methods in implementation A
Shopping Cart: has a price method in implementation B and no methods in implementation A
Order: has a total_price method - this is the same for both implementations

- 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?

In implementation A the logic to compute price is retained in Order; however, in implementation B the logic is in ShoppingCart and CartEntry

- Does total_price directly manipulate the instance variables of other classes?

Total_price directly manipulates the instance variables in implementation A, but not B

- If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify?

This would change either the total_price method in implementation A of the price method of CartEntry is implementation B. Implementation B would be easier to modify.

- Which implementation better adheres to the single responsibility principle?

Implementation B

- Bonus question once you've read Metz ch. 3: Which implementation is more loosely coupled?

Implementation B (fewer dependencies)

Describe in design-activity.md what changes you would need to make to improve this design, and how the resulting design would be an improvement.

11 changes: 11 additions & 0 deletions lib/block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'date'

class Block
attr_reader :reservations, :block_id

def initialize(reservations:, block_id:)
@reservations = reservations
@block_id = block_id
end

end
135 changes: 135 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
require_relative 'reservation'
require_relative 'block'

class Hotel
attr_reader :reservations, :rooms, :blocks

def initialize(reservations: nil, blocks:nil)
@reservations = reservations || []
@blocks = blocks || []
@rooms = [*1..20]
end


def make_reservation(start_date:, end_date:, hold_block:false, block_id:nil)

Choose a reason for hiding this comment

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

There's enough going on here that it'd be cleaner to break it up into smaller methods that this method calls.

Choose a reason for hiding this comment

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

Oh! I see you called that out in your refactors list! Awesome!

if hold_block != false && hold_block.to_s.match(/[1-5]/) == nil
raise ArgumentError.new("If you want hold a block of rooms, enter the number of rooms (maximum of 5) to hold.")
elsif hold_block == false && block_id == nil
id = @reservations.length + 1
room = list_available_rooms(start_date, end_date).sample
reservation = Reservation.new(start_date:start_date, end_date:end_date, room:room, reservation_id:id)
reservations.push(reservation)
return reservation
elsif hold_block.to_s.match(/[1-5]/) != nil
if block_id != nil
raise ArgumentError.new("Please make hotel block before booking a room ")
end
reservation_block = {}
available_count = list_available_rooms(start_date, end_date).length
if available_count < hold_block
raise ArgumentError.new("Not enough rooms available for this block")
end
hold_block.times do
id = @reservations.length + 1
room = list_available_rooms(start_date, end_date).sample
reservation = Reservation.new(start_date:start_date, end_date:end_date, room:room, reservation_id:id, block:true)
reservations.push(reservation)
reservation_block[reservation] = "Not booked"
end
id = @blocks.length + 1
block = Block.new(reservations:reservation_block, block_id:id)
blocks.push(block)
return block
elsif block_id.to_s.match(/[1-5]/) != nil
block = blocks.find{|block| block.block_id == block_id }
if block == nil
raise ArgumentError.new("This block does not exist yet, please reserve the block first")
end
reservations = block.reservations
reservation = reservations.find{|reservation, status| status == "Not booked"}
if reservation == nil
raise ArgumentError.new("This block has been fully booked")
end
reservations[reservation[0]] = "Booked"
return reservations[reservation[0]]
end
end

def find_reservations_by_date(start_date, end_date)
if start_date.class == String
start_date = Date.strptime(start_date, "%m/%d/%Y")
end
if end_date.class == String
end_date = Date.strptime(end_date, "%m/%d/%Y")
end
found_reservations = []
if @reservations != nil
@reservations.each do |reservation|
date = start_date.dup
until date == end_date do
if (start_date >= reservation.start_date && start_date < reservation.end_date) || (end_date > reservation.start_date && end_date <= reservation.end_date)
found_reservations.push(reservation)
break
end
date += 1
end
end
end
return found_reservations
end

def check_block_availability(block_id:)
if block_id.to_s.match(/[1-5]/) != nil
block = @blocks.find{|block| block.block_id == block_id }
if block == nil
raise ArgumentError.new("This block does not exist yet, please reserve the block first")
end
reservations = block.reservations
available_in_block = reservations.select{|reservation, status| status == "Not booked"}
puts available_in_block
puts available_in_block.class
if available_in_block.length == 0
raise ArgumentError.new("This block has been fully booked, there are 0 rooms available")
end
available_reservations = []
available_in_block.each do |reservation, status|
available_reservations.push(reservation)
end
available_rooms = available_reservations.map do |reservation|
reservation.room
end
return available_rooms
end
end

def list_available_rooms(start_date, end_date)
if start_date.class == String
start_date = Date.strptime(start_date, "%m/%d/%Y")
end
if end_date.class == String
end_date = Date.strptime(end_date, "%m/%d/%Y")
end
occupied_rooms = []
if @reservations != nil
@reservations.each do |reservation|
date = start_date.dup
until date == end_date do
if (start_date >= reservation.start_date && start_date < reservation.end_date) || (end_date > reservation.start_date && end_date <= reservation.end_date)
occupied_rooms.push(reservation.room)
break
end
date += 1
end
end
end
rooms = @rooms.dup
occupied_rooms.each do |room|
rooms.delete(room)
end
if rooms.length == 0
raise ArgumentError.new("Sorry! We are currently all booked for those days, pleae try again.")
end
return rooms
end

end
21 changes: 21 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'date'

class Reservation
attr_reader :room, :start_date, :end_date, :block, :reservation_id, :cost
ROOM_COST = 200
DISCOUNT = 0.20

def initialize(start_date:, end_date:, room:, block:false, reservation_id:)
@start_date = Date.strptime(start_date, "%m/%d/%Y")
@end_date = Date.strptime(end_date, "%m/%d/%Y")
@room = room
@block = block
@reservation_id = reservation_id
@cost = @block == false ? ROOM_COST * (@end_date - @start_date).to_i : ROOM_COST * (1-DISCOUNT) * (@end_date - @start_date).to_i

if end_date <= start_date || start_date == nil || end_date == nil
raise ArgumentError.new("Please enter a valid date range")
end
end

end
3 changes: 3 additions & 0 deletions refactors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
List of changes that I would like to make:
- I would like to break apart my make_reservation class in to separate methods that are called my an “overall” make_reservation class. Currently, that class contains a lot of ifs/elses that make it confusing to follow and update when needed
- I would like to combine my block and reservation classes into one because there are limited differences between the two and this sticks to single the single responsibility of making reservations for rooms
24 changes: 24 additions & 0 deletions test/block_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require_relative 'test_helper'

describe "Block class" do

describe "Block instantiation" do
before do
@hotel = Hotel.new
@block = @hotel.make_reservation(start_date:"5/05/2019", end_date:"5/09/2019", hold_block:4)
end

it "is an instance of Reservation" do
expect(@block).must_be_kind_of Block
end

it "has correct attributes" do
[:reservations, :block_id].each do |prop|
expect(@block).must_respond_to prop
end
expect(@block.reservations).must_be_kind_of Hash
expect(@block.block_id).must_be_kind_of Integer
end

end
end
Loading