Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
37185c8
Add coverage directory to .gitignore file
larachan15 Sep 4, 2018
d647a3c
First commit w/ guard
larachan15 Sep 4, 2018
380801e
added room.rb with one passing test
larachan15 Sep 4, 2018
332855b
room.rb with all tests written so far passing
larachan15 Sep 4, 2018
a4dc534
simplified room class to take a room_number only
larachan15 Sep 5, 2018
2f79288
added reservation class with check_in, check_out and room. Has workin…
larachan15 Sep 5, 2018
d7fb0cd
created booking_range and rate definitions.
larachan15 Sep 5, 2018
ad67f98
updated reservation.rb and spec file with passing tests for booking_r…
larachan15 Sep 5, 2018
a969eda
Add DS_Store to gitignore
larachan15 Sep 7, 2018
cbc8582
can access the list of all of the rooms in the hotel with passing tes…
larachan15 Sep 7, 2018
b5ff6f6
can reserve a room for a given date range with passing test
larachan15 Sep 7, 2018
a2b9e42
accesses the list of reservations for a specific date with passing test
larachan15 Sep 7, 2018
030ce24
Wave 1 finished with get the total cost for a given reservation and t…
larachan15 Sep 7, 2018
d691eec
added test for nightsstayed definition in reservation.rb
larachan15 Sep 8, 2018
0bf146e
Fixed typo in list of reservations definition. Added some code for wa…
larachan15 Sep 8, 2018
a7cfbe5
created with is_room_available, one failing test and rooms_not_reserv…
larachan15 Sep 10, 2018
f21593b
wave 2 complete with passing tests
larachan15 Sep 10, 2018
8b3b4e8
added a couple of tests.
larachan15 Sep 10, 2018
d5404ec
added a block class and spec sheet with passing tests.
larachan15 Sep 19, 2018
b6848da
added BlockReservation to reservation.rb with passing test.
larachan15 Sep 19, 2018
eea072e
added block section to rooms not reserved definition. Fixed test.
larachan15 Sep 19, 2018
97d3845
added method to create a block with passing test.
larachan15 Sep 20, 2018
4fd6a9b
Added design-activity.md and answered prompts.
larachan15 Sep 30, 2018
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ build-iPhoneSimulator/

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
coverage

