|
function lat_lon(thing) { |
|
return { |
|
"lat": thing.lat || thing.latitude, |
|
"lon": thing.lon || thing.longitude, |
|
} |
|
} |
|
function distance(loc1, loc2) { |
|
loc1 = lat_lon(loc1) |
|
loc2 = lat_lon(loc2) |
|
|
|
// from https://www.movable-type.co.uk/scripts/latlong.html |
|
|
|
const R = 6371e3 // meters |
|
const phi1 = loc1.lat * Math.PI/180 |
|
const phi2 = loc2.lat * Math.PI/180 |
|
const lam1 = loc1.lon * Math.PI/180 |
|
const lam2 = loc2.lon * Math.PI/180 |
|
const x = (lam2 - lam1) * Math.cos((phi1 + phi2)/2) |
|
const y = (phi2 - phi1) |
|
return Math.sqrt(x*x + y*y) * R |
|
} |
|
|
|
now = new Date() |
|
date_formatter = new DateFormatter() |
|
date_formatter.useNoDateStyle() |
|
date_formatter.useShortTimeStyle() |
|
|
|
// pull the directory of feeds |
|
let directory_url = "http://gbfs.citibikenyc.com/gbfs/gbfs.json" |
|
let directory = await new Request(directory_url).loadJSON() |
|
|
|
let feeds = directory.data.en.feeds |
|
function extract_feed(name) { |
|
return new Request(feeds.find(e => e.name == name).url).loadJSON() |
|
} |
|
|
|
// start pulling station information and status |
|
let station_information = extract_feed("station_information") |
|
let station_status = extract_feed("station_status") |
|
|
|
station_information = await station_information |
|
station_status = await station_status |
|
|
|
// turn the station status into something easier to use |
|
let station_status_by_id = new Map(station_status.data.stations.map(e => [e.station_id, e])) |
|
|
|
// where are we going? |
|
let iCloud = FileManager.iCloud() |
|
let citibike_locations_path = iCloud.bookmarkedPath("citibike-locations") |
|
await iCloud.downloadFileFromiCloud(citibike_locations_path) |
|
let citibike_locations = JSON.parse(iCloud.readString(citibike_locations_path)) |
|
let location_info = citibike_locations._target |
|
let target_location = citibike_locations[citibike_locations._target] |
|
|
|
// sort the station information bits by distance to the target |
|
station_information.data.stations.forEach(e => e.distance = distance(e, target_location)) |
|
station_information.data.stations.sort((a, b) => a.distance - b.distance) |
|
|
|
let widget = await createWidget(station_information, station_status_by_id) |
|
|
|
if (!config.runsInWidget) { |
|
await widget.presentMedium() |
|
} |
|
Script.setWidget(widget) |
|
Script.complete() |
|
|
|
function createWidget(station_information, station_status_by_id) { |
|
let w = new ListWidget() |
|
|
|
const num_lines = 6 |
|
for (let i = 0; i < num_lines; i++) { |
|
let station = station_information.data.stations[i] |
|
let status = station_status_by_id.get(station.station_id) |
|
|
|
let station_line = w.addText(`${station.name}: ${status.num_bikes_available} b, ${status.num_docks_available} d`) |
|
station_line.font = Font.systemFont(15) |
|
} |
|
|
|
w.addSpacer(null) |
|
|
|
let info_line = w.addText(`data: ${date_formatter.string(new Date(station_status.last_updated*1000))}, widget: ${date_formatter.string(now)}, target: ${location_info}`) |
|
info_line.font = Font.thinRoundedSystemFont(12) |
|
|
|
return w |
|
} |
I’m getting a error on line 49 after creating citibike location and setting target.