Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
812d5ff
Add coverage directory to .gitignore file
jessiezhang2017 Sep 4, 2018
fc90cbb
set up the room class and the initialize method
jessiezhang2017 Sep 4, 2018
d8195c6
add the initialize method for reservation.rb
jessiezhang2017 Sep 5, 2018
4c9bec1
changed the hotel.rb to admin.rb , added add_reservation method in ro…
jessiezhang2017 Sep 5, 2018
5e3f9b0
add a dates_booked method in reservation class
jessiezhang2017 Sep 5, 2018
8f3294b
finish the initialize for Admin class
jessiezhang2017 Sep 5, 2018
a3835a3
remove add_reservation method from room.rb, changed reservation.rb i…
jessiezhang2017 Sep 7, 2018
2113788
complete the add_reserve_date method in room.rb, adjust the initializ…
jessiezhang2017 Sep 7, 2018
54e9502
add make_reservation method in admin.rb
jessiezhang2017 Sep 8, 2018
65b3d8a
finish list reservations on a date and return the reservation cost m…
jessiezhang2017 Sep 8, 2018
7dea527
finish wave 1
jessiezhang2017 Sep 8, 2018
7e10ae1
add @room_unbooked_dates as the instance attribut for admin.rb, upda…
jessiezhang2017 Sep 9, 2018
8ff8351
complete the room_available_list in a given date range method
jessiezhang2017 Sep 9, 2018
548059f
update make_reservaion method to allow system pick the first room whi…
jessiezhang2017 Sep 9, 2018
a2925c1
change the admin.rb initailze method to add more parameters
jessiezhang2017 Sep 9, 2018
dcf4a38
add a BlockAdmin class which is a child class of Admin class
jessiezhang2017 Sep 9, 2018
8505abe
finished create_room_block method in admin.rb
jessiezhang2017 Sep 10, 2018
87de2a4
add a main.rb for test run purpose
jessiezhang2017 Sep 10, 2018
6f563a7
change a typo
jessiezhang2017 Sep 10, 2018
9b71615
added sesign-activity.md
jessiezhang2017 Sep 30, 2018
0d2503d
add the change plan to design-activity.md
jessiezhang2017 Sep 30, 2018
d44bbac
remove main.rb, change the block class to be indepentaant, remove id …
jessiezhang2017 Oct 1, 2018
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.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ build-iPhoneSimulator/

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
coverage
59 changes: 59 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# What classes does each implementation include? Are the lists the same?
Each implementation include: CartEntry, ShoppingCart and Order.
The lists are the same.

# Write down a sentence to describe each class.
CartEntry: each time when the user add new items into the Cart , taking care of that addition

ShoppingCart: holding a list of the cart entries , represents all the items user has added to the Shopping Cart.

Order: taking care of the order.

# How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper.

ShoppingCart contains a list of CartEntry instances.
Order is generated based on the current items holding in the ShoppingCart.

# What data does each class store? How (if at all) does this differ between the two implementations?
CartEntry class: stores unit_price and quantity of the entry item.
ShoppingCart class: stores a list of the CartEntry.
Order class: stores sales tax rate, a new instance of the SHoppingCart class

two implementations has no difference.

# What methods does each class have? How (if at all) does this differ between the two implementations?

CartEntry: A has read, write methods on instance variable @unit_price and @quantity. B has a price method to calculate the price of each CartEntry.

ShoppingCart: A has a read write method on instance variable @entries. B has a price method on ShoppingCart to calculate the total price of the ShoppingCart

Order : A has a method to calculate the total price of the order. B is the same as A.

# 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?

B : The logic to compute the price delegated to the lower level classes.
A : it is retained all in order.

# Does total_price directly manipulate the instance variables of other classes?

B: does not directly manipulate the instance variable s of other classes.
A: need to access the price and quantity of CartEntry class through ShoppingCart class .

