Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file added .DS_Store
Binary file not shown.
15 changes: 15 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Question | Answer
:------------- | :-------------
What classes does each implementation include? Are the lists the same? | Each implementation includes the same classes - CartEntry, ShoppingCart, and Order.
Write down a sentence to describe each class. | CartEntry: Calculates price for each type of item purchased (e.g. apples). ShoppingCart: Stores the list of items being purchased and calculates the total cost. Order: Calculates the total price with sales tax.
How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper. | A ShoppingCart has many CartEntries, and an Order has one ShoppingCart.
What data does each class store? How (if at all) does this differ between the two implementations? | CartEntry stores unit price and quantity, ShoppingCart stores the entries, and Order stores the cart cost plus tax. The data stored does not differ between the two implementations.
What methods does each class have? How (if at all) does this differ between the two implementations? | In both implementations, the purpose of the program is to calculate the cost. However, in the first implementation, the entire cost is calculated in the Order 'master class.' in the second implementation, the calculations are spread across the three classes.
Consider the Order#total_price method. In each implementation:
Question | Answer
:------------- | :-------------
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 the price is entirely retained in Order. In implementation B, the logic is delegated across all the classes based on what information they store individually.
Does total_price directly manipulate the instance variables of other classes? | Implementation A: total price directly manipulates instance variables in CartEntry and ShoppingCart. Implementation B: total price does not directly manipulate instance variables in other classes.
If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify? | There would no longer be a direct relationship between unit price and quantity - at some point (whatever is deemed a 'bulk amount' for quantity), the unit price would decrease. Implementation B would be easier to change because it does not directly rely on the instance variables in the CartEntry class.
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. The calculations in implementation A have a lot of dependencies on other classes.
Empty file added false,
Empty file.
39 changes: 39 additions & 0 deletions lib/date_range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require 'date'

module Hotel
class DateRange
attr_reader :start_date, :end_date

#why did I have to make these arguments 'required' in order for my tests to work?
def initialize(input_start_date, input_end_date)
@start_date = Date.parse(input_start_date)
@end_date = Date.parse(input_end_date)
if @end_date <= @start_date
raise ArgumentError.new("the end date is before the start date!")
end
end

#do not include end date in range because another reservation can include that same date as the start date
def createDateArray
@date_array = (@start_date...@end_date).to_a
return @date_array
end

def duration
duration = (@end_date - @start_date).to_i
return duration
end

#friend/'mentor' helped with refactoring overlap code
#she explained the single '&' is 'bitwise' code and is used more often in lower-level languages. It is comparing the object's date range array with the inputted object's date range array and pushes those similarities into an array. If they have no similarities (e.g. the array is empty), it returns false (indicating there is no overlap). If the array contains any dates, it returns true (indicating overlap) because the array will be filled with overlapping dates.
#typically 'other' is used, but for my understanding I used the parameter 'input'
def overlap?(input)
if self.createDateArray & input.createDateArray != []

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cool that your mentor showed you this! It's important for Ada that you understand in detail what the code you wrote is doing to the point you could come up with it on your own if given a similar assignment in the future. So if you understand this to that level of depth, that's great! I'm just calling that out because I'm having trouble understanding it tbh. Haha

return true
else
return false
end
end
end
end

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

module Hotel
class HotelBooker
attr_reader :rooms
attr_accessor :reservations

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

#selects first available room for reservation, shovels into reservations array
#if there were no available rooms, the array would be empty! therefore, if the length of the array is 0, the program raises an ArgumentError.
#instructor helped me fix this code and the test in our 1:1 (had been returning a Hash)
def createReservation(room_number, date_range)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This method isn't actually using the room_number param for anything.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You didn't actually need to give the user the ability to define which room number but it's bad to make the method look like it's allowing the user to specify the room number when it isn't.

available_rooms_list = rooms_available?(date_range)
if available_rooms_list.length == 0
raise ArgumentError.new("no available rooms for those dates!")
end

new_reservation = Reservation.new(room_number: available_rooms_list.first, date_range: date_range)
return @reservations << new_reservation
end

#checks the date_range
def reservationsByDate(date)
@reservations.each do |reservation_object|
if reservation_object.date_range.createDateArray.include?(date)
return reservation_object
end
end
end

#first tried shoveling all room numbers EXCEPT those with overlapping date ranges into an empty array available_rooms, but program was returning nil values; .delete method worked (provide full array of rooms using @rooms instance variable, then delete as they appear to return an array with available dates)
def rooms_available?(date_range)
available_rooms = @rooms
@reservations.each do |reservation_object|
if reservation_object.date_range.overlap?(date_range) == true
available_rooms.delete(reservation_object.room_number)
end
end
return available_rooms
end
end
end
17 changes: 17 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'date'

module Hotel
class Reservation
ROOM_RATE = 200
attr_reader :room_number, :date_range

def initialize(room_number:, date_range:)
@room_number = room_number
@date_range = date_range
end

def total_cost(nights)
return (ROOM_RATE * nights)
end
end
end
47 changes: 47 additions & 0 deletions test/date_range_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require_relative 'test_helper'
require 'rake'

describe "DateRange class" do
#similar to before statement in trip_dispatcher 'build_test_dispatcher'
#new_range is instance of DateRange
before do
def new_range(start_date, end_date)
return Hotel::DateRange.new(start_date, end_date)
end
end

describe "DateRange instantiation" do
before do
@start_date = "2001/2/3"
@end_date = "2001/2/5"
@new_range = new_range(@start_date, @end_date)
end