.DS_Store
2 changes: 1 addition & 1 deletion Guardfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
guard :minitest, bundler: false, rubygems: false do
guard :minitest, bundler: false, autorun: false, rubygems: false do
# with Minitest::Spec
watch(%r{^spec/(.*)_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
Expand Down
20 changes: 20 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
1. Implementation A has three classes: CartEntry, ShoppingCart, and Order.
Implementation B has the same three classes as well.

2. For implementation A, CartEntry initializes the unit price and quantity for each item. ShoppingCart stores the entries of each item in an array. Order creates a new instance of a shopping cart and then calculates the total price of all the items in a cart with the sales tax.

For implementation B, CartEntry initializes the unit price and quantity for each item. ShoppingCart stores the entry of each item in an array and also calculates the price of each item. Order creates a new instance of a shopping cart and calculates the total price of each cart with all the items and the sales tax.

3. For implementation A, the CartEntry establishes the quantity and price of each item. ShoppingCart stores each entry. These two classes are needed for the Order class which creates a new instance of a shopping cart and then goes through each entry in the cart to calculate the sum of all the items and their prices. It returns the total price.

For implementation B, CartEntry is responsible for establishing the unit price and and quantity of each item. Then it calculates the price of each type of item depending on the quantity ordered. ShoppingCart stores the entry of each item in a shopping cart. It also calculates the price of each entry by calling on the price method in CartEntry and then adding up the sums. Order creates a new instance of shopping cart. It calculates the subtotal by calling on the price method from ShoppingCart. Then it calculates the overall cost by multiplying the subtotal to the sales tax and adding that to the original subtotal amount.

4. CartEntry stores each item's price and quantity. ShoppingCart stores all the entries. Order retrieves the information from CartEntry and ShoppingCart to return the total price of each cart. Both store the same info. However, I think implementation A does a better job of creating single responsibility for each class without relying too heavily on the Order class to calculate the total price. However, the subtotal variable in implementation B is much clearer on what is being calculated vs, implementation A where the variable sum is used. I wasn't sure why sum was being returned at first.

5. Initially, it seemed logical to compute the the price in "lower level" classes like ShoppingCart and CartEntry. However that creates a tie between all the classes and if one is changed, then the others must be modified as well. In the first implementation, ShoppingCart doesn't rely on price being calculated in CartEntry and then Order doesn't rely on ShoppingCart for price to be calculated in order for the total price to be calculated. Total price does not directly manipulate the instance variables of the other classes.

6. If items were bought in bulk, I think this would be done in a new method called bulk. I think because method A is more loosely coupled than B, it would be easier to implement in A.

7. Implementation A.

8. Implementation A. Although I think implementation B is a little easier to read because the variable subtotal in the method total_price was clearer to me.
23 changes: 23 additions & 0 deletions lib/block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'date'
require 'securerandom'

class Block
attr_reader :check_in_date, :check_out_date, :id, :block_of_rooms
attr_accessor :rooms

BLOCKRATE = 100

def initialize(check_in_date, check_out_date, block_of_rooms)
@id = SecureRandom.uuid
Copy link

Choose a reason for hiding this comment

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

I think your use of the SecureRandom gem here to generate an ID is rad!

@check_in_date = check_in_date
@check_out_date = check_out_date
@block_of_rooms = block_of_rooms
@rooms = []
end

def valid_block_of_rooms
if block_of_rooms > 5
raise ArgumentError, 'Blocks can have up to 5 rooms.'
end
end
end
5 changes: 5 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ROOM_LIST = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

def hotel
return "hotel"
end
Copy link

Choose a reason for hiding this comment

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

Whoops! You should probably delete this file and all references to it.

32 changes: 32 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Keeps track of 1 reservation
require_relative 'room'
require 'date'

# module Hotel
class Reservation
attr_reader :check_in_date, :check_out_date, :room_number, :nights_stayed
Copy link

Choose a reason for hiding this comment

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

attr_readers are reserved for names of instance variables. :nights_stayed isn't the name of an instance var, it's the name of a method -- it doesn't need to be in this list!


def initialize(check_in_date, check_out_date, room_number)
@check_in_date = check_in_date
@check_out_date = check_out_date
@room_number = room_number
raise StandardError, 'The end date cannot be before the start date.' if check_out_date <= check_in_date
Copy link

Choose a reason for hiding this comment

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

I love that the logic to check if reservation dates are valid are in the Reservation itself. Nice decision :)

end

def nights_stayed
date_range = check_out_date - check_in_date
return date_range.to_i
end
end

class BlockReservation < Reservation
def initialize(check_in_date, check_out_date, room_number)
super
end

def block_rate
date_range = @check_out_date - @check_in_date
date_range.to_i
end
end
# end
108 changes: 108 additions & 0 deletions lib/reservation_tracker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
require 'pry'
require 'date'
require_relative 'room'
require_relative 'block'
require_relative 'reservation'
# Keeps track of the list of reservations
# module Hotel
class ReservationTracker
attr_reader :rooms, :check_in_date, :check_out_date, :reservations, :unreserved_rooms, :blocks

def initialize
@rooms = create_rooms
@reservations = []
@unreserved_rooms = []
Copy link

Choose a reason for hiding this comment

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

Does this instance variable @unreserved_rooms ever get used? If it doesn't get used, can we get rid of it?

@blocks = []
# @existing_reservations = []


end

# creates and accesses the list of all of the rooms in the hotel
def create_rooms
rooms = []
(1..20).each do |room|
room_number = Room.new(room)
rooms << room_number
end
return rooms
end

# creates reservation and adds the reservation to the list of reservations
def create_reservation(check_in_date, check_out_date, room_number)
reservation = Reservation.new(check_in_date, check_out_date, room_number)
@reservations << reservation
# @reserved_rooms << room
# return reservation
end

def create_a_block(check_in_date, check_out_date, block_of_rooms)
# rooms_available is an arrary from rooms_not_reserved
rooms_available = rooms_not_reserved(check_in_date,
check_out_date)
block_reservation = Block.new(check_in_date,
check_out_date,
block_of_rooms)
block_reservation.rooms = rooms_available.pop(block_of_rooms)
@blocks << block_reservation

return block_reservation
end

# don't think i need this anymore
# def is_a_room_available?(date)
# @reservations.each do |reservation |
# return false if reservation.check_in_date >= date && reservation.check_out_date > date
# end
# # binding.pry
# return true
# end

# accesses the list of reservations for a specific date
def list_of_reservations(date)
return @reservations.find_all { |reservation| reservation.nights_stayed == date }
Copy link

Choose a reason for hiding this comment

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

Does this code actually work? It looks fishy to me, and I can't tell because there aren't any tests! :(

end

# calculates the total cost for a given reservation
def cost_for_given_reservation(reservation)
total_cost = reservation.nights_stayed * Room::ROOM_RATE
return total_cost
end

# checks to see if a room is available and reserves the first available room for a given date range. Uses the rooms_not reserved method.
def reserve_room(check_in_date, check_out_date)
# set the rooms_not_reserved method and arguments to a local variable.
unreserved_rooms = rooms_not_reserved(check_in_date, check_out_date)
Copy link

Choose a reason for hiding this comment

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

I love this line! Very clear what's going on here.

if unreserved_rooms.length == 0
Copy link

Choose a reason for hiding this comment

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

The indentation here is off ;)

raise ArgumentError, 'No Available Rooms for Given Dates'
Copy link

Choose a reason for hiding this comment

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

Instead of raising an ArgumentError, it might make more sense to make your own custom error or just raise StandardError!

else
# uses the create reservation method if there are available rooms
create_reservation(check_in_date, check_out_date, unreserved_rooms[0])
# binding.pry
end
end

# accesses a list of rooms that are not reserved for a given date range
def rooms_not_reserved(check_in_date, check_out_date)
# if the reservations array is empty, this returns an array of available room numbers. If there are no reservations, all rooms can be reserved.
return @rooms.map { |room| room.room_number } if @reservations.empty?
unreserved_rooms = @rooms.map { |room| room.room_number }
Copy link

Choose a reason for hiding this comment

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

Love how dense and juicy and exciting the above two lines are!

# if @reservation.empty? is not empty
@reservations.each { |reservation|
if (reservation.check_in_date >= check_in_date && reservation.check_in_date <= check_out_date) || (reservation.check_out_date >= check_in_date && reservation.check_out_date <= check_out_date)
unreserved_rooms.delete(reservation.room_number)
Copy link

Choose a reason for hiding this comment

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

This is a very funny assumption you're putting here:

For the call .delete to work, this assumes that the array unreserved_rooms is an array full room numbers (originally stemming from @rooms) that are unique. If they aren't unique, then this call to delete might not do what you expect... so if the requirement changes that the hotel does not have unique room numbers, this may introduce bugs here.

end
}

@blocks.each { |block|
if (block.check_in_date >= check_in_date && block.check_in_date <= check_out_date) || (block.check_out_date >= check_in_date && block.check_out_date <= check_out_date)
unreserved_rooms - block.rooms
Copy link

Choose a reason for hiding this comment

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

This is cool code here! I like it. However... the - isn't destructive. It just does the subtraction, and the result isn't stored anywhere. Observe in irb:

a = [1,2,3]
b = [1,2]
a - b
# => returns [3], as expected
# a is still [1,2,3]
# b is still [1,2]

So the subtraction doesn't do anything!

end
}
# unreserved_rooms returns an empty array if nothing is availible in the given date range or it will return an array of available room numbers in date range given.
# for use in the reserve_room method
return unreserved_rooms
end

end
# end
11 changes: 11 additions & 0 deletions lib/room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Keeps track of 1 room_
class Room
attr_reader :room_number

ROOM_RATE = 200

def initialize(room_number)
@room_number = room_number
end

end
32 changes: 32 additions & 0 deletions spec/block_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'simplecov'
SimpleCov.start
require_relative 'spec_helper'

describe 'Block Class' do
it 'creates a new instance of a block' do
check_in_date = Date.new(2018, 9, 5)
check_out_date = Date.new(2018, 9, 8)
new_block = Block.new(check_in_date, check_out_date, 5)
expect(new_block).must_be_instance_of Block
end

it 'charges a rate of 100 for the BLOCKRATE' do
Block::BLOCKRATE.must_equal 100
end

it 'block of rooms must equal 5' do
check_in_date = Date.new(2018, 9, 5)
check_out_date = Date.new(2018, 9, 8)
new_block = Block.new(check_in_date, check_out_date, 5)
expect(new_block.block_of_rooms).must_equal 5
end
end

describe 'validate block of rooms' do
it 'raises an Argument Error, if there are more than 5 rooms in a block' do
check_in_date = Date.new(2018, 9, 5)
check_out_date = Date.new(2018, 9, 8)
new_block = Block.new(check_in_date, check_out_date, 6)
expect { new_block.valid_block_of_rooms }.must_raise ArgumentError
end
end
8 changes: 8 additions & 0 deletions spec/hotel_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require_relative 'spec_helper'

describe 'hotel' do
it 'prints hotel' do
result = hotel()
expect(result).must_equal 'hotel'
end
end
54 changes: 54 additions & 0 deletions spec/reservation_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require 'simplecov'
SimpleCov.start
require 'pry'
require 'time'

require_relative 'spec_helper'

describe 'Reservation' do
describe 'initialize' do
check_in_date = Date.new(2018, 9, 5)
check_out_date = Date.new(2018, 9, 8)
room_number = Room.new(15)
reservation = Reservation.new(check_in_date, check_out_date, room_number)

it 'takes a check in date, check out date, and room number' do

expect(reservation).must_respond_to :check_in_date
expect(reservation.check_in_date).must_equal check_in_date

expect(reservation).must_respond_to :check_out_date
expect(reservation.check_out_date).must_equal check_out_date

expect(reservation).must_respond_to :room_number
expect(reservation.room_number).must_equal room_number
end

it 'raises an ArgumentError for an invalid date range' do
expect{ (Reservation.new(check_out_date, check_in_date)) }.must_raise StandardError
end
end

describe 'nights stayed method' do
check_in_date = Date.new(2018, 9, 6)
check_out_date = Date.new(2018, 9, 10)
room_number = 15
reservation = Reservation.new(check_in_date, check_out_date, room_number)

it 'calculates the number of nights stayed correctly' do

expect(reservation.nights_stayed).must_equal 4
end
end
end

describe 'BlockReservation' do
it 'instantiates a block reservation' do
check_in_date = Date.new(2018, 9, 6)
check_out_date = Date.new(2018, 9, 10)
room_number = 15
block_reservation = BlockReservation.new(check_in_date, check_out_date, room_number)
expect(block_reservation).must_be_instance_of BlockReservation
end

end
Loading