congressional-district-finder
v0.2.0
Published
a node module for finding a congressional district based on latitude and longitude
Downloads
19
Maintainers
Readme
Congressional District Finder
A small library of functions for determining US Congressional representation based on location.
Fetches and parses data from:
- https://github.com/unitedstates/districts/
- http://www.house.gov/
- http://maps.googleapis.com/maps/api/geocode/json
And uses geolib to determine if a given latitude or longitude resides in a state or district's geoJSON boundaries.
None of these require API tokens but getDistricts fetches from the Github Contents API, which rate-limits unauthenticated requests to 60 per hour from a given IP.
Requirements
Requires NodeJS version 4 or greater.
Installation
$ npm install congressional-district-finder --save
Usage
All methods return promises, using Request-Promise-Native for various http GET requests.
Get a District by Latitude and Longitude
var finder = require('congressional-district-finder');
finder.getDistrictByLatLng(40.718031, -73.9583047)
.then(function(result) {
console.log(result.isMatched); // outputs true
console.log(result.district.name); //outputs "New York 12th"
console.log(result.district.districtCode); //outputs "NY-12"
});
If coordinates are outside the US:
finder.getDistrictByLatLng(31.6538179, -106.5890206)
.catch(function(err) {
console.log(err.message);
// Outputs:
// "The specified latitude: 31.6538179 and longitude: -106.5890206
// are for the country: MX. To Find a Congressional District,
// please provide coordinates in the US."
});
Get a District by Address
finder.getDistrictByAddress('45 Main Street Brooklyn')
.then(function(result) {
console.log(result.isMatched); // outputs true
console.log(result.district.name); //outputs "New York 7th"
console.log(result.district.districtCode); //outputs "NY-07"
});
If the address is too vague:
finder.getDistrictByAddress('Pittsburgh, PA')
.catch(function (err) {
console.log(err.statusCode); //outputs 400
console.log(err.message);
// Outputs:
// "The specified address: ''Pittsburgh, PA'' appears to be too vague.
// Try including a street name and number."
});
If the address is outside the US:
finder.getDistrictByAddress('3895 Boulevard St-Laurent, Montreal')
.catch(function (err) {
console.log(err.statusCode); //outputs 404
console.log(err.message);
// Outputs:
// "The specified address: '3895 Boulevard St-Laurent, Montreal'
// appears to be from the country: CA. To find a Congressional District,
// please provide coordinates in the US. More specific coordinates might also work."
});
Handling the 404 for DC and Puerto Rico's At-Large Districts
Currently the repository of GeoJSON for 2016 congressional districts doesn't contain a district shape for DC's at-large district (DC-0 or DC-AL). To handle this situation, you can check the message on a 404 response against the template used to format the message for this particular error.
finder.getDistrictByAddress('1600 Pennsylvania Avenue DC')
.catch(function(err) {
if (err.message === finder.DISTRICT_NOT_FOUND('DC-0')) {
throw new Error('Taxation without representation.');
}
throw err;
})
.catch(function(err) {
console.log(err.message); // Outputs: "Taxation without representation."
});
Since DC is an at-large district, it's safe to assume that the provided coordinates reside in this district.
Likewise, because it's a territory, Puerto Rico will also throw a 404. While Puerto Rico's at-large district is also missing from the 2016 GEOJson repo, this particular error is thrown because it doesn't reside in the US. It can be detected and handled as such:
var address = 'San Juan, Puerto Rico';
finder.getDistrictByAddress(address)
.catch(function(err) {
if (err.statusCode != 404) {
throw err;
}
switch (err.message) {
case finder.ADDRESS_OUTSIDE_US(address, 'PR') :
return Promise.resolve({
district: {
districtCode: 'PR-AL',
name: 'Puerto Rico At-Large'
}
});
default:
throw err;
}
})
.then(function(result) {
console.log(result.district.name); // Outputs "Puerto Rico At-Large"
});
Error templates are also exported for COORDS_OUTSIDE_US: 404, and ADDRESS_TOO_VAGUE: 400.
Other Methods
Get a List of All US Congressional Districts
finder.getDistricts()
.then(function(result) {
console.log(result.districts.length); // outputs all 435 US Congressional Districts
console.log(result.districts[0]);// outputs AK-0
console.log(result.districts[434]);// outputs WY-0
});
Note that this particular method uses the Github Contents API Without Github API auth credentials, you are limited to 60 requests per hour from a given IP. If your application will likely exceed this, you can do the following:
- Increase your rate limit by passing auth credentials via the customHeaders.
- Cache the result and verify that it's up to date by passing an etag or last modified time stamp.
var districts, myCachedEtag = '"36bac568759f240e06955cf597493555"';
finder.getDistricts({'If-None-Match': myCachedEtag})
.then(function(result) {
//update your cached etag and cached list of districts
myCachedEtag = result.headers.etag;
districts = result.districts;
console.log(myCachedEtag);
})
.catch(function(err) {
if (err.statusCode === 304) {
console.log('just use your cached districts.');
}
});
Read more about Github's rate limit rules.
Check Coordinates Against a State
- fetches GEOJson from github/unitedstates
- parses and checks the coordinates using geolib
var lat = 40.718031;
var lng = -73.9583047;
finder.checkLatLngInState(lat, lng, 'NY')
.then(function(result) {
console.log('Check coordinates in New York...');
console.log(result); // outputs { isMatched: true, stateId: 'NY', latitude: 40.718031, longitude: -73.9583047 }
});
finder.checkLatLngInState(lat, lng, 'CT')
.then(function(result) {
console.log('Check coordinates in Connecticut...');
console.log(result); // outputs {isMatched: false, stateId: 'CT',latitude: 40.718031, ongitude: -73.9583047 }
});
Check Coordinates Against a District
- fetches GEOJson from github/unitedstates
- parses and checks the coordinates using geolib
var honolulu = {latitude: 21.3069, longitude: -157.8583};
finder.checkLatLngInDistrict(honolulu.latitude, honolulu.longitude, 'HI-1')
.then(function(result) {
console.log(result.districtId); // outputs HI-1
console.log(result.district.districtCode); // outputs HI-01
console.log(result.district.name); // outputs Hawaii 1st
console.log(result.isMatched); // outputs true
console.log('-');
});
finder.checkLatLngInDistrict(honolulu.latitude, honolulu.longitude, 'HI-2')
.then(function(result) {
console.log(result.districtId); // outputs HI-2
console.log(result.district.districtCode); // outputs HI-02
console.log(result.district.name); // outputs Hawaii 2nd
console.log(result.isMatched); // outputs false
console.log('-');
});
Tests
$ npm test
Contributing
Code is transpiled from ES6/ES2015. You can lint code by running:
$ npm run lint