Availability Service
This module consists of a class that has one main method, checkAvailability()
. This method accepts a start date and an end date as strings formatted like 'YYYY-MM-DD'
, along with an array of reservation objects, formatted like:
{"campsiteId": 1, "startDate": "2016-06-01", "endDate": "2016-06-04"}
The method will check to see which sites, identified by 'campsiteId'
, have openings for the requested dates, taking the gap rules into consideration.
Gap Rules
To eliminate or minimize un-booked sites, site owners utilize "Gap Rules" which enforce a maximum number of days unbooked between reservations. To illustrate, consider a site that has existing reservations spanning the 1st through the 3rd of the month and the 10th through the 15th. If a gap rule exists that states the maximum gap is 2 days, a request for a reservation spanning the 4th through the 7th would be denied, because the gap between the 7th and the 10th violates the rule.
High-Level Approach
My approach for this challenge centered around implementing the solution in a manner that allowed easy reuse and high cohesion. I chose to create a module that would implement the functionality in either a server environment or in the browser. To accomplish this, I wrote the module as an ES2015 module, and then transpiled it using Babel and the babel-plugin-add-module-exports
plugin to allow it to be used with require()
or import
.
To support a more effective workflow, I set up a CI workflow using CircleCI which automatically builds the module and runs the tests each time a commit is pushed to master. The badge at the top of this page illustrates the current build status. This process could be improved by enforcing a rule that the CI build must pass successfully before commits are allowed to be merged into the master branch.
To make it easier for other applications to use this module as a dependency, I've published it on npm. This makes it easy for other applications to easily include it using npm install availability-service
and to require that specific versions be used. Details of the example API are provided below.
The processing of the reservation list to determine availability follows four main steps:
- Remove any reservation objects that contain a reservation which overlaps the requested date range
- Remove all reservation objects that relate to a site that has an overlapping reservation (in a different reservation object)
-
Parse the remaining reservations into a format like:
{ campsiteId: 1, reservations: [ [startDate1, endDate1], [startDate2, endDate2], [startDate3, endDate3] ] }
Calculate the gap between each reservation in the reservations array above, and calculate if the requested range will fit without violating the gap rules.
Assumptions
When determining how to solve this problem, I made the following assumptions:
- The gap rule value was to be used in an inclusive comparison. In other words, if the gap rule is 2, that means that the difference between the end of one reservation and the beginning of another must be less than or equal to 2, rather than less than 2.
- If there's more than one gap rule, the smallest rule takes precedence.
- The gap rules before and after the requested range must be calculated.
- If there's no reservation before a requested range or there's not one after it, there's no need to calculate the gap rule for that span.
Dependencies
To speed development time, I used the popular moment.js library to extend the Date
object, and the moment-range library to provide additional methods for calculating date ranges.
Building and Running Tests
-
npm run build
- produces production version of your library under thelib
folder -
npm run test
- You'll never believe what it does! -
npm run test:watch
- re-run tests as you make changes
Example Implementation
To provide an example implementation, I created a Loopback API that exposes a route, /reservations/availability
. This route is available for POST
requests only, and requires two params: startDate
and endDate
. It returns a JSON collection of campsite objects that have availability for that date range.
To run the api, simply follow these steps:
- Clone or download a copy of campspot-api
- Edit
./server/datasources.json
and enter your credentials for a MySQL database and a database that you'd like to use for testing - Run
npm install
to install the dependencies (including this one, availability-service) - Run
node .
to start the server in a terminal session. This will create a database migration with the data from the provided JSON document (located in the file./server/boot/test-case.js
) - Navigate to http://localhost:3000/explorer/#!/Reservation/Reservation_availability and enter the dates '2016-06-07' and '2016-06-10' in the provided text input fields, then submit.
-
Inspect the response body. You should see the following JSON object:
{ "startDate": "2016-06-07", "endDate": "2016-06-10", "available_sites": [ { "name": "Daniel Boone Bungalow", "id": 5 }, { "name": "Teddy Rosevelt Tent Site", "id": 6 }, { "name": "Bear Grylls Cozy Cave", "id": 8 }, { "name": "Wyatt Earp Corral", "id": 9 } ] }
Conclusion
Thank you again for the opportunity. Please feel free to contact me if you have any additional questions or comments.