-
Notifications
You must be signed in to change notification settings - Fork 45
Marisa Morris - Carets #23
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
9b0e8a5
25b1675
a5bf73e
3de1164
c2c919d
4800909
fc4bc05
472f74d
1d81dc5
76cbbdf
9d61cab
d0f04d7
6d8c2dc
c679ceb
68a6906
a68ce8c
29bdaf2
a7a3f33
bf4d70d
8c7ac00
dfd1487
d9d2022
b8bb268
2261275
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,70 @@ | ||
| - What classes does each implementation include? Are the lists the same? | ||
|
|
||
| Each implementation includes the same three classes consisting of CartEntry, ShoppingCart, and Order. | ||
|
|
||
| - Write down a sentence to describe each class. | ||
|
|
||
| CartEntry: Initializes unit_price and quantity (implementation A & B), and calculates the price of the entry to be added to the cart (implementation B). | ||
|
|
||
| ShoppingCart: In both implementations, an entries array is initialized, however, the only difference is that implementation B has a price method that returns the sum of each entry utilizing the price method from the CartEntry class. | ||
|
|
||
| Order: Each of the order classes initializes a new instance of the ShoppingCart class and returns the total price of the shopping cart after factoring in tax. | ||
|
|
||
| - 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 attributes of the class prior. for example, in implementation B, the ShoppingCart class entries array will consist of the instances of the car class after the price method has been executed and the Order class returns the total price based on what is returned in the ShoppingCart class. | ||
|
|
||
|
|
||
| - What data does each class store? How (if at all) does this differ between the two implementations? | ||
|
|
||
| Implementation A | ||
| CartEntry: Stores a unit_price and quantity instance variables. | ||
|
|
||
| ShoppingCart: Stores an entires array. | ||
|
|
||
| Order: Stores an instance of the ShoppingCart class and a method that sums the total of the entires array and adds tax. | ||
|
|
||
| Implementation B | ||
| CartEntry: Stores a unit_price and quantity instance variables and a price method that returns the sum of the unit_price and quantity multiplied. | ||
|
|
||
| ShoppingCart: Stores an entires array and has a price method that returns the sum of all the entries in the array | ||
|
|
||
| Order: Stores an instance of the ShoppingCart class and has a total_price method that adds tax to the sum of entries array. | ||
|
|
||
|
|
||
| - What methods does each class have? How (if at all) does this differ between the two implementations? | ||
|
|
||
| Implementation A (methods in each class) | ||
| CartEntry: No methods | ||
| ShoppingCart: No methods | ||
| Order: total_price | ||
|
|
||
| Implementation B (methods in each class) | ||
| CartEntry: price | ||
| ShoppingCart: price | ||
| Order: total_price | ||
|
|
||
| - 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 B, logic to compute total_price is broken down throughout the three classes whereas in implementation A all of the logic to compute total price resides in the order class. | ||
|
|
||
| - Does total_price directly manipulate the instance variables of other classes? | ||
|
|
||
| No, the total_price method does not directly manipulate the instance variables of the other classes. | ||
|
|
||
|
|
||
| - If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify? | ||
|
|
||
| If items are bought in bulk, it would be easier to update the code in Implementation B, specifically within the CartEntry class as it deals with a quantity instance variable. The update can be done by adding a conditional. | ||
|
|
||
|
|
||
| - Which implementation better adheres to the single responsibility principle? | ||
|
|
||
| Implementation B better adheres to the single reason principle. | ||
|
|
||
| <!-- - Bonus question once you've read Metz ch. 3: Which implementation is more loosely coupled? --> | ||
|
|
||
| ACTIVITY | ||
|
|
||
| An area in my code that needed to be updated was the hotel class, specifically the create_reservation method. The method was checking for valid date ranges in addition to creating and instance of the reservation class id the dates were valid. I fixed this by moving the date validation portion to the reservation class and creating a new method that checks for date validity. This is an improvement because it allows the hotel class to focus on creating reservations (regular and block) and return bits of information having to due with reservations and designating other functions such as checking dates to lower level classes. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # block | ||
| require 'date' | ||
| require 'securerandom' | ||
|
|
||
| module HotelManagment | ||
| class Block | ||
| attr_reader :amount_of_rooms, :check_in_date, :check_out_date, :id | ||
| attr_accessor :rooms | ||
|
|
||
| BLOCKRATE = 100 | ||
|
|
||
| def initialize(check_in_date, check_out_date, amount_of_rooms) | ||
| @amount_of_rooms = amount_of_rooms | ||
| @check_in_date = check_in_date | ||
| @check_out_date = check_out_date | ||
| @rooms = [] | ||
| @id = SecureRandom.uuid | ||
| end | ||
|
|
||
| def validate | ||
| if amount_of_rooms > 5 | ||
| raise ArgumentError, '5 rooms is the Maximum a block allows' | ||
| end | ||
| end | ||
|
|
||
| end #class end | ||
| end #module end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # block_reservation | ||
| require 'date' | ||
|
|
||
| module HotelManagment | ||
| class BlockReservation < Reservation | ||
|
|
||
| def initialize(first_name, last_name, check_in_date, check_out_date, room_number) | ||
| super | ||
| @cost = cost | ||
| end | ||
|
|
||
| def block_rate | ||
| nights = @check_out_date - @check_in_date | ||
| @cost = nights.to_i * Block::BLOCKRATE | ||
| end | ||
|
|
||
| # private | ||
| # def validate | ||
| # if amount_of_rooms > 5 | ||
| # raise ArgumentError, '5 rooms is the Maximum a block allows' | ||
| # end | ||
| # end | ||
| end #class end | ||
| end #module end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| # hotel | ||
| require_relative 'room.rb' | ||
| require 'date' | ||
|
|
||
| module HotelManagment | ||
| class Hotel | ||
| attr_reader :rooms, :reservations, :found_reservations, :unreserved_rooms, :blocks | ||
| def initialize | ||
| @rooms = [] | ||
|
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. If you're setting |
||
| @reservations = [] | ||
| @found_reservations = [] | ||
| @unreserved_rooms = [] | ||
| @blocks = [] | ||
|
|
||
| # add_20_rooms | ||
| end | ||
|
|
||
| def add_20_rooms | ||
| room_number = 1 | ||
| 20.times do | ||
| room = HotelManagment::Room.new(room_number) | ||
| @rooms << room | ||
| room_number += 1 | ||
| end | ||
| end | ||
|
|
||
|
|
||
| # creates a reservation | ||
| def create_reservation(first_name, last_name, check_in_date, check_out_date, room_number) | ||
|
|
||
|
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. The |
||
| reservation = Reservation.new(first_name, last_name, check_in_date, check_out_date, room_number) | ||
|
|
||
| @reservations << reservation | ||
| end | ||
|
|
||
|
|
||
|
|
||
| def reservations_by_date(date) | ||
| @reservations.each { |reservation| | ||
|
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. Good use of enumerables in this project. |
||
| if reservation.check_in_date <= date && reservation.check_out_date >= date | ||
| found_reservations << reservation | ||
| end | ||
| } | ||
| return @found_reservations | ||
| end | ||
|
|
||
|
|
||
| # returns an array or rooms not reserved for a given date range | ||
| def rooms_not_reserved(check_in_date, check_out_date) | ||
| # guard clause: if the reservations array is empty, return a rooms array of room numbers. If no reservations, all rooms can be reserved for a block. | ||
| return @rooms.map { |room| room.room_number } if @reservations.empty? && @blocks.empty? | ||
|
|
||
| unreserved_rooms = @rooms.map { |room| room.room_number } | ||
| # if !@reservation.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) | ||
| end | ||
| } | ||
| # 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 | ||
| end | ||
| } | ||
| return unreserved_rooms | ||
| end | ||
|
|
||
|
|
||
| # reserves the first available room for a given date range. Uses the rooms_not reserved method. | ||
| def reserve_room_for_date_range(first_name, last_name, check_in_date, check_out_date) | ||
|
|
||
| # set the rooms_not_reserved method and arguments to a local variable. | ||
| # rooms_not_reserved returns an empty array if there is nothing avail in given date range. | ||
| # or returns array of room numbers of the avail rooms in date range given. | ||
|
|
||
| rooms_unreserved_for_this_date = rooms_not_reserved(check_in_date, check_out_date) | ||
|
|
||
| if rooms_unreserved_for_this_date.length == 0 | ||
| raise ArgumentError, 'No Available Rooms for Given Dates' | ||
| else | ||
| create_reservation(first_name, last_name, check_in_date, check_out_date, rooms_unreserved_for_this_date[0]) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| def create_block(check_in_date, check_out_date, amount_of_rooms) | ||
| available_rooms = rooms_not_reserved(check_in_date, check_out_date) | ||
|
|
||
| block = HotelManagment::Block.new(check_in_date, check_out_date, amount_of_rooms) | ||
| block.rooms = available_rooms.pop(amount_of_rooms) | ||
| @blocks << block | ||
| return block | ||
| end | ||
| # end | ||
|
|
||
|
|
||
| def reserve_room_in_block(first_name, last_name, block_id) | ||
| block = @blocks.select {|block| block.id == block_id}[0] | ||
|
|
||
| if block.rooms.empty? | ||
| # TODO make test | ||
| raise ArgumentError, 'No rooms left in block' | ||
| else | ||
| room_number = block.rooms.pop | ||
| HotelManagment::BlockReservation.new(first_name, last_name, block.check_in_date, block.check_out_date, room_number) | ||
| end | ||
| end | ||
|
|
||
| # private | ||
| # def add_20_rooms | ||
| # room_number = 1 | ||
| # 20.times do | ||
| # room = HotelManagment::Room.new(room_number) | ||
| # @rooms << room | ||
| # room_number += 1 | ||
| # end | ||
| # end | ||
|
|
||
|
|
||
| end #class end | ||
| end #module end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| #reservation | ||
| require 'date' | ||
|
|
||
|
|
||
| module HotelManagment | ||
| class Reservation | ||
| attr_reader :first_name, :last_name, :check_in_date, :check_out_date, :room_number, :cost | ||
|
|
||
|
|
||
| def initialize(first_name, last_name, check_in_date, check_out_date, room_number) | ||
| @first_name = first_name | ||
| @last_name = last_name | ||
| @check_in_date = check_in_date | ||
| @check_out_date = check_out_date | ||
| @room_number = room_number | ||
| @cost = cost | ||
| end | ||
|
|
||
| def rate | ||
| nights = @check_out_date - @check_in_date | ||
| @cost = nights.to_i * Room::RATE | ||
|
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 set the cost to a different value in |
||
| end | ||
|
|
||
| def validate_dates | ||
| if check_in_date < DateTime.now || check_out_date < check_in_date | ||
| raise ArgumentError, 'Invalid dates' | ||
| end | ||
| end | ||
|
|
||
| end #class end | ||
| end #module end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| #room | ||
| require 'awesome_print' | ||
|
|
||
| module HotelManagment | ||
| class Room | ||
| attr_reader :room_number | ||
|
|
||
| RATE = 200 | ||
|
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. Good use of a constant! |
||
|
|
||
| def initialize(room_number) | ||
| @room_number = room_number | ||
| end | ||
|
|
||
| end #class end | ||
| end #module end | ||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| require_relative 'spec_helper' | ||
| require 'date' | ||
|
|
||
|
|
||
| describe "Reservaton Class" do | ||
| describe "Initialize" do | ||
|
|
||
| it "Should be able to instantiate a reservation" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.must_be_instance_of HotelManagment::BlockReservation | ||
| end | ||
|
|
||
| it "First name should be an instance of String" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.first_name.must_be_instance_of String | ||
| end | ||
|
|
||
| it "Last name should be an instance of String" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.last_name.must_be_instance_of String | ||
| end | ||
|
|
||
| it "check_in_date should be an instance of Date" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.check_in_date.must_be_instance_of Date | ||
| end | ||
|
|
||
| it "check_out_date should be an instance of Date" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.check_out_date.must_be_instance_of Date | ||
| end | ||
|
|
||
| it "reservation_number must be instance of integer" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.room_number.must_be_instance_of Integer | ||
| end | ||
|
|
||
| end | ||
|
|
||
|
|
||
| describe "block_rate Method" do | ||
|
|
||
| it "Must respond to block_rate" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.must_respond_to :block_rate | ||
| end | ||
|
|
||
| it "should return the total cost based on the number of nights reserved" do | ||
| date = Date.today | ||
| new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 3, 1) | ||
| new_block_reservation.block_rate.must_equal 200 | ||
| end | ||
| end | ||
|
|
||
| # describe "validate" do | ||
| # it "should raise error if block room amount is greater than 5" do | ||
| # date = Date.today | ||
| # new_block_reservation = HotelManagment::BlockReservation.new("marisa", "morris", date + 1, date + 6, 6) | ||
| # | ||
| # proc {new_block_reservation.validate("marisa", "morris", date + 1, date + 4, 6) }.must_raise ArgumentError | ||
| # end | ||
| # end | ||
| end |
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.
Shouldn't you simply override the
ratemethod?Why create the same method by a different name in a subclass?