Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
9 changes: 9 additions & 0 deletions Rakefile
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 = true
t.test_files = FileList['specs/*_spec.rb']
end

task default: :test
41 changes: 41 additions & 0 deletions design_activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
What classes does each implementation include? Are the lists the same?
Each implementation has the same classes CartEntry, ShoppingCart, and Order.

Write down a sentence to describe each class.
CartEntry: the CartEntry is responsible for keeping track of the unit price and quantity of each cart item.
ShoppingCart:The shopping car is responsible for storing all the entries in an array.
Order: The order is responsible for storing the sales tax, creating a new shopping cart, and calculating the total price of each cart.

How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper.
Each class relies on another to either fill in its data or to use in a method to calculate data.

What data does each class store? How (if at all) does this differ between the two implementations?
ShoppingCart is the only class that stores data it stores all the entries. this is the same among implementations

What methods does each class have? How (if at all) does this differ between the two
implementations?
In implementation A Order is the only class that contains a method outside of initialize and it has a total_price method.

In implementation B all of the classes have a method. CartEntry and ShoppingCart have a price method, which differ from each other and order class has a total_price method.

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?
It is delegated to lower level classes

Does total_price directly manipulate the instance variables of other classes?
yes.

If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify?
The CartEntry class would change to include constants with bulk pricing. this could possibly be done with a method and if bulk pricing the equation of total price would differ. I think implementation A would be easier to modify because it refers to unit_price and quantity only once outside of the CartEntry class.

Which implementation better adheres to the single responsibility principle?
Implementation A

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


Identify one place in your Hotel project where a class takes on multiple roles, or directly modifies the attributes of another class.
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.
The hotel class takes on multiple roles, it does not modify attributes from the reservation class but, along with storing the reservations and listing the reservations and rooms available it also determines whether a room is available which could be something that a room class could do. To improve this design I would add a room class which would take on storing the rooms and managing whether they were available or not. Then the hotel could call the method in the rooms class as it does in the reservations class to determine whether the room is available and add it to a reservation and/or list available rooms depending on what admin needed to do.
54 changes: 54 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require_relative 'reservation'
require_relative 'rooms'
require 'pry'

# class hotel should store and manage the room and reservation lists

class Hotel
attr_reader :rooms, :reservations
# the ability to create a hotel instance
def initialize
@rooms = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]# 1-20
@reservations = []
end


# As an administrator, I can reserve a room for a given date range
# As an administrator, I can reserve an available room for a given date range
def create_reservation(start_date, end_date,room)
# create instance of reservation
# store the reservation
unless room_available?(start_date, end_date, room)
raise ArgumentError.new("Room number #{room} is not available")
end

new_reservation = Reservation.new(start_date, end_date, room)
@reservations << new_reservation
end



# As an administrator, I can access the list of reservations for a specific date
def list_reservations_for_specific_date(date)
# find reservations that contain the date
@reservations.select { |reservation| reservation.contains?(date) }
end

# As an administrator, I can view a list of rooms that are not reserved for a given date range
def list_rooms_available(start_date,end_date)
rooms.select {|room| room_available?(start_date, end_date, room) }
end

def room_available?(start_date, end_date,room)
# find all reservations for room
# check reservations for date
select_rooms = reservations.select { |reservation| reservation.room_number == room }

select_rooms.each do |res|
if res.contains?(start_date) || res.contains?(end_date) || (res.start_date >= start_date && res.end_date <= end_date)
return false
end
end
return true
end #room_available
end #class
48 changes: 48 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

require 'date'
require 'pry'

class Reservation
attr_reader :start_date, :end_date, :room_number

RATE = 200

# the ability to create a reservation
# raise an error for the incorrect date range
def initialize(start_date, end_date, room_number)
@room_number = room_number
@start_date = start_date
@end_date = end_date


date_valid?
end # initialize

#validate the dates for checkin and checkout
def date_valid?
unless @end_date == nil || @start_date == nil
raise ArgumentError.new('Invalid date range') if @end_date < @start_date
end
end

def contains?(date)
# reservation dates are included or not included in params
# room is reserved or available
date >= start_date && date <= end_date
end


# calculate days booked to help determine the cost of the reservation
# days_booked should not include the last day of the reservation
# checkout day days_booked is the (end_date - start_date)
def days_booked
end_date - start_date
end

# calculate total cost of reservation using the days booked and RATE
def total_cost
total_cost = (days_booked - 1)* RATE
return total_cost
end

end #class
Empty file added lib/rooms.rb
Empty file.
150 changes: 150 additions & 0 deletions specs/hotel_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
require_relative 'spec_helper'
gem 'minitest', '>= 5.0.0'
require 'minitest/pride'
require 'awesome_print'
require 'pry'

describe 'hotel class' do

describe '#initialize' do
it "can create an instance of hotel" do
new_building = Hotel.new
new_building.must_be_instance_of Hotel
end

