Skip to content
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

Laura Robertson -- Carets #38

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
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
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
54 changes: 54 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
##### What classes does each implementation include? Are the lists the same?
Implementation A & B both include three classes: CartEntry, ShoppingCart, and Order. The class names are the same, but attr-s and methods are different.

##### Write down a sentence to describe each class.
**CartEntry:** Initializes a product object (unit_price, quantity). **ShoppingCart:** Is a single object (array) that holds the CartEntry objects, but not actually coupled with CartEntry. **Order:** Initializes a new ShoppingCart object, both versions have a SALES_TAX constant and total_price method.

##### How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper.
Order creates a new ShoppingCart object, which creates an @entries array. The @entries array in ShoppingCart holds CartEntry objects. When total_price is called in Order, the method iterates over each CartEntry to gets its unit_price and quantity and add it to the sum, then adding tax.

##### What **data** does each class store? How (if at all) does this differ between the two implementations?
**CartEntry** holds a product's price and how many are being purchased. **ShoppingCart** will hold an array of CartEntry objects. **Order** holds the individual ShoppingCart object. The implementations seems to hold the same data, but different methods.

##### What **methods** does each class have? How (if at all) does this differ between the two implementations?
Implementation A & B both have a total_price method in the Order class. In implementation A, this is the only method. In implementation B, CartEntry and ShoppingCart have additional methods for price.

##### Consider the Order#total_price method. In each implementation:
**-Is the logic to compute the price delegated to "lower level" classes like ShoppingCart and CartEntry, or is it retained in Order?**
Implementation A: retained in Order. Implementation B: it is delegated to lower level classes.

**-Does total_price directly manipulate the instance variables of other classes?**
My understanding is that neither implementations change/manipulate the instance variables; however, Implementation A could manipulate the variables because of the attr_accessors in CartEntry and ShoppingCart.

##### If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify?
Implementation B, the adjustment can be made in the price method within the CartEntry class.

##### Which implementation better adheres to the single responsibility principle?
Implementation B, the added method for price makes it single responsibility. If a change was made within the class, it should not affect methods outside of the class.

##### **Bonus question** once you've read Metz ch. 3: Which implementation is more loosely coupled?
Implementation B, everything is contained within a class. Changes to names would only affect things within the class (unless the price method was re-named). Whereas in implementation A, any name/function changes in any class would affect Order.total_price.


**Now that we've got you thinking about design, spend some time to revisit the code you wrote for the Hotel project. For each class in your program, ask yourself the following questions:**

###What is this class's responsibility?
You should be able to describe it in a single sentence.

###Is this class responsible for exactly one thing?

###Does this class take on any responsibility that should be delegated to "lower level" classes?

###Is there code in other classes that directly manipulates this class's instance variables?

##Activity

Based on the answers to the above questions, 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 why the resulting design would be an improvement.

##### Answer

My find_available method in class California directly accessed the instance objects of rooms. Class California took an additional role when availability of a room could easily be determined within the class Room.

Changes to be made: create isAvailable method in room that returns the room number if it is available, modify find_available to use isAvailable method on each room.

This makes class California more loosely coupled to class Room. Modifications in either class will be less likely to break functionality.
12 changes: 12 additions & 0 deletions lib/block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require_relative 'reservation'

module Hotel
class Block < Reservation
attr_accessor :status

def initialize(start_date, end_date)
super(start_date, end_date)
@status = :available
end
end
end
97 changes: 97 additions & 0 deletions lib/hotel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
require 'date'
require_relative 'room'
require_relative 'reservation'
require_relative 'block'

module Hotel

class California
attr_reader :all_rooms

def initialize
@num_of_rooms = 20
@rate = 200
@all_rooms = {}
(1..@num_of_rooms).each do |room|
@all_rooms[room] = Hotel::Room.new(room, @rate)
end
end

