Weatherscan/webroot/js/utils.js

261 lines
7.6 KiB
JavaScript

// Fisher-Yates shuffle
function shuffle (array) {
var i = 0,
j = 0,
temp = null;
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1));
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function getRandom(min, max) {
return Math.random() * (max - min) + min;
}
function getNextHighestIndex(arr, value) {
var i = arr.length;
while (arr[--i] > value);
return ++i;
}
function getUrlParameter(e) {
return decodeURI((new RegExp(e + "=(.+?)(&|$)").exec(location.search) || [, null])[1])
}
//convert minutes to hour and minutes
function formatMinutes(m){
var hours = Math.trunc(m/60);
var minutes = m % 60;
return (((hours != 0) ? ('<em>' + hours + '</em> hr <em>') : '<em>') + minutes +'</em> min');
}
// convert celsius to farenheight
function C2F(c){
return Math.round( c * 9 / 5 + 32 );
}
// meters per second to mph
function mps2mph(meters) {
return Math.round( parseFloat(meters) * 2.23694 );
}
// array swap
Array.prototype.swap = function(a,b){ var tmp=this[a];this[a]=this[b];this[b]=tmp;};
function degToCompass(deg){
val = Math.round((deg/22.5)+.5);
arr=["N","NE","E","SE","S","SW","W","NW"];
return arr[(val % 8)];
}
function distance(lat1, lon1, lat2, lon2) {
var radlat1 = Math.PI * lat1/180,
radlat2 = Math.PI * lat2/180,
theta = lon1-lon2,
radtheta = Math.PI * theta/180,
dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
dist = Math.acos(dist);
dist = dist * 180/Math.PI;
dist = dist * 60 * 1.1515;
return dist;
}
function dewPoint(tem, r){
tem = -1.0*(tem-32)*5/9 ;
es = 6.112*Math.exp(-1.0*17.67*tem/(243.5 - tem));
ed = r/100.0*es;
eln = Math.log(ed/6.112);
td = -243.5*eln/(eln - 17.67 );
return Math.round( (td*9/5)+32 );
}
function heatIndex(T, R) { // T = temp, R = relative humidity
var T2 = T*T, R2= R*R,
c1 = -42.379, c2 = 2.04901523, c3 = 10.14333127,
c4 = -0.22475541, c5 = -6.83783*Math.pow(10,-3), c6 = -5.481717*Math.pow(10,-2),
c7 = 1.22874*Math.pow(10,-3), c8 = 8.5282*Math.pow(10,-4), c9 = -1.99*Math.pow(10,-6);
return Math.round(c1 + c2*T + c3 *R + c4*T*R + c5*T2 + c6*R2 + c7*T2*R + c8*T*R2 + c9*T2*R2);
}
// ----------------------------------------
// Calculate new Lat/Lng from original points
// on a distance and bearing (angle)
// ----------------------------------------
let llFromDistance = function(latitude, longitude, distance, bearing) {
// taken from: https://stackoverflow.com/a/46410871/13549
// distance in KM, bearing in degrees
const R = 6378.1; // Radius of the Earth
const brng = bearing * Math.PI / 180; // Convert bearing to radian
let lat = latitude * Math.PI / 180; // Current coords to radians
let lon = longitude * Math.PI / 180;
// Do the math magic
lat = Math.asin(Math.sin(lat) * Math.cos(distance / R) + Math.cos(lat) * Math.sin(distance / R) * Math.cos(brng));
lon += Math.atan2(Math.sin(brng) * Math.sin(distance / R) * Math.cos(lat), Math.cos(distance/R)-Math.sin(lat)*Math.sin(lat));
// Coords back to degrees and return
return [ (lat * 180 / Math.PI), (lon * 180 / Math.PI) ];
}
let pointsOnMapCircle = function(latitude, longitude, distance, numPoints) {
const points = [];
for (let i=0; i <= numPoints - 1; i++) {
const bearing = Math.round((360 / numPoints) * i);
console.log(bearing, i);
const newPoints = llFromDistance(latitude, longitude, distance, bearing);
points.push(newPoints);
}
return points;
}
// maps current condition code to icon
function getCCicon(ccCode, windData){
var icon = "images/icons/" + ( "0" + {"0":0,"1":0,"2":0,"3":47,"4":01,"5":02,"6":38,"7":03,"8":04,"9":05,"10":06,"11":08,"12":08,"13":09,"14":12,"15":11,"16":12,"17":48,"18":48,"19":16,"20":49,"21":16,"22":14,"23":0,"24":50,"25":34,"26":20,"27":21,"28":22,"29":23,"30":24,"31":25,"32":26,"33":27,"34":28,"35":13,"36":41,"37":29,"38":29,"39":30,"40":31,"41":32,"42":33,"43":34,"44":19,"45":35,"46":36,"47":37}[ccCode]).slice(-2) + ".png";
if (parseInt(windData) >= 20) {
if (icon === "images/icons/12.png" || icon === "images/icons/10.png" || icon === "images/icons/09.png") {
icon = "images/icons/34.png"
} else if (icon === "images/icons/31" || icon === "images/icons/08" || icon === "images/icons/07.png") {
icon = "images/icons/45.png"
}
}
return icon
}
function getWarningPosition(warning) {
var warnpos = { "Tsunami Warning": 1,
"Tornado Warning": 2,
"Extreme Wind Warning": 3,
"Severe Thunderstorm Warning": 4,
"Flash Flood Warning": 5,
"Flash Flood Statement": 6,
"Severe Weather Statement": 7,
"Fire Warning": 14,
"Storm Surge Warning": 17,
"Hurricane Force Wind Warning": 18,
"Hurricane Warning": 19,
"Typhoon Warning": 20,
"Special Marine Warning": 21,
"Blizzard Warning": 22,
"Snow Squall Warning": 23,
"Ice Storm Warning": 24,
"Winter Storm Warning": 25,
"High Wind Warning": 26,
"Tropical Storm Warning": 27,
"Storm Warning": 28,
"Tsunami Advisory": 29,
"Tsunami Watch": 30,
"Avalanche Warning": 31,
"Earthquake Warning": 32,
"Volcano Warning": 33,
"Ashfall Warning": 34,
"Coastal Flood Warning": 35,
"Lakeshore Flood Warning": 36,
"Flood Warning": 37,
"River Flood Warning": 37.5,
"High Surf Warning": 38,
"Dust Storm Warning": 39,
"Blowing Dust Warning": 40,
"Lake Effect Snow Warning": 41,
"Excessive Heat Warning": 42,
"Tornado Watch": 43,
"Severe Thunderstorm Watch": 44,
"Flash Flood Watch": 45,
"Gale Warning": 46,
"Flood Statement": 47,
"Wind Chill Warning": 48,
"Extreme Cold Warning": 49,
"Hard Freeze Warning": 50,
"Freeze Warning": 51,
"Red Flag Warning": 52,
"Storm Surge Watch": 53,
"Hurricane Watch": 54,
"Hurricane Force Wind Watch": 55,
"Typhoon Watch": 56,
"Tropical Storm Watch": 57,
"Storm Watch": 58,
"Hurricane Local Statement": 59,
"Typhoon Local Statement": 60,
"Tropical Storm Local Statement": 61,
"Tropical Depression Local Statement": 62,
"Avalanche Advisory": 63,
"Winter Weather Advisory": 64,
"Wind Chill Advisory": 65,
"Heat Advisory": 66,
"Urban and Small Stream Flood Advisory": 67,
"Small Stream Flood Advisory": 68,
"Arroyo and Small Stream Flood Advisory": 69,
"Flood Advisory": 70,
"Hydrologic Advisory": 71,
"Lakeshore Flood Advisory": 72,
"Coastal Flood Advisory": 73,
"High Surf Advisory": 74,
"Heavy Freezing Spray Warning": 75,
"Dense Fog Advisory": 76,
"Dense Smoke Advisory": 77,
"Small Craft Advisory For Hazardous Seas": 78,
"Small Craft Advisory for Rough Bar": 79,
"Small Craft Advisory for Winds": 80,
"Small Craft Advisory": 81,
"Brisk Wind Advisory": 82,
"Hazardous Seas Warning": 83,
"Dust Advisory": 84,
"Blowing Dust Advisory": 85,
"Lake Wind Advisory": 86,
"Wind Advisory": 87,
"Frost Advisory": 88,
"Ashfall Advisory": 89,
"Freezing Fog Advisory": 90,
"Freezing Spray Advisory": 91,
"Low Water Advisory": 92,
"Avalanche Watch": 94,
"Blizzard Watch": 95,
"Rip Current Statement": 96,
"Beach Hazards Statement": 97,
"Gale Watch": 98,
"Winter Storm Watch": 99,
"Hazardous Seas Watch": 100,
"Heavy Freezing Spray Watch": 101,
"Coastal Flood Watch": 102,
"Lakeshore Flood Watch": 103,
"Flood Watch": 104,
"High Wind Watch": 105,
"Excessive Heat Watch": 106,
"Extreme Cold Watch": 107,
"Wind Chill Watch": 108,
"Lake Effect Snow Watch": 109,
"Hard Freeze Watch": 110,
"Freeze Watch": 111,
"Fire Weather Watch": 112,
"Extreme Fire Danger": 113,
"Coastal Flood Statement": 115,
"Lakeshore Flood Statement": 116,
"Special Weather Statement": 117,
"Marine Weather Statement": 118,
"Air Quality Alert": 119,
"Air Stagnation Advisory": 120,
"Hazardous Weather Outlook": 121,
}[warning]
if (warnpos !== undefined) {
return warnpos;
} else {
return 140;
}
}// https://date-fns.org/docs/Getting-Started