it "has a list of 20 rooms" do
new_building = Hotel.new
new_building.rooms.length.must_equal 20
end

it "has a empty list of reservations" do
new_building = Hotel.new
new_building.reservations.length.must_equal 0
end
end

describe 'create_reservation' do
it "can create a reservation" do
new_building = Hotel.new

new_res = new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),3)

new_building.reservations.length.must_equal 1
new_building.reservations.length.must_be :>, 0
end

it "can create multiple reservations" do
new_building = Hotel.new

new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),2)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),7)
new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),20)


new_building.reservations.length.must_equal 3
new_building.reservations.length.must_be :>, 2
end

it "raises an ArgumentError when a room is not avaialable" do
new_building = Hotel.new

proc { new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),1)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),1)
}.must_raise ArgumentError
end

it "raises an ArgumentError when all the rooms are books" do
new_building = Hotel.new

new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),1)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),2)
new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),3)
new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),4)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),5)
new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),6)
new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),7)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),8)
new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),9)
new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),10)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),11)
new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),12)
new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),13)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),14)
new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),15)
new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),16)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),17)
new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),18)
new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),19)
new_building.create_reservation(Date.new(2018,3,7),Date.new(2018,3,10),20)

proc { new_building.create_reservation(Date.new(2018,3,8),Date.new(2018,3,11),3)
}.must_raise ArgumentError
end

end

describe 'list_reservations_for_specific_date' do
it "will list all reservations during the date passed in" do
new_building = Hotel.new


new_building.create_reservation(Date.new(2018,4,2),Date.new(2018,4,7),1)
new_building.create_reservation(Date.new(2018,9,1),Date.new(2018,9,6),1)


res = new_building.list_reservations_for_specific_date(Date.new(2018,4,4))
res.must_be_kind_of Array

res.length.must_equal 1

res_2 = new_building.list_reservations_for_specific_date(Date.new(2017,4,4))
res_2.length.must_equal 0


end
#two reservations that overlap and make sure it displays 2
end


describe 'list_rooms_available' do
it "can list all available rooms" do
new_building = Hotel.new

res_1 = new_building.create_reservation(Date.new(2018,4,2),Date.new(2018,4,7),2)
res_2 = new_building.create_reservation(Date.new(2018,4,1),Date.new(2018,4,6),1)
res_3 = new_building.create_reservation(Date.new(2018,4,3),Date.new(2018,4,5),3)
# new_building.create_reservation(Date.new(2018,5,7),Date.new(2018,5,14),1)

list = new_building.list_rooms_available(Date.new(2018,4,3),Date.new(2018,4,6))

list.must_be_kind_of Array
list.wont_include 2
list.wont_include 1
list.wont_include 3
end
end

describe 'room_available?' do
it "returns true when room is available" do
new_building = Hotel.new

res_0 = new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),1)
res_1 = new_building.create_reservation(Date.new(2018,4,2),Date.new(2018,4,7),2)

res_2 = new_building.room_available?(Date.new(2018,3,6),Date.new(2018,3,9),2)

res_2.must_equal true
end

it "returns false when a room is not available" do
new_building = Hotel.new

res_0 = new_building.create_reservation(Date.new(2018,3,6),Date.new(2018,3,9),1)
res_1 = new_building.create_reservation(Date.new(2018,4,2),Date.new(2018,4,7),2)

res_2 = new_building.room_available?(Date.new(2018,3,6),Date.new(2018,3,9),1)

res_2.must_equal false
end
end
end
45 changes: 45 additions & 0 deletions specs/reservation_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require_relative 'spec_helper'
gem 'minitest', '>= 5.0.0'
require 'minitest/pride'
require 'pry'

describe 'reservations class' do

describe 'initialize' do
it "can create an instance of reservation" do

new_reservation = Reservation.new(Date.new(2018,2,5), Date.new(2018,2,6),3)
new_reservation.must_be_instance_of Reservation
end

it "raises and ArgumentError if end_date is before start_date" do

start_date = Date.new(2018,2,20),
end_date = Date.new(2018,2,2),
room_number = 4


proc {
new_res = Reservation.new(start_date, end_date, room_number)
}.must_raise ArgumentError

end
end

describe 'days_booked' do
it "calculates days booked correctly" do
new_reservation = Reservation.new(Date.new(2018,3,10), Date.new(2018,3,15),3)

new_reservation.days_booked.must_equal 5
end
end

describe 'total_cost' do
it "calculates total_cost correctly" do
new_reservation = Reservation.new(Date.new(2018,5,10), Date.new(2018,5,20),9)

new_reservation.total_cost.must_equal 1800
end
end

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

gem 'minitest', '>= 5.0.0'
require 'minitest/pride'
require 'minitest/autorun'
require 'minitest/reporters'

require_relative '../lib/hotel'
require_relative '../lib/reservation'



Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new