def find_available(date)
by_date = []
@all_rooms.each do |k, v|
room = @all_rooms[k].isAvailable(date)
if room
by_date << room
end
end
return by_date
end

def total(room, reservation)
num_nights = @all_rooms[room].reservations[reservation].dates.length - 1
return num_nights * @rate
end

def find_by_date(date)
valid_date = Date.parse(date)
by_date = []
@all_rooms.each do |k, v|
if @all_rooms[k].reservations.length != 0
@all_rooms[k].reservations.each_index do |i|
if @all_rooms[k].reservations[i].dates.include? valid_date.to_s
by_date << @all_rooms[k]
end
end
end
end
return by_date
end

def all_reservations
all = []
@all_rooms.each do |k, v|
if @all_rooms[k].reservations.length != 0
all << @all_rooms[k].reservations
end
end
return all
end

def create_block(start_date, end_date, num_rooms)
if num_rooms > 5
raise ArgumentError.new("You cannot block reserve more then 5 rooms.")
end

start_date = Date.parse(start_date)
end_date = Date.parse(end_date)
dates = (start_date..end_date).map(&:to_s)

available_rooms = []
dates.each {|date| available_rooms << find_available(date)}
available_rooms = available_rooms.inject(:&).first(num_rooms)

if available_rooms.length < num_rooms
raise ArgumentError.new("There are not enough rooms available for those dates.")
end

available_rooms.each do |id|
@all_rooms[id].reservations << Hotel::Block.new(start_date, end_date)
end
end

def reserve_block
# currently only for all blocks not specific blocks
reserved = false
@all_rooms.each do |id, room|
room.reservations.each_index do |resId|
if reserved == false && room.reservations[resId].class == Hotel::Block && room.reservations[resId].status == :available
room.reservations[resId].status = :occupied
reserved = true
end
end
end
end

end #end of California
end #end of Hotel
13 changes: 13 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Hotel

class Reservation
attr_reader :start_date, :end_date, :dates

def initialize(start_date, end_date)
@start_date = start_date
@end_date = end_date
@dates = (@start_date..@end_date).map(&:to_s)
end

end
end
49 changes: 49 additions & 0 deletions lib/room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require_relative 'reservation'

module Hotel

class Room
attr_reader :room_num, :rate, :dates
attr_accessor :reservations

def initialize(room_num, rate)
@room_num = room_num
@rate = rate
@reservations = []
end

def create_reservation(start_date, end_date)
start_date = Date.parse(start_date)
end_date = Date.parse(end_date)
dates = (start_date..end_date).map(&:to_s)
reservation = Hotel::Reservation.new(start_date, end_date)

if @reservations.length == 0
@reservations << reservation
else
@reservations.each do |item|
compare = dates & item.dates[0...-1]
if compare.length != 0
raise ArgumentError.new("This room is already booked.")
end
end
@reservations << reservation
end
end

def isAvailable(date)
valid_date = Date.parse(date)
if @reservations.length == 0
return @room_num
elsif @reservations.length != 0
@reservations.each_index do |i|
unless @reservations[i].dates.include? valid_date.to_s
return @room_num
end
end
end
return nil
end

end #end of Room
end #end of Hotel
18 changes: 18 additions & 0 deletions specs/block_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require_relative "spec_helper"

describe "Block class" do
# using let()!
let(:block) {Hotel::Block.new("2017-03-01", "2017-03-05")}

describe "initialize" do
it "Creates an instance" do
block.must_be_kind_of Hotel::Block
end

it "Can access Reservation initialize" do
block.start_date.must_equal "2017-03-01"
block.end_date.must_equal "2017-03-05"
block.dates.must_be_instance_of Array
end
end
end
5 changes: 5 additions & 0 deletions specs/coverage/.last_run.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"result": {
"covered_percent": 100.0
}
}
7 changes: 7 additions & 0 deletions specs/coverage/.resultset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"RSpec": {
"coverage": {
},
"timestamp": 1504884464
}
}
Empty file.
Loading