forked from AdaGold/hotel
-
Notifications
You must be signed in to change notification settings - Fork 46
Laura_hotel project #40
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
Open
lauracodecreations
wants to merge
49
commits into
Ada-C10:master
Choose a base branch
from
lauracodecreations:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
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 a888ce7
calculates cost per reservation
lauracodecreations 2bb49d6
raise standard error for invalid range
lauracodecreations bfbc1f8
created instances of reservations
lauracodecreations e9885e4
sorts reservations by dates
lauracodecreations c813c55
verify that Admin is an instance of an admin
lauracodecreations baf978d
made helper methods private
lauracodecreations 7c173ff
admin can find reservations based on a date
lauracodecreations 0009d3a
administrator can check the cost of a reservation
lauracodecreations c4d82cf
admin can view rooms
lauracodecreations 5045663
wrote method to create rooms, and class for rooms
lauracodecreations 6ce551a
created spec file for room class
lauracodecreations 329707d
admin can reserve a room
lauracodecreations 0d62fb7
reserve_room converts string into computer date
lauracodecreations 79b0714
wrote create_range method
lauracodecreations fd9c9a2
removed create range it is only one line
lauracodecreations a143e43
removes status instance from room class, and added ranges instance
lauracodecreations 73f3b25
changes method from view_rooms to view_all_rooms
lauracodecreations 65ba818
binary search but range greater than target range is not possible
lauracodecreations 8fae705
admin can view vacant rooms
lauracodecreations d50ed7d
updated reserve room method to take into account vacant room but test…
lauracodecreations b91977d
made view vacant room
lauracodecreations 916f26e
rate is defaults as 200 if it is not specified
lauracodecreations b1d79f9
added create range for hotel to not count the last day
lauracodecreations 65fd636
fixed find cost method to intake a instance of a reservation
lauracodecreations 1c96e46
find reservation method does not return a reservation that has target…
lauracodecreations a0360c7
can make a reservation without checking availability
lauracodecreations 04de786
created array of dates
lauracodecreations 0ea9157
find reservations does not include the last day
lauracodecreations 04b1f1f
vacant method checks every day in the array of ranges
lauracodecreations 568f723
no rooms available for 20 reservations with the same date
lauracodecreations c6ad0c0
create block rooms
lauracodecreations 5ab322a
created test to not allow admin to create a block for more than 5 rooms
lauracodecreations 2b9fd30
sucessfuly updates status of room in a block
lauracodecreations 588787c
fixed a bug in reserve room in block and made sure that person from o…
lauracodecreations db4b3ed
method to find a block
lauracodecreations 6029c56
view vacant rooms in a block
lauracodecreations db41b55
view vacant rooms in block
lauracodecreations 4d35280
all tests work and comments for future work
lauracodecreations af35669
refactor.txt
lauracodecreations 1eba79d
range to not include last day
lauracodecreations 472c300
added refactor goal for the weekend
lauracodecreations 14c675b
single responsibility practice
lauracodecreations 961d6b2
design analysis of my hotel
lauracodecreations 007602c
added comments
lauracodecreations 0873287
evaluation of my refactor notes from weeks ago
lauracodecreations 467dd62
answered question about variable names
lauracodecreations 4d13273
finished test about bug that checked an outsider of a party can't res…
lauracodecreations 77e605c
fixed bug about an outsider of a party can't reserve a room in a block
lauracodecreations File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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? | ||
| # 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 | ||
|
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 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 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 this method instead return an empty array if there are no rooms available?