# If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify?
we need to add a conditional statement when calculating the price of that entry, the price should be discounted based on the quantity.
B is easier for implementation.
since in B, order only need to know the price of ShoppingCart, don't need to know how many CartEntries that instance of ShoppingCart holds, and the price & quantity of each CartEntries. The change will only need to be made to the CartEntry class, ShoppingCart class and Order class do not need to know what happened, and no change needed to these two classes.
while in A, order need to know what happened in other two classes. order need to know how many instances of CartEntry are contained in the ShoppingCart instance, the entry unit_price and entry quantity.
Order need to access the unit_price and quantity of CartEntry class through the SHoppingCart class to decide if a bulk bought has happened, and to calculate a new total price.

# Which implementation better adheres to the single responsibility principle?
B is better

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

# What changes need to make to the design of the hotel class?
changed the Reservation.new method, to remove the reservation id from the parameters. Instead, generate the reservation id by the program.

the block_admin class is a child class of admin class, which made the design very complicated, will keep the block class, but instead of make it inherit from admin class, will make it totally independent.
184 changes: 184 additions & 0 deletions lib/admin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
require 'pry'
require 'date'
require_relative 'reservation'
require_relative 'room'
require_relative 'block_admin'

class Admin
attr_reader :reservations, :rooms, :room_unbooked_dates, :room_blocks, :start_date, :end_date

def initialize(room_id_list, start_date, end_date)
check_input_dates(start_date, end_date)
@rooms = []
@reservations = []
@room_unbooked_dates = []
@room_blocks =[]
@start_date = start_date
@end_date = end_date

room_id_list.each do |i|
room_new = create_room(i)
@rooms << room_new
start_d = start_date

while start_d < end_date

@room_unbooked_dates << {room_n: room_new, unbooked_date: start_d}
start_d += 1
end
end
end

# find availabe rooms in a given period
def find_room_available(start_date, end_date)

check_input_dates(start_date, end_date)
dates_available_rooms = []

@rooms.each do |room|
dates_needed = []
start_d = start_date

while start_d < end_date
dates_needed << {room_n: room, unbooked_date: start_d}
start_d += 1
end

if (@room_unbooked_dates & dates_needed) == dates_needed
dates_available_rooms << room
end
end
return dates_available_rooms
end

# make new reservations
def make_reservation(customer_name, start_date, end_date)

check_input_dates(start_date, end_date)
if start_date < @start_date || (end_date > @end_date)
raise ArgumentError, "can only book reservations between #{@start_date} and #{@end_date}"
end

rooms_not_booked = find_room_available(start_date, end_date)

if rooms_not_booked == []
raise ArgumentError, "No room available at this time."
else
room = rooms_not_booked.first
end

result = create_reservation(customer_name, room, start_date, end_date)
@reservations << result
start_d = start_date

while start_d < end_date
@room_unbooked_dates.reject! {|item| item == {room_n: room, unbooked_date: start_d}}
start_d += 1
end

return result
end

# create room blocks
def create_room_block(name_of_block, room_collection, start_date, end_date, discount_rate)
if discount_rate < 0 || discount_rate > 1
raise ArgumentError
end

if room_collection.nil? || room_collection == [] || room_collection.length > 5
raise ArgumentError, "room list can not be nil, empty array or more than 5 in the list"
end

if start_date.class != Date || end_date.class != Date
raise ArgumentError, "start_date and end_Date should be Date objects"
end
if start_date >= end_date
raise ArgumentError, "invlid dates entered, start_date should be ealier than end_date"
end

if start_date < @start_date || end_date > @end_date
raise ArgumentError, "start_date and end_date of room block must be in the working period"
end

available_rooms = find_room_available(start_date, end_date)
room_entered = room_collection.map {|item| find_room(item)}

if (available_rooms & room_entered) != room_entered
raise ArgumentError, "rooms are not available in given period"
else
start_d = start_date

date_list = []
while start_d < end_date
date_list << start_d
start_d += 1
end

room_date_list = []
date_list.each do |item|
room_entered.each do |r|
room_date_list << {room_n: r, unbooked_date: item}
end
end

@room_unbooked_dates = @room_unbooked_dates - room_date_list
end

new_block = create_block_admin(name_of_block,room_collection, start_date, end_date, discount_rate)
room_blocks << new_block
return new_block

end

