Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
7d8109c
calculates number of nights
lauracodecreations Sep 4, 2018
a888ce7
calculates cost per reservation
lauracodecreations Sep 4, 2018
2bb49d6
raise standard error for invalid range
lauracodecreations Sep 4, 2018
bfbc1f8
created instances of reservations
lauracodecreations Sep 5, 2018
e9885e4
sorts reservations by dates
lauracodecreations Sep 5, 2018
c813c55
verify that Admin is an instance of an admin
lauracodecreations Sep 5, 2018
baf978d
made helper methods private
lauracodecreations Sep 5, 2018
7c173ff
admin can find reservations based on a date
lauracodecreations Sep 6, 2018
0009d3a
administrator can check the cost of a reservation
lauracodecreations Sep 6, 2018
c4d82cf
admin can view rooms
lauracodecreations Sep 6, 2018
5045663
wrote method to create rooms, and class for rooms
lauracodecreations Sep 6, 2018
6ce551a
created spec file for room class
lauracodecreations Sep 6, 2018
329707d
admin can reserve a room
lauracodecreations Sep 6, 2018
0d62fb7
reserve_room converts string into computer date
lauracodecreations Sep 6, 2018
79b0714
wrote create_range method
lauracodecreations Sep 6, 2018
fd9c9a2
removed create range it is only one line
lauracodecreations Sep 6, 2018
a143e43
removes status instance from room class, and added ranges instance
lauracodecreations Sep 7, 2018
73f3b25
changes method from view_rooms to view_all_rooms
lauracodecreations Sep 7, 2018
65ba818
binary search but range greater than target range is not possible
lauracodecreations Sep 7, 2018
8fae705
admin can view vacant rooms
lauracodecreations Sep 7, 2018
d50ed7d
updated reserve room method to take into account vacant room but test…
lauracodecreations Sep 7, 2018
b91977d
made view vacant room
lauracodecreations Sep 7, 2018
916f26e
rate is defaults as 200 if it is not specified
lauracodecreations Sep 7, 2018
b1d79f9
added create range for hotel to not count the last day
lauracodecreations Sep 7, 2018
65fd636
fixed find cost method to intake a instance of a reservation
lauracodecreations Sep 7, 2018
1c96e46
find reservation method does not return a reservation that has target…
lauracodecreations Sep 7, 2018
a0360c7
can make a reservation without checking availability
lauracodecreations Sep 7, 2018
04de786
created array of dates
lauracodecreations Sep 7, 2018
0ea9157
find reservations does not include the last day
lauracodecreations Sep 8, 2018
04b1f1f
vacant method checks every day in the array of ranges
lauracodecreations Sep 8, 2018
568f723
no rooms available for 20 reservations with the same date
lauracodecreations Sep 10, 2018
c6ad0c0
create block rooms
lauracodecreations Sep 10, 2018
5ab322a
created test to not allow admin to create a block for more than 5 rooms
lauracodecreations Sep 10, 2018
2b9fd30
sucessfuly updates status of room in a block
lauracodecreations Sep 10, 2018
588787c
fixed a bug in reserve room in block and made sure that person from o…
lauracodecreations Sep 10, 2018
db4b3ed
method to find a block
lauracodecreations Sep 10, 2018
6029c56
view vacant rooms in a block
lauracodecreations Sep 10, 2018
db41b55
view vacant rooms in block
lauracodecreations Sep 10, 2018
4d35280
all tests work and comments for future work
lauracodecreations Sep 10, 2018
af35669
refactor.txt
lauracodecreations Sep 10, 2018
1eba79d
range to not include last day
lauracodecreations Sep 12, 2018
472c300
added refactor goal for the weekend
lauracodecreations Sep 20, 2018
14c675b
single responsibility practice
lauracodecreations Sep 30, 2018
961d6b2
design analysis of my hotel
lauracodecreations Sep 30, 2018
007602c
added comments
lauracodecreations Sep 30, 2018
0873287
evaluation of my refactor notes from weeks ago
lauracodecreations Sep 30, 2018
467dd62
answered question about variable names
lauracodecreations Sep 30, 2018
4d13273
finished test about bug that checked an outsider of a party can't res…
lauracodecreations Sep 30, 2018
77e605c
fixed bug about an outsider of a party can't reserve a room in a block
lauracodecreations Sep 30, 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
55 changes: 55 additions & 0 deletions design-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# What classes does each implementation include? Are the lists the same?
IMPLEMENTATION A includes the CartEntry class, the ShoppingCart class, and the Order class

