Skip to content

Commit

Permalink
Improve algorithm for detecting airport size
Browse files Browse the repository at this point in the history
  • Loading branch information
watson committed Dec 24, 2017
1 parent 7f2d690 commit 8bdec61
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 11 deletions.
49 changes: 39 additions & 10 deletions assets/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,21 @@

const aircraftIndex = {}
const airlineICAOIndex = {}
const airportSize = {}
const airportMarkers = []
const INITIAL_ZOOM_LEVEL = 9
const AIRPORT_VISIBILITY_THRESHOLD = [
null,
200,
150,
120,
100,
80,
60,
40,
20,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
]
const infoPanel = document.getElementById('info')
let map, selectedMarker, planeIcon, currentPosition, openInfoWindow

Expand Down Expand Up @@ -33,7 +47,7 @@ function initMap () {

// eslint-disable-next-line no-undef
map = new google.maps.Map(document.getElementById('map'), {
zoom: 9,
zoom: INITIAL_ZOOM_LEVEL,
center: currentPosition
? new google.maps.LatLng(currentPosition.lat, currentPosition.lng) // eslint-disable-line no-undef
: new google.maps.LatLng(48.9062802, 2.3598659) // eslint-disable-line no-undef
Expand All @@ -42,7 +56,9 @@ function initMap () {
map.addListener('zoom_changed', zoomLevelChanged)

onJQuery(function ($) {
$.getJSON('airports', plotAirports).fail(onAjaxError)
$.getJSON('routes', parseRoutes).fail(onAjaxError).done(function () {
$.getJSON('airports', plotAirports).fail(onAjaxError)
})
$.getJSON('airlines', parseAirlines).fail(onAjaxError)
setInterval(function () {
$.getJSON('aircrafts', plotAircrafts).fail(onAjaxError)
Expand All @@ -57,13 +73,9 @@ function onAjaxError (jqXHR, textStatus, err) {
function zoomLevelChanged () {
const level = map.getZoom()
airportMarkers.forEach(function (marker) {
let visible = true
if (level >= 6 && level <= 7) {
visible = !!marker.airport.IATA
} else if (level < 6) {
visible = false
}
marker.setVisible(visible)
const size = airportSize[marker.airport.IATA]
const threshold = AIRPORT_VISIBILITY_THRESHOLD[level]
marker.setVisible(threshold ? size > threshold : true)
})
}

Expand All @@ -73,6 +85,20 @@ function parseAirlines (airlines) {
})
}

function parseRoutes (routes) {
routes.forEach(function (route) {
tickAirport(route.source)
tickAirport(route.dest)
})
}

// Keep a record of how many routes fly to and from a given airport.
// This helps us know how big an airport is.
function tickAirport (IATA) {
if (!airportSize[IATA]) airportSize[IATA] = 1
else airportSize[IATA]++
}

function plotAirports (airports) {
const airportIcon = {
path: 'M182.9,551.7c0,0.1,0.2,0.3,0.2,0.3S358.3,283,358.3,194.6c0-130.1-88.8-186.7-175.4-186.9 C96.3,7.9,7.5,64.5,7.5,194.6c0,88.4,175.3,357.4,175.3,357.4S182.9,551.7,182.9,551.7z M122.2,187.2c0-33.6,27.2-60.8,60.8-60.8 c33.6,0,60.8,27.2,60.8,60.8S216.5,248,182.9,248C149.4,248,122.2,220.8,122.2,187.2z',
Expand All @@ -81,14 +107,17 @@ function plotAirports (airports) {
fillOpacity: 1,
scale: 0.03
}
const visibilityThreshold = AIRPORT_VISIBILITY_THRESHOLD[INITIAL_ZOOM_LEVEL]

airports.forEach(function (airport) {
const size = airportSize[airport.IATA]
// eslint-disable-next-line no-undef
const marker = new google.maps.Marker({
position: {lat: airport.lat, lng: airport.lng},
map: map,
title: airport.name,
icon: airportIcon
icon: airportIcon,
visible: visibilityThreshold ? size > visibilityThreshold : true
})
marker.airport = airport
// eslint-disable-next-line no-undef
Expand Down
29 changes: 29 additions & 0 deletions lib/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,35 @@ exports.airports = function (req, res) {
})
}

exports.routes = function (req, res) {
let first = true
res.setHeader('Content-Type', 'application/json')

fs.createReadStream(path.join(__dirname, '..', 'data', 'routes.csv'))
.pipe(csv(['airline', 'airlineId', 'source', 'sourceId', 'dest', 'destId', 'codeshare', 'stops', 'equipment']))
.on('error', function (err) {
console.error(err.stack)
if (first) res.writeHead(500)
res.end()
})
.on('data', function (row) {
Object.keys(row).forEach(function (key) {
if (row[key] === '\\N') row[key] = null
})
row.airlineId = Number.parseInt(row.airlineId, 10)
row.sourceId = Number.parseInt(row.sourceId, 10)
row.destId = Number.parseInt(row.destId, 10)
row.codeshare = row.codeshare === 'Y'
row.stops = Number.parseInt(row.stops, 10)

res.write((first ? '[\n' : ',') + JSON.stringify(row) + '\n')
first = false
})
.on('end', function () {
res.end(']')
})
}

exports.aircrafts = function (req, res) {
const aircrafts = store
.getAircrafts()
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
"standard": "^10.0.3"
},
"scripts": {
"data": "npm run data-airlines && npm run data-airports",
"data": "npm run data-airlines && npm run data-airports && npm run data-routes",
"data-airlines": "mkdir -p data && curl -o data/airlines.csv https://raw.githubusercontent.com/jpatokal/openflights/master/data/airlines.dat",
"data-airports": "mkdir -p data && curl -o data/airports.csv https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat",
"data-routes": "mkdir -p data && curl -o data/routes.csv https://raw.githubusercontent.com/jpatokal/openflights/master/data/routes.dat",
"postinstall": "npm run data",
"test": "standard"
},
Expand Down
1 change: 1 addition & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ patterns.add('GET /', routes.index)
patterns.add('GET /assets/{file}', routes.assets)
patterns.add('GET /airlines', routes.airlines)
patterns.add('GET /airports', routes.airports)
patterns.add('GET /routes', routes.routes)
patterns.add('GET /aircrafts', routes.aircrafts)

const server = http.createServer(function (req, res) {
Expand Down

0 comments on commit 8bdec61

Please sign in to comment.