it "is an instance of DateRange" do
expect(@new_range).must_be_instance_of Hotel::DateRange
end

it "raises an argument error if dates are invalid" do
expect{new_range("2001/2/5", "2001/2/3")}.must_raise ArgumentError
end

it "creates an array of all dates, excluding reservation end date" do
test_range = @new_range.createDateArray
expect(test_range).must_be_kind_of Array
expect(test_range).wont_include @new_range.end_date
end

#test includes one array with dates that overlap with the range_array and one array with dates that do not. The test for the overlapping dates returns true and the test for the non-overlapping dates returns false.
it "makes sure dates don't overlap" do
range_array = new_range("2001/2/3", "2001/2/5")
test_array_with_overlap = new_range("2001/2/4", "2001/2/6")
test_array_with_no_overlap = new_range("2001/5/14", "2001/5/17")

overlap_test = @new_range.overlap?(test_array_with_overlap)
no_overlap_test = @new_range.overlap?(test_array_with_no_overlap)

expect(overlap_test).must_equal true
expect(no_overlap_test).must_equal false
end
end
end
63 changes: 63 additions & 0 deletions test/hotel_booker_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require_relative 'test_helper'
require 'rake'

describe "HotelBooker class" do
before do
@date_range = Hotel::DateRange.new("2001/2/3", "2001/2/5")
@reservations = Hotel::Reservation.new(room_number: 1, date_range: @date_range)
@hotel_booker = Hotel::HotelBooker.new(
rooms: (1..20).to_a,
reservations: @reservations)
end

describe "HotelBooker instantiation" do
it "is an instance of HotelBooker" do
expect(@hotel_booker).must_be_instance_of Hotel::HotelBooker
end

it "lists all rooms in the hotel" do
expect(@hotel_booker.rooms.count).must_equal 20
end
end

#added @reservations.room_number parameter to try to debug the Hash error when raising an ArgumentError when all rooms are taken for a range range; might delete
#deleted before/do statement which contained @hotel_reservation = @hotel_booker.createReservation(@reservations.room_number, @date_range); it was causing errors
describe "HotelBooker methods" do
it "stores new reservations in the reservations array" do
@hotel_reservation = @hotel_booker.createReservation(@reservations.room_number, @date_range)
expect(@hotel_reservation).must_be_kind_of Array
expect(@hotel_reservation[0]).must_be_instance_of Hotel::Reservation
end

#shovels the reservations for a specified date into an array
it "selects all reservations on a specified date" do
@hotel_reservation = @hotel_booker.createReservation(@reservations.room_number, @date_range)
list_of_reservations = []
list_of_reservations << @hotel_booker.reservationsByDate(Date.parse("2001/2/3"))

expect(list_of_reservations).must_be_kind_of Array
expect(list_of_reservations[0]).must_be_instance_of Hotel::Reservation
end

#code finds the first available room, so the array will equal the remaining rooms 2-20
it "can view a list of rooms that are not reserved for a given date range" do
@hotel_reservation = @hotel_booker.createReservation(@reservations.room_number, @date_range)

dates = Hotel::DateRange.new("2001/2/3", "2001/2/5")

reservation = Hotel::Reservation.new(room_number: 1, date_range: dates)

expect(@hotel_booker.rooms_available?(dates)).must_equal (2..20).to_a
end

#loops 20 times to create 20 different reservations to book all rooms; raises ArgumentError because no rooms available
it "raises an exception if program tries to reserve a room during a date range when all rooms are reserved" do
#room_number = 1
20.times do
@hotel_booker.createReservation(@reservations.room_number, @date_range)
#room_number += 1
end
expect{@hotel_booker.createReservation(@reservations.room_number, @date_range)}.must_raise ArgumentError
end
end
end
29 changes: 29 additions & 0 deletions test/reservation_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require_relative 'test_helper'
require 'rake'

describe "Reservation class" do
describe "Reservation instantiation" do
before do
@date_range = Hotel::DateRange.new("2001/2/3", "2001/2/5")
@reservation = Hotel::Reservation.new(
room_number: 1,
date_range: @date_range
)
end

it "is an instance of Reservation" do
expect(@reservation).must_be_instance_of Hotel::Reservation
end

it "date_range is an instance of DateRange" do
puts @reservation.date_range
expect(@reservation.date_range).must_be_instance_of Hotel::DateRange
end

it "finds duration of stay and total cost of reservation" do
nights = @reservation.date_range.duration
total_cost = @reservation.total_cost(nights)
expect(total_cost).must_equal 400
end
end
end
10 changes: 10 additions & 0 deletions test/simplecovtests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
1. What are SimpleCov and Guard?
a. SimpleCov - a tool to check what lines of code your tests cover (green).
b. Guard - Autorake - runs the tests affected by code changes, when you save
2. How might you use them in the Hotel project?
a. SimpleCov - Identify places in your code you're not testing!
i. refactoring - can help you identify blocks of code that will never be executed and aren't needed
b. Guard - see if the change you just wrote caused a test to pass or fail
3. Where do SimpleCov & Guard not help you in testing/
a. SimpleCov - doesn't tell you if you covered all scenarios/edge cases (test quality)
b. Guard - causes the SimpleCov report to only cover the most recent tests run (run rake manually to override this!)
9 changes: 8 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
# Add simplecov
require 'simplecov'
SimpleCov.start do
add_filter 'test/'
end

require "minitest"
require "minitest/autorun"
require "minitest/reporters"

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

# require_relative your lib files here!
require_relative "../lib/date_range"
require_relative "../lib/reservation"
require_relative "../lib/hotel_booker"