-
Notifications
You must be signed in to change notification settings - Fork 48
Branches - Linnea #44
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
base: master
Are you sure you want to change the base?
Changes from all commits
160a369
c59bdef
3e02f23
7bb406f
f40d1ec
644dc7e
cc9b5a1
446d6b2
b51006a
c25879e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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. |
| 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 != [] | ||
| return true | ||
| else | ||
| return false | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| 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) | ||
|
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. This method isn't actually using the room_number param for anything. 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 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 | ||
| 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 |
| 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 |
| 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 |
| 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 |
| 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!) |
| 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" |
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.
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