You represent a organisation of resellers scattered in urban areas scattered across the continent. Or in some cases across several continents. Your main products are high value low volume objects, normally only purchased in planned scenarios, frequently with financial packages. As customers don't make this type of purchase often, so they normally want to look at the SKU before purchase and think about it.
Due to the relative durability of your main product, and its high initial sales figure, there is a strong second hand market. Buyers definitely want to physically look at the “pre-owned” market due to the more variable goods.
As such there is a locator service, allowing potential customers visibility of SKU across the continent. The locator service was presented as a HTML web service, as it was targeted for end users. The primary organisation holds stock levels and location of each of the stock items (“you” in this article).
Outline of requirements
Under this scenario you need a process to match your buyer to the nearest occurrence of what they would like to purchase. As you are representing the entire chain, there is no favouritism between each franchise unit (otherwise the entire definition of closest starts to get contested).
Behavioural requirements :
- From the users stated location, be able to list sellers and their location (and stock).
- Comprehend a realistic range of users methods about their location (postcode, town, potentially [long,lat]).
- When the user also sets a maximum radius, filter the results by this figure.
- When the user also supplies what SKU they want (broad category, or specific models), filter results to this.
- Support a fairly standard range of sort options (price, distance, age, model name, significant attributes)
Non functional requirements :
- Respond inside a reasonable time-frame, so the user doesn't experience lag.
- Be intelligent about location (as example there are at least six towns or cities called “Christchurch”, which one did the user mean?).
- Be intelligent about national boundaries (airfreight for large volume SKU is expensive).
DiscussionThere are several mapping and route plotting service providers. The biggest are Google inc and Bing (part of Microsoft inc). The architecturally simplest means to build this would be run the routing services from the web-host. This structure would mean less trips between the client and server (so theoretically faster results). The way these are built requires code downloaded to the web-client. Its not possible to run these services on a server-side copy of Node.js.
The mapping data vendors can convert the users stated location to a [long,lat]. From a set of co-ordinates it is possible to compute distance to the stock and dealers. This isn't a trivial computation for figures in excess of fifty miles, as the planet isn't a sphere, its an ellipsoid. The following equation is the cartographers normalised solution.
var R = 6371; // km var dLat = (lat2-lat1).toRad(); var dLon = (lon2-lon1).toRad(); var lat1 = lat1.toRad(); var lat2 = lat2.toRad(); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c;
Please read, for more information
It is not sensible to push the entire stock catalogues to the client. Its commercially naive, and may be an infeasibly large amount of data. The filtering to useful SKU therefore needs to be done on the server.
The second option to computing results therefore requires the client to do communication with the GIS vendor; append location to a request for stock levels from the server. This does have small advantage that if the GIS client-side libraries need to ask for further data or permissions from the user; they have the ability to do so. The request for the stock cannot be cached, as stock will obviously be sold, and different users are in different locations. Until the user changes the description of their location, the results of the first geo-lookup may be cached. As corporate intellectual property, there was a requirement to be flexible with deployment. That is, different installations of this library, will require different communication process, and branding.
As this resource is written as a retrospective, I will state what I built:
- JS: An OO wrapper library for networking. This was a political requirement to interoperate with existing code. The calling structure was the same for the business logic layers. This was based on asynchronous callbacks.
- JS: A simple JS test harness, to allow rapid creation of many tests, and execute them. This was mostly custom code, as I needed to run mock requests on the server side. Each test was defined as a callback, and an input array.
- JS: An integration with Bing maps as a place name description to [long,lat] converter. Bing maps have quite good guessing from what you entered, but this needs to be configured.
- JS: Code to request available stock from your servers (requests include the ability to set anything in the behavioural requirements).
- Perl: Server side code to poll the database for current stock, but filter it against the maximum radius when this is supplied. Existing system used JSON as a response language.
- Perl: TAP test suite for the above.
- PHP: Use of previous locator rasteriser and HTML shell to display the results. The shell will be identical to cjddealer
- JS: The JS needed to be re-deployable into various platforms, so was a decoupled OO structure.