# input a string of date, to return the list of the reservations on that date
def list_reservations(date_selected)
return @reservations.select {|reserve| reserve.dates_booked.include? date_selected}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

👍


end

# find room obj by id
def find_room(id)
raise ArgumentError, "ID cannot be blank, less than zero or more than 20. (got #{id})" if id.nil? || id <= 0 || id > 20
return @rooms.find { |room| room.room_num == id }
end

# find reservation obj by id
def find_reservation(id)

return @reservations.find {|reserve| reserve.id == id }

end

# calculate reservation cost by reservation id
def calculate_cost(reservation_id)

return find_reservation(reservation_id).reserve_cost

end

private
# check inputed start_date and end_date to make sure they are valid
def check_input_dates(start_date, end_date)
if start_date.class != Date || end_date.class != Date
raise ArgumentError, "start_date and end_Date should be Date objects"
end
if start_date >= end_date
raise ArgumentError, "invlid dates entered, start_date should be ealier than end_date"
end
end

# create new instance of reservation object
def create_reservation(customer_name, room, start_date, end_date)
return Reservation.new(customer_name, room, start_date, end_date)
end

# create new room object
def create_room(id)
return Room.new(id)
end

# create new room_block admin object
def create_block_admin(name, room_id_list, start_date, end_date, discount_rate)
return Block.new(name, room_id_list, start_date, end_date, discount_rate)
end
end
60 changes: 60 additions & 0 deletions lib/block_admin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require 'pry'
require 'date'
require_relative 'reservation'
require_relative 'room'


class Block
attr_reader :discount, :block_name, :rooms, :reservations, :start_date, :end_date, :rooms_available

def initialize(name, room_id_list, start_date, end_date, discounted_rate)
@discount = discounted_rate
@block_name = name
@rooms = []
@reservations = []
@start_date = start_date
@end_date = end_date
@rooms_available = []

room_id_list.each do |i|
room_new = create_room(i)
@rooms << room_new
@rooms_available << room_new
end
end

def calculate_cost(reservation_id)
return find_reservation(reservation_id).reserve_cost * (1 - @discount)
end

def make_reservation(customer_name)

if @rooms_available == []
raise ArgumentError, "No room available at this time."
else
room = @rooms_available.pop
end

result = create_reservation(customer_name, room, @start_date, @end_date)
@reservations << result

return result
end


private

def create_reservation(customer_name, room, start_date, end_date)
return Reservation.new(customer_name, room, start_date, end_date)
end

def create_room(id)
return Room.new(id)
end

def find_reservation(id)

return @reservations.find {|reserve| reserve.id == id }
end

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

class Reservation
attr_reader :id, :customer_name, :room, :start_date, :end_date

def initialize (customer_name,room,start_date, end_date)
if start_date >= end_date || start_date < Date.today
raise ArgumentError
else
@id = sprintf("%20.10f", Time.now.to_f).delete('.').to_i.to_s(36)
@customer_name = customer_name
@room = room
@start_date = start_date
@end_date = end_date

end
end

# list all the dates been covered in the reservation
def dates_booked
result = []
date_enter = @start_date
while date_enter < @end_date
result << date_enter
date_enter += 1
end
return result
end

# calculate the cost of the reservation
def reserve_cost
return (@end_date - @start_date) * @room.rate
end


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


class Room
attr_reader :room_num, :rate

def initialize(room_num)
if room_num.to_i > 20 || room_num.to_i < 1
raise ArgumentError
else
@room_num = room_num
@rate = 200


end
end


end
5 changes: 5 additions & 0 deletions refactor.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
refactor plan for hotel project

#1. in hotel project, I have used an array of the available room & date combinations as the instant variable in the admin class, which need to occupy lot of the space. Each time, when a reservation made, a list of the room_date combination need to be removed from the the available list, which might need a long processing time to accomplish that. To improve, I plan to change the that design . I will use the list of reservations to replace the list of the available room & date combinations. in that case, although the logic to check if a room is available on a specific period is more complicated than my original design, it might save the space and the time needed to processing.

#2 the block_admin class is a child class of admin class, which made the design very complicated, will keep the block class, but instead of make it inherit from admin class, will make it a totally independent.
Loading