/**
* @function getWeatherForecast
* @summary
* Get the Weather Forecst from API.WEATHER.GOV
* @description
* Uses the zip code in the Ad Parameters (adParameters.geoInfo.postalCode) to
* 1. Get the Lat/Lon from pterodactlyus (or raptor) centered on the zip code
* 2. Make an asynchronous call to API.WEATHER.GOV for the weather forecast at the LAT/LON
* 3. Emits an event 'WEATHER_FORECAST_RESULTS' when the data is received
* 4. Returns a JavaScript Promise when can be used as an alternative way to receive data or catch an error
* 5. The zip code from the Ad Parameters can be superceded by passing in options.zipCode
*
* Example Usage:
* ```
* window.$b.snippets.getWeatherForecast()
* window.$b.on('WEATHER_FORECAST_RESULTS', function (data) {
* if (data.periods) {
* data.periods.forEach(function (period) {
* console.log(period.name + ': ' + period.shortForecast)
* console.log(period.detailedForecast)
* })
* }
* }
* ```
* Example of data object returned:
* ```
* {
* "updated": "2018-09-06T23:47:02+00:00",
* "units": "us",
* "forecastGenerator": "BaselineForecastGenerator",
* "generatedAt": "2018-09-07T01:30:36+00:00",
* "updateTime": "2018-09-06T23:47:02+00:00",
* "validTimes": "2018-09-06T17:00:00+00:00/P7DT20H",
* "elevation": {
* "value": 39.9288,
* "unitCode": "unit:m"
* },
* "periods": [
* {
* "number": 1,
* "name": "Tonight",
* "startTime": "2018-09-06T18:00:00-07:00",
* "endTime": "2018-09-07T06:00:00-07:00",
* "isDaytime": false,
* "temperature": 54,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "7 to 18 mph",
* "windDirection": "WSW",
* "icon": "https://api.weather.gov/icons/land/night/bkn?size=medium",
* "shortForecast": "Mostly Cloudy",
* "detailedForecast": "Mostly cloudy, with a low around 54. West southwest wind 7 to 18 mph, with gusts as high as 24 mph."
* },
* {
* "number": 2,
* "name": "Friday",
* "startTime": "2018-09-07T06:00:00-07:00",
* "endTime": "2018-09-07T18:00:00-07:00",
* "isDaytime": true,
* "temperature": 70,
* "temperatureUnit": "F",
* "temperatureTrend": "falling",
* "windSpeed": "7 to 18 mph",
* "windDirection": "WSW",
* "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
* "shortForecast": "Mostly Sunny",
* "detailedForecast": "Mostly sunny. High near 70, with temperatures falling to around 65 in the afternoon. West southwest wind 7 to 18 mph, with gusts as high as 25 mph."
* },
* {
* "number": 3,
* "name": "Friday Night",
* "startTime": "2018-09-07T18:00:00-07:00",
* "endTime": "2018-09-08T06:00:00-07:00",
* "isDaytime": false,
* "temperature": 55,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "9 to 18 mph",
* "windDirection": "WSW",
* "icon": "https://api.weather.gov/icons/land/night/bkn?size=medium",
* "shortForecast": "Mostly Cloudy",
* "detailedForecast": "Mostly cloudy, with a low around 55. West southwest wind 9 to 18 mph, with gusts as high as 24 mph."
* },
* {
* "number": 4,
* "name": "Saturday",
* "startTime": "2018-09-08T06:00:00-07:00",
* "endTime": "2018-09-08T18:00:00-07:00",
* "isDaytime": true,
* "temperature": 68,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "9 to 16 mph",
* "windDirection": "WSW",
* "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
* "shortForecast": "Mostly Sunny",
* "detailedForecast": "Mostly sunny, with a high near 68. West southwest wind 9 to 16 mph, with gusts as high as 22 mph."
* },
* {
* "number": 5,
* "name": "Saturday Night",
* "startTime": "2018-09-08T18:00:00-07:00",
* "endTime": "2018-09-09T06:00:00-07:00",
* "isDaytime": false,
* "temperature": 54,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "5 to 16 mph",
* "windDirection": "WSW",
* "icon": "https://api.weather.gov/icons/land/night/bkn?size=medium",
* "shortForecast": "Mostly Cloudy",
* "detailedForecast": "Mostly cloudy, with a low around 54. West southwest wind 5 to 16 mph, with gusts as high as 22 mph."
* },
* {
* "number": 6,
* "name": "Sunday",
* "startTime": "2018-09-09T06:00:00-07:00",
* "endTime": "2018-09-09T18:00:00-07:00",
* "isDaytime": true,
* "temperature": 66,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "5 to 14 mph",
* "windDirection": "W",
* "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
* "shortForecast": "Mostly Sunny",
* "detailedForecast": "Mostly sunny, with a high near 66."
* },
* {
* "number": 7,
* "name": "Sunday Night",
* "startTime": "2018-09-09T18:00:00-07:00",
* "endTime": "2018-09-10T06:00:00-07:00",
* "isDaytime": false,
* "temperature": 54,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "8 to 14 mph",
* "windDirection": "W",
* "icon": "https://api.weather.gov/icons/land/night/sct?size=medium",
* "shortForecast": "Partly Cloudy",
* "detailedForecast": "Partly cloudy, with a low around 54."
* },
* {
* "number": 8,
* "name": "Monday",
* "startTime": "2018-09-10T06:00:00-07:00",
* "endTime": "2018-09-10T18:00:00-07:00",
* "isDaytime": true,
* "temperature": 66,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "8 to 14 mph",
* "windDirection": "W",
* "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
* "shortForecast": "Mostly Sunny",
* "detailedForecast": "Mostly sunny, with a high near 66."
* },
* {
* "number": 9,
* "name": "Monday Night",
* "startTime": "2018-09-10T18:00:00-07:00",
* "endTime": "2018-09-11T06:00:00-07:00",
* "isDaytime": false,
* "temperature": 55,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "9 to 14 mph",
* "windDirection": "WNW",
* "icon": "https://api.weather.gov/icons/land/night/sct?size=medium",
* "shortForecast": "Partly Cloudy",
* "detailedForecast": "Partly cloudy, with a low around 55."
* },
* {
* "number": 10,
* "name": "Tuesday",
* "startTime": "2018-09-11T06:00:00-07:00",
* "endTime": "2018-09-11T18:00:00-07:00",
* "isDaytime": true,
* "temperature": 65,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "9 to 16 mph",
* "windDirection": "WNW",
* "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
* "shortForecast": "Mostly Sunny",
* "detailedForecast": "Mostly sunny, with a high near 65."
* },
* {
* "number": 11,
* "name": "Tuesday Night",
* "startTime": "2018-09-11T18:00:00-07:00",
* "endTime": "2018-09-12T06:00:00-07:00",
* "isDaytime": false,
* "temperature": 55,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "10 to 16 mph",
* "windDirection": "WNW",
* "icon": "https://api.weather.gov/icons/land/night/sct?size=medium",
* "shortForecast": "Partly Cloudy",
* "detailedForecast": "Partly cloudy, with a low around 55."
* },
* {
* "number": 12,
* "name": "Wednesday",
* "startTime": "2018-09-12T06:00:00-07:00",
* "endTime": "2018-09-12T18:00:00-07:00",
* "isDaytime": true,
* "temperature": 65,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "12 to 15 mph",
* "windDirection": "W",
* "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
* "shortForecast": "Mostly Sunny",
* "detailedForecast": "Mostly sunny, with a high near 65."
* },
* {
* "number": 13,
* "name": "Wednesday Night",
* "startTime": "2018-09-12T18:00:00-07:00",
* "endTime": "2018-09-13T06:00:00-07:00",
* "isDaytime": false,
* "temperature": 56,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "8 to 15 mph",
* "windDirection": "W",
* "icon": "https://api.weather.gov/icons/land/night/few?size=medium",
* "shortForecast": "Mostly Clear",
* "detailedForecast": "Mostly clear, with a low around 56."
* },
* {
* "number": 14,
* "name": "Thursday",
* "startTime": "2018-09-13T06:00:00-07:00",
* "endTime": "2018-09-13T18:00:00-07:00",
* "isDaytime": true,
* "temperature": 66,
* "temperatureUnit": "F",
* "temperatureTrend": null,
* "windSpeed": "7 to 13 mph",
* "windDirection": "W",
* "icon": "https://api.weather.gov/icons/land/day/few?size=medium",
* "shortForecast": "Sunny",
* "detailedForecast": "Sunny, with a high near 66."
* }
* ],
* "geometry": {
* "type": "GeometryCollection",
* "geometries": [
* {
* "type": "Point",
* "coordinates": [
* -122.4097848,
* 37.7725663
* ]
* },
* {
* "type": "Polygon",
* "coordinates": [
* [
* [
* -122.4263966,
* 37.7812349
* ],
* [
* -122.42073930000001,
* 37.759429600000004
* ],
* [
* -122.39317570000001,
* 37.76389580000001
* ],
* [
* -122.39882750000001,
* 37.78570150000001
* ],
* [
* -122.4263966,
* 37.7812349
* ]
* ]
* ]
* }
* ]
* }
* }
* ```
* @param {Object=} options
* @param {string=} options.zipCode optional zip code to overrride value in Ad Parameters
* @param {string=} options.temperatureUnit Sets the unit type that degrees will be measured. Accepts 'F' or 'C'. Default is 'F'.
* @param {number=} timeout (default 30 seconds) maximum seconds to wait for api results
* @returns {Promise}
*/
function getWeatherForecast (options) {
options = options || {}
var eventName = 'WEATHER_FORECAST_RESULTS'
var errorEvent = 'WEATHER_FORECAST_ERROR'
var temperatureUnit = options.temperatureUnit || 'F'
var blink = window.$b || {}
var adParameters = blink.adParameters || {}
var zipCode = options.zipCode
var isZipValid = function (zip) {
return /^\d{5,5}$/.test(zip)
}
var isLocationValid = function (locationObj) {
return typeof locationObj.latitude === 'number' && typeof locationObj.longitude === 'number'
}
if (!isZipValid(zipCode)) {
var message
if (adParameters.geoInfo && adParameters.geoInfo.postalCode) {
zipCode = adParameters.geoInfo.postalCode
if (!isZipValid(zipCode)) {
message = 'Invalid zip code: ' + zipCode
console.error(errorEvent, message)
var error = new Error(message)
try {
window.$b.emit(errorEvent, error)
} catch (err) {
console.error(err)
}
return Promise.reject(error)
}
} else {
message = 'Ad Parameter has no geoInfo.postalCode'
console.error(errorEvent, message)
try {
window.$b.emit(errorEvent, message)
} catch (err) {
console.error(err)
}
return Promise.reject(new Error(message))
}
}
var timeout = options.timeout
if ((typeof timeout !== 'number') || (timeout <= 0)) {
timeout = 30000
} else {
timeout *= 1000
}
// var zipUrl = 'https://pterodactylus.tremorvideodsp.com/ws/zipcodes/ZIP.json'
var zipUrl = 'https://raptor.tremorvideodsp.com/ws/zipcodes/ZIP.json'
var weatherUrl = 'https://api.weather.gov/points/LAT,LON/forecast'
zipUrl = zipUrl.replace('ZIP', zipCode)
return new Promise(function (resolve, reject) {
$.ajax({
url: zipUrl,
method: 'GET',
timeout: timeout
})
.fail(function (err) {
var message = zipUrl + ': ' + err.statusText
console.error(errorEvent, message)
var error = new Error(message)
reject(error)
try {
window.$b.emit(errorEvent, error)
} catch (err) {
console.error(err)
}
})
.then(function (json) {
if (!isLocationValid(json)) {
var message = 'Zipcode "' + zipCode + '" is invalid'
console.error(errorEvent, message)
var error = new Error(message)
try {
window.$b.emit(errorEvent, error)
} catch (err) {
console.error(err)
}
return reject(error)
}
weatherUrl = weatherUrl
.replace('LAT', json.latitude)
.replace('LON', json.longitude)
$.ajax({
url: weatherUrl,
method: 'GET',
timeout: timeout
})
.fail(function (err) {
var message = weatherUrl + ': ' + err.statusText
console.error(errorEvent, message)
var error = new Error(message)
reject(error)
try {
window.$b.emit(errorEvent, error)
} catch (err) {
console.error(err)
}
})
.done(function (data) {
if (data.properties instanceof Object) {
data.properties.geometry = data.geometry
data.properties.zipCode = zipCode
if (temperatureUnit === 'C' && data.properties.periods) {
data.properties.periods.forEach(function (element) {
element.temperature = Math.round((5 / 9) * (element.temperature - 32))
element.temperatureUnit = 'C'
})
}
console.log(eventName, data.properties)
resolve(data.properties)
try {
window.$b.emit(eventName, data.properties)
} catch (err) {
console.error(err)
}
} else {
var message = 'Weather Forecast from ' + weatherUrl + ' did not return data.properties'
console.error(errorEvent, message)
var error = new Error(message)
reject(error)
try {
window.$b.emit(errorEvent, error)
} catch (err) {
console.error(err)
}
}
})
})
})
}
window.$b = window.$b || {}
window.$b.snippets = window.$b.snippets || {}
var snippets = window.$b.snippets
snippets.getWeatherForecast = getWeatherForecast
if (window.module) {
window.module.exports = getWeatherForecast
}