IMPLEMENTATION B includes the CartEntry class, the ShoppingCart class, and the Order class
The both have the same classes' names
# Write down a sentence to describe each class.
CartEntry class initializes a instance of an entry, it has price of the entry and the quantity of this entry
ShoppingCart class initializes an instance of a Cart, it has the an array of entries
The Order class calculates the total cost for the entries in the cart
# How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper.
IMPLEMENTATION A: The Order class depends on the ShoppingCart class to create the cart with an entries array. The Order class, calculates the total price for all entries in the cart.

IMPLEMENTATION B: The Order class depends on the ShoppingCart class to create the cart with an entries array. The ShoppingCart class calculates the price for all the items in the cart
# What data does each class store? How (if at all) does this differ between the two implementations?
IMPLEMENTATION A:
CartEntry stores unit price and quantity of an entry
ShoppingCart stores all the entries in an array
Order stores the cart that contains all the entries

IMPLEMENTATION B:
CartEntry stores the unit price and quantity of an entry
ShoppingCart stores the all the entries in an array
Order stores the cart that contains all the entries
This does not differ between the two implementations

#What methods does each class have? How (if at all) does this differ between the two implementations?
IMPLEMENTATION A:
CartEntry: no methods
ShoppingCart: no methods
Order: total_price method to calculate the price for each entry, the price for all entries, and the total price including tax

IMPLEMENTATION B:
CartEntry: price method to calculate the price for the entry (quantity and unit price)
ShoppingCart: price method to calculate total price for the cart (all entries)
Order: total price method to calculate the total price including tax

#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?
#Does total_price directly manipulate the instance variables of other classes?
IMPLEMENTATION A: It's retained in Order
total_price directly manipulate instance variables of other classes (it calls the unit price and quantity instance variables from the Cart Entry, and the entries instance variable from the ShoppingCart class)

IMPLEMENTATION B: It computes the price delegated to "lower lever" classes. The computes the total cost by applying the tax.
total_price doesn't directly manipulate instance variables of other classes (it calls the price method, but it is not an instance variable)

#If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify?
IMPLEMENTATION A: you will have to add an if statement in the do loop to calculate a discount if entry.quantity is of a certain number before adding it to the sum variable

IMPLEMENTATION B: you will need to change the price method in the CartEntry class by calculating a discount if quantity is of certain items.

IMPLEMENTATION B is easier to modify
#Which implementation better adheres to the single responsibility principle?
IMPLEMENTATION B because code that reads or modifies the instance variables of a class is wrapped in a method of that class
#Bonus question once you've read Metz ch. 3: Which implementation is more loosely coupled?
IMPLEMENTATION B is more loosely coupled because code that reads or modifies the instance variables of a class is wrapped in an instance method on that class.
36 changes: 36 additions & 0 deletions design-analysis-of-my-hotel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#What is this class's responsibility?
ROOM class: it keeps track of the rooms are reserved in a block reservation or in a regular reservation
Behaviors:
-it adds the range to the instance variable range
-it adds the block to the instance variable block
-it adds the reservation status of "booked" to the block variable instance

RESERVATION class: it calculates cost of a reservation by creating instance variables

ADMIN class: It holds the rooms and the reservations, checks if rooms are available for block reservations or regular reservations, and provides views for current reservations.
Behaviors:
-it creates the rooms instances
-it creates the reservation instances
-it reserves a room by calling the methods in the ROOM class
-it views vacant rooms by reading the instance variable "ranges" of the ROOM class ---improve here
-it views all the rooms by reading it's instance variable: rooms
-it finds a reservation by reading it's instance variable: reservation
-it finds the cost of a reservation by reading the instance variable of the RESERVATION class.
-it creates a block of rooms, by modifying the block instance variable of the ROOM class --- improve here
-it finds vacant rooms available for a block by reading the instance variable, ranges, of the ROOM class --- improve here
-it reserves a room in a block by modifying the block instance variable of the ROOM class --- improve here

#Is this class responsible for exactly one thing?
ROOM class: not sure. I think no because it keeps track of blocks and regular reservation, and reserves rooms; but it doesn't change the instance variable of other classes so it is loosely coupled.
RESERVATION class: yes
ADMIN class: no (it checks if two reservations clashes before calling the reservation method in the ROOM class)

#Does this class take on any responsibility that should be delegated to "lower level" classes?
ROOM class: no
RESERVATION class: no
ADMIN class: yes, viewing vacant rooms should be moved to the ROOM class, creating a block of rooms should be moved to the ROOM class, and reserving a room should be move to the ROOM class

#Is there code in other classes that directly manipulates this class's instance variables?
ROOM class: yes, range and block are modified by methods in the ADMIN class (create block of rooms, and reserve a room)
RESERVATION class: no
ADMIN: no
277 changes: 277 additions & 0 deletions lib/admin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
require 'csv'
require 'pry'

#REFACTOR_IDEAS:
# create helper method that creates instance of time, and a range

class Admin
attr_reader :reservations, :find_reservation, :rooms, :vacant_rooms, :booked_rooms
def initialize
@reservations = load_reservations('spec/test_data/test_reservation.csv')
@rooms = create_rooms(20)
sort_reservations
end

def create_rooms(number)
rooms = []
number.times do |num|
input_data = {}
room_number = num + 1
input_data[:number] = room_number
rooms << Room.new(input_data)
end
return rooms
end

def load_reservations(filename)
reservations = []

CSV.read(filename, headers: true).each do |line|
data = line.to_h
input_data = {}
input_data[:id] = data["id"].to_i
input_data[:start_time] = Time.parse(data["start_time"])
input_data[:end_time] = Time.parse(data["end_time"]) # no need to subtract last day because reservation class only calculates cost
# REFACTOR idea: make the reservation instance a separate method - isolating dependencies
reservations << Reservation.new(input_data)
end

return reservations
end

#As an administrator, I can reserve a room for a given date range
# uses view_vacant_rooms create range with one day less
def reserve_room(start_date, end_date)
start_date = Time.parse(start_date)
end_date = Time.parse(end_date)
range = create_hotel_range(start_date, end_date) # for hotel
e_date = end_date - 1 # rooms do not keep track of last night
vacant_rooms = view_vacant_rooms(start_date, e_date)
if vacant_rooms.nil?

Choose a reason for hiding this comment

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

Shouldn't this method instead return an empty array if there are no rooms available?

# REFACTOR idea: begin rescue block, exception handleing
raise StandardError, "no rooms are available"
else
room = vacant_rooms.first
room.add_range(range)
input_data = {}
input_data[:start_time] = start_date
input_data[:end_time] = end_date
input_data[:room_num] = room.number
reservations << Reservation.new(input_data)
end
end

#As an administrator, I can view a list of rooms that are not reserved for a given date range
## expects dates to be instances of time
def view_vacant_rooms(start_date, end_date)
# I am editing the rooms! it's not making a copy
# I am just creating a new pointer that points to the same data as what rooms points to
vacant_rooms = @rooms
target_range = create_hotel_range(start_date, end_date)
vacant_rooms.each do |room|
ranges = room.ranges
ranges.each do |range|
# nil means no intersection
if intersection(target_range, range) != nil # there was a overlap
vacant_rooms.delete(room)
break # where does this go? it goes to the next room, if one range conflicts, I do not have to check if the others conflicts
end
end
end


# remove rooms that have a block in them
vacant_rooms_result = vacant_rooms.select do | room |
if room.blocks.empty?
room.blocks.empty?
else
intersection(target_range, room.blocks.first[:range]) == nil
end
end

return vacant_rooms_result

# QUEstion for later: how come this does not work without using select: Can't escape from eval with next

# vacant_rooms.each do |room|
# if room.blocks.empty? == false
# if intersection(target_range, room.blocks.first[:range]) != nil # there was a overlap
# vacant_rooms.delete(room)
# end
# else # it does not have a block
# next # go to the next room
# end
# end
end

# As an administrator, I can access the list of all of the rooms in the hotel
def view_all_rooms
return @rooms
end

#As an administrator, I can access the list of reservations for a specific date
# I do not have to return a reservation that has specific date at the end
# In my program, the reservations have real checkout date
# In my program, the room class have real dates, not including the last check out date
# REFACTOR idea: to keep take out -1 day when you load reservation, but reservations calculates the cost based of nights - I wil have to fix that too
def find_reservations(date)
date = Time.parse(date)
reservations = @reservations.select do |instance|
start_date = instance.start_time
end_date = instance.end_time
end_date = end_date - 1
if date_in_range(start_date, end_date, date)
instance
end
end
return reservations
end

#As an administrator, I can get the total cost for a given reservation
#input is a reservation instance
def find_cost(reservation)
cost = reservation.cost
return cost
end

#As an administrator, I can create a block of rooms
def create_block_rooms(data)
start_date = Time.parse(data[:start_date])
end_date = Time.parse(data[:end_date])
e_date = end_date - 1
range = (start_date..e_date)
rooms = data[:rooms]
raise StandardError if rooms > 5 #max block size
discounted_rate = data[:discounted_rate]
# view vacant_rooms - current method
available_rooms = view_vacant_rooms_for_blocks(start_date, e_date)

if available_rooms.length < rooms
return "no available rooms for block"
else
max = rooms - 1 # because of the 0 index
block_rooms = available_rooms[0 .. max]
input_data = {}
input_data[:discounted_rate] = discounted_rate
input_data[:range] = range
input_data[:status] = "available"
block_rooms.each do |room|
room.add_block(input_data)
end
end
end

def view_vacant_rooms_for_blocks(start_date, end_date)
vacant_rooms = @rooms
target_range = create_hotel_range(start_date, end_date)
vacant_rooms.each do |room|
ranges = room.ranges
blocks = room.blocks
ranges.each do |range|
# nil means no intersection
if intersection(target_range, range) != nil # there was a overlap
vacant_rooms.delete(room)
break
end
end
blocks.each do |block|
# nil means no intersection
if intersection(target_range, blocks[:range]) != nil # there was a overlap
vacant_rooms.delete(room)
break
end
end
end
return vacant_rooms
end

# As an administrator, I can reserve a room from within a block of rooms
def reserve_room_in_block(data)
room_num = data[:room_num]
range = data[:range]
room = @rooms.select { |room| room.number == room_num}[0]
room.reserve_room_block(range)
### FUTURE WORK: 1. use method view_vacant_rooms_in_block before making a reservation
# => 2. create isntance of reservation
end

# As an administrator, I can check whether a given block has any rooms available
def view_vacant_rooms_in_block(range)
available_rooms = []
block_rooms = find_block(range)
block_rooms.each do |room|
#blocks variable is an array
blocks = room.blocks
blocks.each do |block|
if block[:status] == "available"
available_rooms << room
end
end
end
return available_rooms
end
# it is used in view_vacant_rooms_in_block method
def find_block(range)
#find block
rooms_with_blocks = @rooms.select { |room| room.blocks.empty? == false}
#blocks variable are an array
block_set = []
rooms_with_blocks.each do |room|
blocks = room.blocks
blocks.each do |block|
if block[:range] == range
block_set << room
end
end
end
end

#last day not counted
#expect input to be time instances
def create_hotel_range(start_date, end_date)
end_date = end_date - 1
range = (start_date .. end_date)
return range
end

# expects input to be time instances
def create_array_of_dates(start_date, end_date)
dates = []
difference = end_date - start_date
difference = difference/86400
difference.to_i.times do |i|
dates << start_date + (1+i)
end
return dates
end

private

Choose a reason for hiding this comment

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

Good that you're using private methods.

#never used currently
def sort_reservations
@reservations.sort_by { |object| object.start_time }
end

def intersection(range, range2)
if (range.max < range2.begin or range2.max < range.begin)
return nil
else
return [range.begin, range2.begin].max..[range.max, range2.max].min
end
end

def date_in_range(start_date, end_date, date)
range = (start_date .. end_date)
range.include?(date)
end

# find range in an array of ranges,
#NOT USEFUL you need to check every day in the range not just that the ranges are not equal
def range_search(ranges, target)
ranges.each do |range|
if range == target
return true
end
end
return false
end
end
16 changes: 16 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# the roal of this class is to calculate cost of a reservation, and check for invalid range
class Reservation
attr_reader :start_time, :end_time, :nights, :cost, :reservations, :id, :room_num

def initialize(data)
#@id = data[:id] || 0
@start_time = data[:start_time]
@end_time = data[:end_time]
@room_num = data[:room_num] || 0
sec = @end_time - @start_time
@nights = sec.to_i / 86400
rate = 200 if data[:rate].nil?
@cost = @nights * rate
raise StandardError if sec < 0 #invalid range
end
end
Loading