Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85e2553cb2 | ||
|
|
101d0ac9ea | ||
|
|
834d68f9e3 | ||
|
|
0ee7fdc9f8 | ||
|
|
d75121e894 | ||
|
|
4cdced3659 | ||
|
|
1a5548d135 | ||
|
|
11c826a2af | ||
|
|
7a129c1cd3 | ||
|
|
867657a965 | ||
|
|
e89dc52541 | ||
|
|
317883fc04 | ||
|
|
a4a601a387 | ||
|
|
375812c024 | ||
|
|
6af8b58f14 | ||
|
|
6287db7483 | ||
|
|
46a8fa470c | ||
|
|
8489b7e2be | ||
|
|
7a196ac64a | ||
|
|
5946ee495a | ||
|
|
93ac03acd4 | ||
|
|
23a0dd6870 | ||
|
|
384693688c | ||
|
|
e2877aad77 | ||
|
|
7fae649357 | ||
|
|
468e057c51 | ||
|
|
4c65f5bc4d | ||
|
|
99308155d6 | ||
|
|
cde7ceda6e | ||
|
|
72938671ac | ||
|
|
9e1ea31262 | ||
|
|
e952d860dc | ||
|
|
262ea15468 | ||
|
|
5d2e5a6d9c | ||
|
|
992258d3ce | ||
|
|
b031934022 | ||
|
|
4cc2312ffd | ||
|
|
ce99fc16e7 | ||
|
|
97f96d4091 | ||
|
|
13f08b62cc | ||
|
|
eacd82b4f4 | ||
|
|
91f669e828 | ||
|
|
cdbe3d968f | ||
|
|
0a388cdb83 | ||
|
|
8678d9f053 | ||
|
|
a592668d0d | ||
|
|
b3faf95e39 | ||
|
|
3a304d7c08 | ||
|
|
c6918f0c6c | ||
|
|
fb93ade4d2 | ||
|
|
6f260a6ac7 | ||
|
|
50e526639c | ||
|
|
38db5cb6a6 | ||
|
|
8c278928b9 | ||
|
|
130a1bfad3 | ||
|
|
bd6c5430c4 | ||
|
|
cc896bf18d | ||
|
|
f7a15a93c6 | ||
|
|
0baa31a92c | ||
|
|
8fa00b34b4 | ||
|
|
23cc1a1f7a | ||
|
|
b272aa298a | ||
|
|
f0166ec2df | ||
|
|
1983d025a4 | ||
|
|
c7eb56f60c |
@@ -2,8 +2,7 @@
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"jquery": true
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"airbnb-base"
|
||||
@@ -12,10 +11,11 @@
|
||||
"TravelCities": "readonly",
|
||||
"RegionalCities": "readonly",
|
||||
"StationInfo": "readonly",
|
||||
"SunCalc": "readonly"
|
||||
"SunCalc": "readonly",
|
||||
"NoSleep": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2023,
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [],
|
||||
|
||||
5
.gitignore
vendored
@@ -11,4 +11,7 @@ server/music/*
|
||||
|
||||
#dist folder
|
||||
dist/*
|
||||
!dist/readme.txt
|
||||
!dist/readme.txt
|
||||
|
||||
#environment variables
|
||||
.env
|
||||
13
.vscode/launch.json
vendored
@@ -15,10 +15,13 @@
|
||||
"**/*.min.js",
|
||||
"**/vendor/**"
|
||||
],
|
||||
"runtimeArgs": [
|
||||
"--autoplay-policy=no-user-gesture-required"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Data:stations",
|
||||
"program": "${workspaceFolder}/datagenerators/stations.js",
|
||||
"program": "${workspaceFolder}/datagenerators/stations.mjs",
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
@@ -27,7 +30,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Data:regionalcities",
|
||||
"program": "${workspaceFolder}/datagenerators/regionalcities.js",
|
||||
"program": "${workspaceFolder}/datagenerators/regionalcities.mjs",
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
@@ -36,7 +39,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Data:travelcities",
|
||||
"program": "${workspaceFolder}/datagenerators/travelcities.js",
|
||||
"program": "${workspaceFolder}/datagenerators/travelcities.mjs",
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
@@ -66,13 +69,13 @@
|
||||
},
|
||||
{
|
||||
"name": "Test",
|
||||
"program": "${workspaceFolder}/tests/index.js",
|
||||
"program": "${workspaceFolder}/tests/index.mjs",
|
||||
"request": "launch",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"type": "node",
|
||||
"outputCapture": "std"
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
],
|
||||
"compounds": [
|
||||
|
||||
5
.vscode/settings.json
vendored
@@ -1,7 +1,4 @@
|
||||
{
|
||||
"cSpell.enableFiletypes": [
|
||||
"javascript"
|
||||
],
|
||||
"liveSassCompile.settings.formats": [
|
||||
{
|
||||
"format": "compressed",
|
||||
@@ -22,5 +19,5 @@
|
||||
},
|
||||
"eslint.validate": [
|
||||
"javascript"
|
||||
]
|
||||
],
|
||||
}
|
||||
16
README.md
@@ -18,7 +18,7 @@ This project is based on the work of [Mike Battaglia](https://github.com/vbguyny
|
||||
|
||||
## Does WeatherStar 4000+ work outside of the USA?
|
||||
|
||||
This project is tightly coupled to [NOAA's Weather API](https://www.weather.gov/documentation/services-web-api), which is exclsuive to the United States. Using NOAA's Weather API is a crucial requirement to provide an authentic WeatherStar 4000+ experience.
|
||||
This project is tightly coupled to [NOAA's Weather API](https://www.weather.gov/documentation/services-web-api), which is exclusive to the United States. Using NOAA's Weather API is a crucial requirement to provide an authentic WeatherStar 4000+ experience.
|
||||
|
||||
If you would like to display weather information for international locations (outside of the USA), please checkout a fork of this project created by [@mwood77](https://github.com/mwood77):
|
||||
- [`ws4kp-international`](https://github.com/mwood77/ws4kp-international)
|
||||
@@ -92,11 +92,12 @@ Kiosk mode can be activated by a checkbox on the page. Note that there is no way
|
||||
|
||||
It's also possible to enter kiosk mode using a permalink. First generate a [Permalink](#sharing-a-permalink-bookmarking), then to the end of it add `&kiosk=true`. Opening this link will load all of the selected displays included in the Permalink, enter kiosk mode immediately upon loading and start playing the forecast.
|
||||
|
||||
## Wish list
|
||||
## Default query string paramaters (environment variables)
|
||||
When serving this via the built-in Express server, it's possible to define environment variables that direct the user to a default set of paramaters (like the [Permalink](#sharing-a-permalink-bookmarking) above). If a user requests the root page at `http://localhost:8080/` the query string provided by environment variables will be appended to the url thus providing a default configuration.
|
||||
|
||||
As time allows I will be working on the following enhancements.
|
||||
Environment variables can be added to the command line as usual, or via a .env file which is parsed with [dotenv](https://github.com/motdotla/dotenv). Both methods have the same effect.
|
||||
|
||||
* Better error reporting when api.weather.gov is down (happens more often than you would think)
|
||||
Environment variables that are to be added to the default query string are prefixed with `WSQS_` and then use the same key/value pairs generated by the [Permalink](#sharing-a-permalink-bookmarking) above, with the `- (dash)` character replaced by an `_ (underscore)`. For example, if you wanted to turn the travel forecast on, you would find `travel-checkbox=true` in the permalink, it's matching environment variable becomes `WSQS_travel_checkbox=true`.
|
||||
|
||||
## Serving static files
|
||||
The app can be served as a static set of files on any web server. Run the provided gulp task to create a set of static distribution files:
|
||||
@@ -108,7 +109,7 @@ The resulting files will be in the /dist folder in the root of the project. Thes
|
||||
## Music
|
||||
The WeatherStar had wonderful background music from the smooth jazz and new age genres by artists of the time. Lists of the music that played are available by searching online, but it's all copyrighted music and would be difficult to provide as part of this repository.
|
||||
|
||||
I've used AI tools to create WeatherStar-inspired music tracks that are unencumbered by copyright and are included in this repo. Too keep the size down, I've only included 4 tracks. Additional tracks will be posted in a companion repository [ws4kp-music](https://github.com/netbymatt/ws4kp-music).
|
||||
I've used AI tools to create WeatherStar-inspired music tracks that are unencumbered by copyright and are included in this repo. Too keep the size down, I've only included 4 tracks. Additional tracks are in a companion repository [ws4kp-music](https://github.com/netbymatt/ws4kp-music).
|
||||
|
||||
### Customizing the music
|
||||
Placing .mp3 files in the `/server/music` folder will override the default music included in the repo. Subdirectories will not be scanned. When weatherstar loads in the browser it will load a list if available files and randomize the order when it starts playing. On each loop through the available tracks the order will again be shuffled. If you're using the static files method to host your WeatherStar music is located in `/music`.
|
||||
@@ -129,6 +130,7 @@ Thanks to the WeatherStar community for providing these discussions to further e
|
||||
|
||||
* [Stream as FFMPEG](https://github.com/netbymatt/ws4kp/issues/37#issuecomment-2008491948)
|
||||
* [Weather like it's 1999](https://blog.scottlabs.io/2024/02/weather-like-its-1999/) Raspberry pi, streaming, music and CRT all combined into a complete solution.
|
||||
* [ws4channels](https://github.com/rice9797/ws4channels) A Dockerized Node.js application to stream WeatherStar 4000 data into Channels DVR using Puppeteer and FFmpeg.
|
||||
|
||||
## Customization
|
||||
A hook is provided as `/server/scripts/custom.js` to allow customizations to your own fork of this project, without accidentally pushing your customizations back upstream to the git repository. An sample file is provided at `/server/scripts/custom.sample.js` and should be renamed to `custom.js` activate it.
|
||||
@@ -139,6 +141,10 @@ Please do not report issues with api.weather.gov being down. It's a new service
|
||||
|
||||
Note: not all units are converted to metric, if selected. Some text-based products such as warnings are simple text strings provided from the national weather service and thus have baked-in units such as "gusts up to 60 mph." These values will not be converted.
|
||||
|
||||
## Related Projects
|
||||
|
||||
Not retro enough? Try the [Weatherstar 3000+](https://github.com/netbymatt/ws3kp)
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This web site should NOT be used in life threatening weather situations, or be relied on to inform the public of such situations. The Internet is an unreliable network subject to server and network outages and by nature is not suitable for such mission critical use. If you require such access to NWS data, please consider one of their subscription services. The authors of this web site shall not be held liable in the event of injury, death or property damage that occur as a result of disregarding this warning.
|
||||
|
||||
@@ -19,4 +19,4 @@ const chunk = (data, chunkSize = 10) => {
|
||||
return chunks;
|
||||
};
|
||||
|
||||
module.exports = chunk;
|
||||
export default chunk;
|
||||
@@ -1,8 +1,7 @@
|
||||
// async https wrapper
|
||||
import https from 'https';
|
||||
|
||||
const https = require('https');
|
||||
|
||||
module.exports = (url) => new Promise((resolve, reject) => {
|
||||
const get = (url) => new Promise((resolve, reject) => {
|
||||
const headers = {};
|
||||
headers['user-agent'] = '(WeatherStar 4000+ data generator, ws4000@netbymatt.com)';
|
||||
|
||||
@@ -22,3 +21,5 @@ module.exports = (url) => new Promise((resolve, reject) => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
|
||||
export default get;
|
||||
@@ -4,8 +4,8 @@
|
||||
"lat": 33.749,
|
||||
"lon": -84.388,
|
||||
"point": {
|
||||
"x": 50,
|
||||
"y": 86,
|
||||
"x": 51,
|
||||
"y": 87,
|
||||
"wfo": "FFC"
|
||||
}
|
||||
},
|
||||
@@ -24,8 +24,8 @@
|
||||
"lat": 41.9796,
|
||||
"lon": -87.9045,
|
||||
"point": {
|
||||
"x": 65,
|
||||
"y": 76,
|
||||
"x": 66,
|
||||
"y": 77,
|
||||
"wfo": "LOT"
|
||||
}
|
||||
},
|
||||
@@ -34,8 +34,8 @@
|
||||
"lat": 41.4995,
|
||||
"lon": -81.6954,
|
||||
"point": {
|
||||
"x": 82,
|
||||
"y": 64,
|
||||
"x": 83,
|
||||
"y": 65,
|
||||
"wfo": "CLE"
|
||||
}
|
||||
},
|
||||
@@ -44,8 +44,8 @@
|
||||
"lat": 32.8959,
|
||||
"lon": -97.0372,
|
||||
"point": {
|
||||
"x": 79,
|
||||
"y": 108,
|
||||
"x": 80,
|
||||
"y": 109,
|
||||
"wfo": "FWD"
|
||||
}
|
||||
},
|
||||
@@ -54,8 +54,8 @@
|
||||
"lat": 39.7391,
|
||||
"lon": -104.9847,
|
||||
"point": {
|
||||
"x": 62,
|
||||
"y": 60,
|
||||
"x": 63,
|
||||
"y": 61,
|
||||
"wfo": "BOU"
|
||||
}
|
||||
},
|
||||
@@ -64,8 +64,8 @@
|
||||
"lat": 42.3314,
|
||||
"lon": -83.0457,
|
||||
"point": {
|
||||
"x": 65,
|
||||
"y": 33,
|
||||
"x": 66,
|
||||
"y": 34,
|
||||
"wfo": "DTX"
|
||||
}
|
||||
},
|
||||
@@ -94,8 +94,8 @@
|
||||
"lat": 39.7684,
|
||||
"lon": -86.158,
|
||||
"point": {
|
||||
"x": 57,
|
||||
"y": 68,
|
||||
"x": 58,
|
||||
"y": 69,
|
||||
"wfo": "IND"
|
||||
}
|
||||
},
|
||||
@@ -104,8 +104,8 @@
|
||||
"lat": 34.0522,
|
||||
"lon": -118.2437,
|
||||
"point": {
|
||||
"x": 154,
|
||||
"y": 44,
|
||||
"x": 155,
|
||||
"y": 45,
|
||||
"wfo": "LOX"
|
||||
}
|
||||
},
|
||||
@@ -114,8 +114,8 @@
|
||||
"lat": 25.7743,
|
||||
"lon": -80.1937,
|
||||
"point": {
|
||||
"x": 109,
|
||||
"y": 50,
|
||||
"x": 110,
|
||||
"y": 51,
|
||||
"wfo": "MFL"
|
||||
}
|
||||
},
|
||||
@@ -124,8 +124,8 @@
|
||||
"lat": 44.98,
|
||||
"lon": -93.2638,
|
||||
"point": {
|
||||
"x": 107,
|
||||
"y": 71,
|
||||
"x": 108,
|
||||
"y": 72,
|
||||
"wfo": "MPX"
|
||||
}
|
||||
},
|
||||
@@ -134,8 +134,8 @@
|
||||
"lat": 40.78,
|
||||
"lon": -73.88,
|
||||
"point": {
|
||||
"x": 36,
|
||||
"y": 38,
|
||||
"x": 37,
|
||||
"y": 39,
|
||||
"wfo": "OKX"
|
||||
}
|
||||
},
|
||||
@@ -144,8 +144,8 @@
|
||||
"lat": 36.8468,
|
||||
"lon": -76.2852,
|
||||
"point": {
|
||||
"x": 89,
|
||||
"y": 51,
|
||||
"x": 90,
|
||||
"y": 52,
|
||||
"wfo": "AKQ"
|
||||
}
|
||||
},
|
||||
@@ -164,8 +164,8 @@
|
||||
"lat": 39.9523,
|
||||
"lon": -75.1638,
|
||||
"point": {
|
||||
"x": 49,
|
||||
"y": 75,
|
||||
"x": 50,
|
||||
"y": 76,
|
||||
"wfo": "PHI"
|
||||
}
|
||||
},
|
||||
@@ -174,8 +174,8 @@
|
||||
"lat": 40.4406,
|
||||
"lon": -79.9959,
|
||||
"point": {
|
||||
"x": 77,
|
||||
"y": 65,
|
||||
"x": 78,
|
||||
"y": 66,
|
||||
"wfo": "PBZ"
|
||||
}
|
||||
},
|
||||
@@ -184,8 +184,8 @@
|
||||
"lat": 38.6273,
|
||||
"lon": -90.1979,
|
||||
"point": {
|
||||
"x": 94,
|
||||
"y": 73,
|
||||
"x": 95,
|
||||
"y": 74,
|
||||
"wfo": "LSX"
|
||||
}
|
||||
},
|
||||
@@ -204,8 +204,8 @@
|
||||
"lat": 47.6062,
|
||||
"lon": -122.3321,
|
||||
"point": {
|
||||
"x": 124,
|
||||
"y": 67,
|
||||
"x": 125,
|
||||
"y": 68,
|
||||
"wfo": "SEW"
|
||||
}
|
||||
},
|
||||
@@ -214,8 +214,8 @@
|
||||
"lat": 43.0481,
|
||||
"lon": -76.1474,
|
||||
"point": {
|
||||
"x": 51,
|
||||
"y": 98,
|
||||
"x": 52,
|
||||
"y": 99,
|
||||
"wfo": "BGM"
|
||||
}
|
||||
},
|
||||
@@ -224,8 +224,8 @@
|
||||
"lat": 27.9756,
|
||||
"lon": -82.5329,
|
||||
"point": {
|
||||
"x": 67,
|
||||
"y": 97,
|
||||
"x": 68,
|
||||
"y": 98,
|
||||
"wfo": "TBW"
|
||||
}
|
||||
},
|
||||
@@ -244,8 +244,8 @@
|
||||
"lat": 42.6526,
|
||||
"lon": -73.7562,
|
||||
"point": {
|
||||
"x": 58,
|
||||
"y": 58,
|
||||
"x": 72,
|
||||
"y": 63,
|
||||
"wfo": "ALY"
|
||||
}
|
||||
},
|
||||
@@ -254,8 +254,8 @@
|
||||
"lat": 35.0845,
|
||||
"lon": -106.6511,
|
||||
"point": {
|
||||
"x": 97,
|
||||
"y": 118,
|
||||
"x": 98,
|
||||
"y": 121,
|
||||
"wfo": "ABQ"
|
||||
}
|
||||
},
|
||||
@@ -264,8 +264,8 @@
|
||||
"lat": 35.222,
|
||||
"lon": -101.8313,
|
||||
"point": {
|
||||
"x": 47,
|
||||
"y": 25,
|
||||
"x": 48,
|
||||
"y": 26,
|
||||
"wfo": "AMA"
|
||||
}
|
||||
},
|
||||
@@ -284,8 +284,8 @@
|
||||
"lat": 30.2671,
|
||||
"lon": -97.7431,
|
||||
"point": {
|
||||
"x": 155,
|
||||
"y": 90,
|
||||
"x": 156,
|
||||
"y": 91,
|
||||
"wfo": "EWX"
|
||||
}
|
||||
},
|
||||
@@ -294,8 +294,8 @@
|
||||
"lat": 44.7502,
|
||||
"lon": -117.6677,
|
||||
"point": {
|
||||
"x": 93,
|
||||
"y": 145,
|
||||
"x": 94,
|
||||
"y": 146,
|
||||
"wfo": "BOI"
|
||||
}
|
||||
},
|
||||
@@ -314,7 +314,7 @@
|
||||
"lat": 44.8012,
|
||||
"lon": -68.7778,
|
||||
"point": {
|
||||
"x": 72,
|
||||
"x": 66,
|
||||
"y": 62,
|
||||
"wfo": "CAR"
|
||||
}
|
||||
@@ -324,8 +324,8 @@
|
||||
"lat": 33.5207,
|
||||
"lon": -86.8025,
|
||||
"point": {
|
||||
"x": 58,
|
||||
"y": 83,
|
||||
"x": 59,
|
||||
"y": 84,
|
||||
"wfo": "BMX"
|
||||
}
|
||||
},
|
||||
@@ -334,8 +334,8 @@
|
||||
"lat": 46.8083,
|
||||
"lon": -100.7837,
|
||||
"point": {
|
||||
"x": 109,
|
||||
"y": 46,
|
||||
"x": 110,
|
||||
"y": 47,
|
||||
"wfo": "BIS"
|
||||
}
|
||||
},
|
||||
@@ -344,8 +344,8 @@
|
||||
"lat": 43.6135,
|
||||
"lon": -116.2034,
|
||||
"point": {
|
||||
"x": 132,
|
||||
"y": 85,
|
||||
"x": 133,
|
||||
"y": 86,
|
||||
"wfo": "BOI"
|
||||
}
|
||||
},
|
||||
@@ -354,8 +354,8 @@
|
||||
"lat": 42.8864,
|
||||
"lon": -78.8784,
|
||||
"point": {
|
||||
"x": 35,
|
||||
"y": 46,
|
||||
"x": 36,
|
||||
"y": 47,
|
||||
"wfo": "BUF"
|
||||
}
|
||||
},
|
||||
@@ -374,8 +374,8 @@
|
||||
"lat": 32.7766,
|
||||
"lon": -79.9309,
|
||||
"point": {
|
||||
"x": 86,
|
||||
"y": 76,
|
||||
"x": 87,
|
||||
"y": 77,
|
||||
"wfo": "CHS"
|
||||
}
|
||||
},
|
||||
@@ -384,8 +384,8 @@
|
||||
"lat": 38.3498,
|
||||
"lon": -81.6326,
|
||||
"point": {
|
||||
"x": 62,
|
||||
"y": 66,
|
||||
"x": 63,
|
||||
"y": 67,
|
||||
"wfo": "RLX"
|
||||
}
|
||||
},
|
||||
@@ -394,8 +394,8 @@
|
||||
"lat": 35.2271,
|
||||
"lon": -80.8431,
|
||||
"point": {
|
||||
"x": 118,
|
||||
"y": 64,
|
||||
"x": 119,
|
||||
"y": 65,
|
||||
"wfo": "GSP"
|
||||
}
|
||||
},
|
||||
@@ -404,8 +404,8 @@
|
||||
"lat": 41.14,
|
||||
"lon": -104.8202,
|
||||
"point": {
|
||||
"x": 109,
|
||||
"y": 13,
|
||||
"x": 110,
|
||||
"y": 14,
|
||||
"wfo": "CYS"
|
||||
}
|
||||
},
|
||||
@@ -414,8 +414,8 @@
|
||||
"lat": 39.162,
|
||||
"lon": -84.4569,
|
||||
"point": {
|
||||
"x": 36,
|
||||
"y": 40,
|
||||
"x": 37,
|
||||
"y": 41,
|
||||
"wfo": "ILN"
|
||||
}
|
||||
},
|
||||
@@ -434,8 +434,8 @@
|
||||
"lat": 39.9612,
|
||||
"lon": -82.9988,
|
||||
"point": {
|
||||
"x": 84,
|
||||
"y": 80,
|
||||
"x": 85,
|
||||
"y": 81,
|
||||
"wfo": "ILN"
|
||||
}
|
||||
},
|
||||
@@ -444,8 +444,8 @@
|
||||
"lat": 41.6005,
|
||||
"lon": -93.6091,
|
||||
"point": {
|
||||
"x": 73,
|
||||
"y": 49,
|
||||
"x": 74,
|
||||
"y": 50,
|
||||
"wfo": "DMX"
|
||||
}
|
||||
},
|
||||
@@ -454,8 +454,8 @@
|
||||
"lat": 42.5006,
|
||||
"lon": -90.6646,
|
||||
"point": {
|
||||
"x": 62,
|
||||
"y": 110,
|
||||
"x": 63,
|
||||
"y": 111,
|
||||
"wfo": "DVN"
|
||||
}
|
||||
},
|
||||
@@ -474,7 +474,7 @@
|
||||
"lat": 44.9062,
|
||||
"lon": -66.99,
|
||||
"point": {
|
||||
"x": 129,
|
||||
"x": 123,
|
||||
"y": 79,
|
||||
"wfo": "CAR"
|
||||
}
|
||||
@@ -484,8 +484,8 @@
|
||||
"lat": 32.792,
|
||||
"lon": -115.563,
|
||||
"point": {
|
||||
"x": 26,
|
||||
"y": 46,
|
||||
"x": 27,
|
||||
"y": 47,
|
||||
"wfo": "PSR"
|
||||
}
|
||||
},
|
||||
@@ -494,8 +494,8 @@
|
||||
"lat": 31.7587,
|
||||
"lon": -106.4869,
|
||||
"point": {
|
||||
"x": 99,
|
||||
"y": 55,
|
||||
"x": 100,
|
||||
"y": 56,
|
||||
"wfo": "EPZ"
|
||||
}
|
||||
},
|
||||
@@ -504,8 +504,8 @@
|
||||
"lat": 44.0521,
|
||||
"lon": -123.0867,
|
||||
"point": {
|
||||
"x": 84,
|
||||
"y": 38,
|
||||
"x": 85,
|
||||
"y": 39,
|
||||
"wfo": "PQR"
|
||||
}
|
||||
},
|
||||
@@ -514,8 +514,8 @@
|
||||
"lat": 46.8772,
|
||||
"lon": -96.7898,
|
||||
"point": {
|
||||
"x": 99,
|
||||
"y": 56,
|
||||
"x": 100,
|
||||
"y": 57,
|
||||
"wfo": "FGF"
|
||||
}
|
||||
},
|
||||
@@ -524,8 +524,8 @@
|
||||
"lat": 35.1981,
|
||||
"lon": -111.6513,
|
||||
"point": {
|
||||
"x": 73,
|
||||
"y": 88,
|
||||
"x": 74,
|
||||
"y": 89,
|
||||
"wfo": "FGZ"
|
||||
}
|
||||
},
|
||||
@@ -544,8 +544,8 @@
|
||||
"lat": 39.0639,
|
||||
"lon": -108.5506,
|
||||
"point": {
|
||||
"x": 94,
|
||||
"y": 101,
|
||||
"x": 95,
|
||||
"y": 102,
|
||||
"wfo": "GJT"
|
||||
}
|
||||
},
|
||||
@@ -554,8 +554,8 @@
|
||||
"lat": 42.9634,
|
||||
"lon": -85.6681,
|
||||
"point": {
|
||||
"x": 40,
|
||||
"y": 46,
|
||||
"x": 41,
|
||||
"y": 47,
|
||||
"wfo": "GRR"
|
||||
}
|
||||
},
|
||||
@@ -564,8 +564,8 @@
|
||||
"lat": 48.55,
|
||||
"lon": -109.6841,
|
||||
"point": {
|
||||
"x": 154,
|
||||
"y": 187,
|
||||
"x": 155,
|
||||
"y": 188,
|
||||
"wfo": "TFX"
|
||||
}
|
||||
},
|
||||
@@ -574,8 +574,8 @@
|
||||
"lat": 46.5927,
|
||||
"lon": -112.0361,
|
||||
"point": {
|
||||
"x": 68,
|
||||
"y": 103,
|
||||
"x": 69,
|
||||
"y": 104,
|
||||
"wfo": "TFX"
|
||||
}
|
||||
},
|
||||
@@ -584,8 +584,8 @@
|
||||
"lat": 21.3069,
|
||||
"lon": -157.8583,
|
||||
"point": {
|
||||
"x": 153,
|
||||
"y": 144,
|
||||
"x": 154,
|
||||
"y": 145,
|
||||
"wfo": "HFO"
|
||||
}
|
||||
},
|
||||
@@ -594,8 +594,8 @@
|
||||
"lat": 34.5037,
|
||||
"lon": -93.0552,
|
||||
"point": {
|
||||
"x": 53,
|
||||
"y": 60,
|
||||
"x": 54,
|
||||
"y": 61,
|
||||
"wfo": "LZK"
|
||||
}
|
||||
},
|
||||
@@ -604,8 +604,8 @@
|
||||
"lat": 43.4666,
|
||||
"lon": -112.0341,
|
||||
"point": {
|
||||
"x": 115,
|
||||
"y": 72,
|
||||
"x": 124,
|
||||
"y": 73,
|
||||
"wfo": "PIH"
|
||||
}
|
||||
},
|
||||
@@ -614,8 +614,8 @@
|
||||
"lat": 32.2988,
|
||||
"lon": -90.1848,
|
||||
"point": {
|
||||
"x": 75,
|
||||
"y": 62,
|
||||
"x": 76,
|
||||
"y": 63,
|
||||
"wfo": "JAN"
|
||||
}
|
||||
},
|
||||
@@ -624,8 +624,8 @@
|
||||
"lat": 30.3322,
|
||||
"lon": -81.6556,
|
||||
"point": {
|
||||
"x": 65,
|
||||
"y": 64,
|
||||
"x": 66,
|
||||
"y": 65,
|
||||
"wfo": "JAX"
|
||||
}
|
||||
},
|
||||
@@ -644,8 +644,8 @@
|
||||
"lat": 39.1142,
|
||||
"lon": -94.6275,
|
||||
"point": {
|
||||
"x": 41,
|
||||
"y": 50,
|
||||
"x": 42,
|
||||
"y": 51,
|
||||
"wfo": "EAX"
|
||||
}
|
||||
},
|
||||
@@ -654,8 +654,8 @@
|
||||
"lat": 24.5557,
|
||||
"lon": -81.7826,
|
||||
"point": {
|
||||
"x": 61,
|
||||
"y": 47,
|
||||
"x": 62,
|
||||
"y": 48,
|
||||
"wfo": "KEY"
|
||||
}
|
||||
},
|
||||
@@ -684,8 +684,8 @@
|
||||
"lat": 36.175,
|
||||
"lon": -115.1372,
|
||||
"point": {
|
||||
"x": 122,
|
||||
"y": 97,
|
||||
"x": 123,
|
||||
"y": 98,
|
||||
"wfo": "VEF"
|
||||
}
|
||||
},
|
||||
@@ -704,8 +704,8 @@
|
||||
"lat": 40.8,
|
||||
"lon": -96.667,
|
||||
"point": {
|
||||
"x": 56,
|
||||
"y": 38,
|
||||
"x": 57,
|
||||
"y": 39,
|
||||
"wfo": "OAX"
|
||||
}
|
||||
},
|
||||
@@ -714,8 +714,8 @@
|
||||
"lat": 33.767,
|
||||
"lon": -118.1892,
|
||||
"point": {
|
||||
"x": 154,
|
||||
"y": 31,
|
||||
"x": 155,
|
||||
"y": 32,
|
||||
"wfo": "LOX"
|
||||
}
|
||||
},
|
||||
@@ -724,8 +724,8 @@
|
||||
"lat": 38.2542,
|
||||
"lon": -85.7594,
|
||||
"point": {
|
||||
"x": 49,
|
||||
"y": 77,
|
||||
"x": 50,
|
||||
"y": 78,
|
||||
"wfo": "LMK"
|
||||
}
|
||||
},
|
||||
@@ -734,8 +734,8 @@
|
||||
"lat": 42.9956,
|
||||
"lon": -71.4548,
|
||||
"point": {
|
||||
"x": 41,
|
||||
"y": 20,
|
||||
"x": 42,
|
||||
"y": 21,
|
||||
"wfo": "GYX"
|
||||
}
|
||||
},
|
||||
@@ -744,8 +744,8 @@
|
||||
"lat": 35.1495,
|
||||
"lon": -90.049,
|
||||
"point": {
|
||||
"x": 41,
|
||||
"y": 66,
|
||||
"x": 42,
|
||||
"y": 67,
|
||||
"wfo": "MEG"
|
||||
}
|
||||
},
|
||||
@@ -754,8 +754,8 @@
|
||||
"lat": 43.0389,
|
||||
"lon": -87.9065,
|
||||
"point": {
|
||||
"x": 87,
|
||||
"y": 64,
|
||||
"x": 88,
|
||||
"y": 65,
|
||||
"wfo": "MKX"
|
||||
}
|
||||
},
|
||||
@@ -764,8 +764,8 @@
|
||||
"lat": 30.6944,
|
||||
"lon": -88.043,
|
||||
"point": {
|
||||
"x": 51,
|
||||
"y": 66,
|
||||
"x": 52,
|
||||
"y": 67,
|
||||
"wfo": "MOB"
|
||||
}
|
||||
},
|
||||
@@ -774,8 +774,8 @@
|
||||
"lat": 32.3668,
|
||||
"lon": -86.3,
|
||||
"point": {
|
||||
"x": 80,
|
||||
"y": 34,
|
||||
"x": 81,
|
||||
"y": 35,
|
||||
"wfo": "BMX"
|
||||
}
|
||||
},
|
||||
@@ -784,8 +784,8 @@
|
||||
"lat": 44.2601,
|
||||
"lon": -72.5754,
|
||||
"point": {
|
||||
"x": 110,
|
||||
"y": 49,
|
||||
"x": 111,
|
||||
"y": 50,
|
||||
"wfo": "BTV"
|
||||
}
|
||||
},
|
||||
@@ -794,8 +794,8 @@
|
||||
"lat": 36.1659,
|
||||
"lon": -86.7844,
|
||||
"point": {
|
||||
"x": 49,
|
||||
"y": 56,
|
||||
"x": 50,
|
||||
"y": 57,
|
||||
"wfo": "OHX"
|
||||
}
|
||||
},
|
||||
@@ -804,8 +804,8 @@
|
||||
"lat": 40.7357,
|
||||
"lon": -74.1724,
|
||||
"point": {
|
||||
"x": 26,
|
||||
"y": 34,
|
||||
"x": 27,
|
||||
"y": 35,
|
||||
"wfo": "OKX"
|
||||
}
|
||||
},
|
||||
@@ -814,8 +814,8 @@
|
||||
"lat": 41.3081,
|
||||
"lon": -72.9282,
|
||||
"point": {
|
||||
"x": 65,
|
||||
"y": 67,
|
||||
"x": 66,
|
||||
"y": 68,
|
||||
"wfo": "OKX"
|
||||
}
|
||||
},
|
||||
@@ -845,7 +845,7 @@
|
||||
"lon": -97.5164,
|
||||
"point": {
|
||||
"x": 97,
|
||||
"y": 93,
|
||||
"y": 94,
|
||||
"wfo": "OUN"
|
||||
}
|
||||
},
|
||||
@@ -854,8 +854,8 @@
|
||||
"lat": 41.2586,
|
||||
"lon": -95.9378,
|
||||
"point": {
|
||||
"x": 82,
|
||||
"y": 59,
|
||||
"x": 83,
|
||||
"y": 60,
|
||||
"wfo": "OAX"
|
||||
}
|
||||
},
|
||||
@@ -864,8 +864,8 @@
|
||||
"lat": 33.4484,
|
||||
"lon": -112.074,
|
||||
"point": {
|
||||
"x": 158,
|
||||
"y": 57,
|
||||
"x": 159,
|
||||
"y": 58,
|
||||
"wfo": "PSR"
|
||||
}
|
||||
},
|
||||
@@ -874,8 +874,8 @@
|
||||
"lat": 44.3683,
|
||||
"lon": -100.351,
|
||||
"point": {
|
||||
"x": 54,
|
||||
"y": 43,
|
||||
"x": 55,
|
||||
"y": 44,
|
||||
"wfo": "ABR"
|
||||
}
|
||||
},
|
||||
@@ -884,8 +884,8 @@
|
||||
"lat": 43.6615,
|
||||
"lon": -70.2553,
|
||||
"point": {
|
||||
"x": 75,
|
||||
"y": 58,
|
||||
"x": 76,
|
||||
"y": 59,
|
||||
"wfo": "GYX"
|
||||
}
|
||||
},
|
||||
@@ -894,8 +894,8 @@
|
||||
"lat": 45.5234,
|
||||
"lon": -122.6762,
|
||||
"point": {
|
||||
"x": 112,
|
||||
"y": 103,
|
||||
"x": 113,
|
||||
"y": 104,
|
||||
"wfo": "PQR"
|
||||
}
|
||||
},
|
||||
@@ -914,8 +914,8 @@
|
||||
"lat": 35.7721,
|
||||
"lon": -78.6386,
|
||||
"point": {
|
||||
"x": 74,
|
||||
"y": 56,
|
||||
"x": 75,
|
||||
"y": 57,
|
||||
"wfo": "RAH"
|
||||
}
|
||||
},
|
||||
@@ -924,8 +924,8 @@
|
||||
"lat": 39.4986,
|
||||
"lon": -119.7681,
|
||||
"point": {
|
||||
"x": 45,
|
||||
"y": 104,
|
||||
"x": 46,
|
||||
"y": 105,
|
||||
"wfo": "REV"
|
||||
}
|
||||
},
|
||||
@@ -934,8 +934,8 @@
|
||||
"lat": 38.7725,
|
||||
"lon": -112.0841,
|
||||
"point": {
|
||||
"x": 81,
|
||||
"y": 86,
|
||||
"x": 82,
|
||||
"y": 87,
|
||||
"wfo": "SLC"
|
||||
}
|
||||
},
|
||||
@@ -944,8 +944,8 @@
|
||||
"lat": 37.5538,
|
||||
"lon": -77.4603,
|
||||
"point": {
|
||||
"x": 44,
|
||||
"y": 76,
|
||||
"x": 45,
|
||||
"y": 77,
|
||||
"wfo": "AKQ"
|
||||
}
|
||||
},
|
||||
@@ -954,8 +954,8 @@
|
||||
"lat": 37.271,
|
||||
"lon": -79.9414,
|
||||
"point": {
|
||||
"x": 73,
|
||||
"y": 68,
|
||||
"x": 74,
|
||||
"y": 69,
|
||||
"wfo": "RNK"
|
||||
}
|
||||
},
|
||||
@@ -964,8 +964,8 @@
|
||||
"lat": 38.5816,
|
||||
"lon": -121.4944,
|
||||
"point": {
|
||||
"x": 40,
|
||||
"y": 67,
|
||||
"x": 41,
|
||||
"y": 68,
|
||||
"wfo": "STO"
|
||||
}
|
||||
},
|
||||
@@ -974,8 +974,8 @@
|
||||
"lat": 40.7608,
|
||||
"lon": -111.891,
|
||||
"point": {
|
||||
"x": 99,
|
||||
"y": 174,
|
||||
"x": 100,
|
||||
"y": 175,
|
||||
"wfo": "SLC"
|
||||
}
|
||||
},
|
||||
@@ -984,8 +984,8 @@
|
||||
"lat": 29.4241,
|
||||
"lon": -98.4936,
|
||||
"point": {
|
||||
"x": 125,
|
||||
"y": 53,
|
||||
"x": 126,
|
||||
"y": 54,
|
||||
"wfo": "EWX"
|
||||
}
|
||||
},
|
||||
@@ -994,8 +994,8 @@
|
||||
"lat": 32.7153,
|
||||
"lon": -117.1573,
|
||||
"point": {
|
||||
"x": 56,
|
||||
"y": 13,
|
||||
"x": 57,
|
||||
"y": 14,
|
||||
"wfo": "SGX"
|
||||
}
|
||||
},
|
||||
@@ -1014,8 +1014,8 @@
|
||||
"lat": 35.687,
|
||||
"lon": -105.9378,
|
||||
"point": {
|
||||
"x": 125,
|
||||
"y": 143,
|
||||
"x": 126,
|
||||
"y": 146,
|
||||
"wfo": "ABQ"
|
||||
}
|
||||
},
|
||||
@@ -1024,8 +1024,8 @@
|
||||
"lat": 32.0835,
|
||||
"lon": -81.0998,
|
||||
"point": {
|
||||
"x": 46,
|
||||
"y": 40,
|
||||
"x": 47,
|
||||
"y": 41,
|
||||
"wfo": "CHS"
|
||||
}
|
||||
},
|
||||
@@ -1034,7 +1034,7 @@
|
||||
"lat": 32.5251,
|
||||
"lon": -93.7502,
|
||||
"point": {
|
||||
"x": 76,
|
||||
"x": 74,
|
||||
"y": 69,
|
||||
"wfo": "SHV"
|
||||
}
|
||||
@@ -1074,8 +1074,8 @@
|
||||
"lat": 39.8017,
|
||||
"lon": -89.6437,
|
||||
"point": {
|
||||
"x": 47,
|
||||
"y": 55,
|
||||
"x": 48,
|
||||
"y": 56,
|
||||
"wfo": "ILX"
|
||||
}
|
||||
},
|
||||
@@ -1094,8 +1094,8 @@
|
||||
"lat": 37.2153,
|
||||
"lon": -93.2982,
|
||||
"point": {
|
||||
"x": 66,
|
||||
"y": 34,
|
||||
"x": 67,
|
||||
"y": 35,
|
||||
"wfo": "SGF"
|
||||
}
|
||||
},
|
||||
@@ -1104,8 +1104,8 @@
|
||||
"lat": 41.6639,
|
||||
"lon": -83.5552,
|
||||
"point": {
|
||||
"x": 18,
|
||||
"y": 66,
|
||||
"x": 19,
|
||||
"y": 67,
|
||||
"wfo": "CLE"
|
||||
}
|
||||
},
|
||||
@@ -1114,8 +1114,8 @@
|
||||
"lat": 36.154,
|
||||
"lon": -95.9928,
|
||||
"point": {
|
||||
"x": 40,
|
||||
"y": 104,
|
||||
"x": 41,
|
||||
"y": 105,
|
||||
"wfo": "TSA"
|
||||
}
|
||||
},
|
||||
@@ -1124,8 +1124,8 @@
|
||||
"lat": 36.8529,
|
||||
"lon": -75.978,
|
||||
"point": {
|
||||
"x": 100,
|
||||
"y": 52,
|
||||
"x": 101,
|
||||
"y": 53,
|
||||
"wfo": "AKQ"
|
||||
}
|
||||
},
|
||||
@@ -1134,8 +1134,8 @@
|
||||
"lat": 37.6922,
|
||||
"lon": -97.3375,
|
||||
"point": {
|
||||
"x": 61,
|
||||
"y": 33,
|
||||
"x": 62,
|
||||
"y": 34,
|
||||
"wfo": "ICT"
|
||||
}
|
||||
},
|
||||
@@ -1144,18 +1144,18 @@
|
||||
"lat": 34.2257,
|
||||
"lon": -77.9447,
|
||||
"point": {
|
||||
"x": 88,
|
||||
"y": 67,
|
||||
"x": 89,
|
||||
"y": 68,
|
||||
"wfo": "ILM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"city": "Tuscan",
|
||||
"city": "Tucson",
|
||||
"lat": 32.2216,
|
||||
"lon": -110.9698,
|
||||
"point": {
|
||||
"x": 90,
|
||||
"y": 48,
|
||||
"x": 91,
|
||||
"y": 49,
|
||||
"wfo": "TWC"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
"Latitude": 33.749,
|
||||
"Longitude": -84.388,
|
||||
"point": {
|
||||
"x": 50,
|
||||
"y": 86,
|
||||
"x": 51,
|
||||
"y": 87,
|
||||
"wfo": "FFC"
|
||||
}
|
||||
},
|
||||
@@ -24,8 +24,8 @@
|
||||
"Latitude": 41.9796,
|
||||
"Longitude": -87.9045,
|
||||
"point": {
|
||||
"x": 65,
|
||||
"y": 76,
|
||||
"x": 66,
|
||||
"y": 77,
|
||||
"wfo": "LOT"
|
||||
}
|
||||
},
|
||||
@@ -34,8 +34,8 @@
|
||||
"Latitude": 41.4995,
|
||||
"Longitude": -81.6954,
|
||||
"point": {
|
||||
"x": 82,
|
||||
"y": 64,
|
||||
"x": 83,
|
||||
"y": 65,
|
||||
"wfo": "CLE"
|
||||
}
|
||||
},
|
||||
@@ -44,8 +44,8 @@
|
||||
"Latitude": 32.8959,
|
||||
"Longitude": -97.0372,
|
||||
"point": {
|
||||
"x": 79,
|
||||
"y": 108,
|
||||
"x": 80,
|
||||
"y": 109,
|
||||
"wfo": "FWD"
|
||||
}
|
||||
},
|
||||
@@ -54,8 +54,8 @@
|
||||
"Latitude": 39.7391,
|
||||
"Longitude": -104.9847,
|
||||
"point": {
|
||||
"x": 62,
|
||||
"y": 60,
|
||||
"x": 63,
|
||||
"y": 61,
|
||||
"wfo": "BOU"
|
||||
}
|
||||
},
|
||||
@@ -64,8 +64,8 @@
|
||||
"Latitude": 42.3314,
|
||||
"Longitude": -83.0457,
|
||||
"point": {
|
||||
"x": 65,
|
||||
"y": 33,
|
||||
"x": 66,
|
||||
"y": 34,
|
||||
"wfo": "DTX"
|
||||
}
|
||||
},
|
||||
@@ -94,8 +94,8 @@
|
||||
"Latitude": 39.7684,
|
||||
"Longitude": -86.158,
|
||||
"point": {
|
||||
"x": 57,
|
||||
"y": 68,
|
||||
"x": 58,
|
||||
"y": 69,
|
||||
"wfo": "IND"
|
||||
}
|
||||
},
|
||||
@@ -104,8 +104,8 @@
|
||||
"Latitude": 34.0522,
|
||||
"Longitude": -118.2437,
|
||||
"point": {
|
||||
"x": 154,
|
||||
"y": 44,
|
||||
"x": 155,
|
||||
"y": 45,
|
||||
"wfo": "LOX"
|
||||
}
|
||||
},
|
||||
@@ -114,8 +114,8 @@
|
||||
"Latitude": 25.7743,
|
||||
"Longitude": -80.1937,
|
||||
"point": {
|
||||
"x": 109,
|
||||
"y": 50,
|
||||
"x": 110,
|
||||
"y": 51,
|
||||
"wfo": "MFL"
|
||||
}
|
||||
},
|
||||
@@ -124,8 +124,8 @@
|
||||
"Latitude": 44.98,
|
||||
"Longitude": -93.2638,
|
||||
"point": {
|
||||
"x": 107,
|
||||
"y": 71,
|
||||
"x": 108,
|
||||
"y": 72,
|
||||
"wfo": "MPX"
|
||||
}
|
||||
},
|
||||
@@ -134,8 +134,8 @@
|
||||
"Latitude": 40.7142,
|
||||
"Longitude": -74.0059,
|
||||
"point": {
|
||||
"x": 32,
|
||||
"y": 34,
|
||||
"x": 33,
|
||||
"y": 35,
|
||||
"wfo": "OKX"
|
||||
}
|
||||
},
|
||||
@@ -144,8 +144,8 @@
|
||||
"Latitude": 36.8468,
|
||||
"Longitude": -76.2852,
|
||||
"point": {
|
||||
"x": 89,
|
||||
"y": 51,
|
||||
"x": 90,
|
||||
"y": 52,
|
||||
"wfo": "AKQ"
|
||||
}
|
||||
},
|
||||
@@ -164,8 +164,8 @@
|
||||
"Latitude": 39.9523,
|
||||
"Longitude": -75.1638,
|
||||
"point": {
|
||||
"x": 49,
|
||||
"y": 75,
|
||||
"x": 50,
|
||||
"y": 76,
|
||||
"wfo": "PHI"
|
||||
}
|
||||
},
|
||||
@@ -174,8 +174,8 @@
|
||||
"Latitude": 40.4406,
|
||||
"Longitude": -79.9959,
|
||||
"point": {
|
||||
"x": 77,
|
||||
"y": 65,
|
||||
"x": 78,
|
||||
"y": 66,
|
||||
"wfo": "PBZ"
|
||||
}
|
||||
},
|
||||
@@ -184,8 +184,8 @@
|
||||
"Latitude": 38.6273,
|
||||
"Longitude": -90.1979,
|
||||
"point": {
|
||||
"x": 94,
|
||||
"y": 73,
|
||||
"x": 95,
|
||||
"y": 74,
|
||||
"wfo": "LSX"
|
||||
}
|
||||
},
|
||||
@@ -204,8 +204,8 @@
|
||||
"Latitude": 47.6062,
|
||||
"Longitude": -122.3321,
|
||||
"point": {
|
||||
"x": 124,
|
||||
"y": 67,
|
||||
"x": 125,
|
||||
"y": 68,
|
||||
"wfo": "SEW"
|
||||
}
|
||||
},
|
||||
@@ -214,8 +214,8 @@
|
||||
"Latitude": 43.0481,
|
||||
"Longitude": -76.1474,
|
||||
"point": {
|
||||
"x": 51,
|
||||
"y": 98,
|
||||
"x": 52,
|
||||
"y": 99,
|
||||
"wfo": "BGM"
|
||||
}
|
||||
},
|
||||
@@ -224,8 +224,8 @@
|
||||
"Latitude": 27.9475,
|
||||
"Longitude": -82.4584,
|
||||
"point": {
|
||||
"x": 70,
|
||||
"y": 96,
|
||||
"x": 71,
|
||||
"y": 97,
|
||||
"wfo": "TBW"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -575,7 +575,7 @@
|
||||
"lon": -77.9447
|
||||
},
|
||||
{
|
||||
"city": "Tuscan",
|
||||
"city": "Tucson",
|
||||
"lat": 32.2216,
|
||||
"lon": -110.9698
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// look up points for each regional city
|
||||
const fs = require('fs/promises');
|
||||
const chunk = require('./chunk');
|
||||
const https = require('./https');
|
||||
|
||||
(async () => {
|
||||
// source data
|
||||
const regionalCities = JSON.parse(await fs.readFile('./datagenerators/regionalcities-raw.json'));
|
||||
|
||||
const result = [];
|
||||
const dataChunks = chunk(regionalCities, 5);
|
||||
|
||||
// for loop intentional for use of await
|
||||
// this keeps the api from getting overwhelmed
|
||||
for (let i = 0; i < dataChunks.length; i += 1) {
|
||||
const cityChunk = dataChunks[i];
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const chunkResult = await Promise.all(cityChunk.map(async (city) => {
|
||||
try {
|
||||
const data = await https(`https://api.weather.gov/points/${city.lat},${city.lon}`);
|
||||
const point = JSON.parse(data);
|
||||
return {
|
||||
...city,
|
||||
point: {
|
||||
x: point.properties.gridX,
|
||||
y: point.properties.gridY,
|
||||
wfo: point.properties.gridId,
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return city;
|
||||
}
|
||||
}));
|
||||
|
||||
result.push(...chunkResult);
|
||||
}
|
||||
|
||||
await fs.writeFile('./datagenerators/output/regionalcities.json', JSON.stringify(result, null, ' '));
|
||||
})();
|
||||
40
datagenerators/regionalcities.mjs
Normal file
@@ -0,0 +1,40 @@
|
||||
// look up points for each regional city
|
||||
import fs from 'fs/promises';
|
||||
|
||||
import chunk from './chunk.mjs';
|
||||
import https from './https.mjs';
|
||||
|
||||
// source data
|
||||
const regionalCities = JSON.parse(await fs.readFile('./datagenerators/regionalcities-raw.json'));
|
||||
|
||||
const result = [];
|
||||
const dataChunks = chunk(regionalCities, 5);
|
||||
|
||||
// for loop intentional for use of await
|
||||
// this keeps the api from getting overwhelmed
|
||||
for (let i = 0; i < dataChunks.length; i += 1) {
|
||||
const cityChunk = dataChunks[i];
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const chunkResult = await Promise.all(cityChunk.map(async (city) => {
|
||||
try {
|
||||
const data = await https(`https://api.weather.gov/points/${city.lat},${city.lon}`);
|
||||
const point = JSON.parse(data);
|
||||
return {
|
||||
...city,
|
||||
point: {
|
||||
x: point.properties.gridX,
|
||||
y: point.properties.gridY,
|
||||
wfo: point.properties.gridId,
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return city;
|
||||
}
|
||||
}));
|
||||
|
||||
result.push(...chunkResult);
|
||||
}
|
||||
|
||||
await fs.writeFile('./datagenerators/output/regionalcities.json', JSON.stringify(result, null, ' '));
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = [
|
||||
export default [
|
||||
'AZ',
|
||||
'AL',
|
||||
'AK',
|
||||
@@ -50,4 +50,4 @@ module.exports = [
|
||||
'WI',
|
||||
'WY',
|
||||
'PR',
|
||||
];
|
||||
];
|
||||
@@ -1,73 +0,0 @@
|
||||
// list all stations in a single file
|
||||
// only find stations with 4 letter codes
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('./https');
|
||||
const states = require('./stations-states');
|
||||
const chunk = require('./chunk');
|
||||
|
||||
// skip stations starting with these letters
|
||||
const skipStations = ['U', 'C', 'H', 'W', 'Y', 'T', 'S', 'M', 'O', 'L', 'A', 'F', 'B', 'N', 'V', 'R', 'D', 'E', 'I', 'G', 'J'];
|
||||
|
||||
// immediately invoked function so we can access async/await
|
||||
const start = async () => {
|
||||
// chunk the list of states
|
||||
const chunkStates = chunk(states, 5);
|
||||
|
||||
// store output
|
||||
const output = {};
|
||||
|
||||
// process all chunks
|
||||
for (let i = 0; i < chunkStates.length; i += 1) {
|
||||
const stateChunk = chunkStates[i];
|
||||
// loop through states
|
||||
|
||||
stateChunk.forEach(async (state) => {
|
||||
try {
|
||||
let stations;
|
||||
let next = `https://api.weather.gov/stations?state=${state}`;
|
||||
do {
|
||||
// get list and parse the JSON
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const stationsRaw = await https(next);
|
||||
stations = JSON.parse(stationsRaw);
|
||||
// filter stations for 4 letter identifiers
|
||||
const stationsFiltered4 = stations.features.filter((station) => station.properties.stationIdentifier.match(/^[A-Z]{4}$/));
|
||||
// filter against starting letter
|
||||
const stationsFiltered = stationsFiltered4.filter((station) => !skipStations.includes(station.properties.stationIdentifier.slice(0, 1)));
|
||||
// add each resulting station to the output
|
||||
stationsFiltered.forEach((station) => {
|
||||
const id = station.properties.stationIdentifier;
|
||||
if (output[id]) {
|
||||
console.log(`Duplicate station: ${state}-${id}`);
|
||||
return;
|
||||
}
|
||||
output[id] = {
|
||||
id,
|
||||
city: station.properties.name,
|
||||
state,
|
||||
lat: station.geometry.coordinates[1],
|
||||
lon: station.geometry.coordinates[0],
|
||||
};
|
||||
});
|
||||
next = stations?.pagination?.next;
|
||||
// write the output
|
||||
// write the output
|
||||
fs.writeFileSync(path.join(__dirname, 'output/stations.json'), JSON.stringify(output, null, 2));
|
||||
}
|
||||
while (next && stations.features.length > 0);
|
||||
console.log(`Complete: ${state}`);
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(`Unable to get state: ${state}`);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// immediately invoked function allows access to async
|
||||
(async () => {
|
||||
await start();
|
||||
})();
|
||||
67
datagenerators/stations.mjs
Normal file
@@ -0,0 +1,67 @@
|
||||
// list all stations in a single file
|
||||
// only find stations with 4 letter codes
|
||||
|
||||
import { writeFileSync } from 'fs';
|
||||
import https from './https.mjs';
|
||||
import states from './stations-states.mjs';
|
||||
import chunk from './chunk.mjs';
|
||||
|
||||
// skip stations starting with these letters
|
||||
const skipStations = ['U', 'C', 'H', 'W', 'Y', 'T', 'S', 'M', 'O', 'L', 'A', 'F', 'B', 'N', 'V', 'R', 'D', 'E', 'I', 'G', 'J'];
|
||||
|
||||
// chunk the list of states
|
||||
const chunkStates = chunk(states, 1);
|
||||
|
||||
// store output
|
||||
const output = {};
|
||||
|
||||
// process all chunks
|
||||
for (let i = 0; i < chunkStates.length; i += 1) {
|
||||
const stateChunk = chunkStates[i];
|
||||
// loop through states
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await Promise.allSettled(stateChunk.map(async (state) => {
|
||||
try {
|
||||
let stations;
|
||||
let next = `https://api.weather.gov/stations?state=${state}`;
|
||||
let round = 0;
|
||||
do {
|
||||
console.log(`Getting: ${state}-${round}`);
|
||||
// get list and parse the JSON
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const stationsRaw = await https(next);
|
||||
stations = JSON.parse(stationsRaw);
|
||||
// filter stations for 4 letter identifiers
|
||||
const stationsFiltered4 = stations.features.filter((station) => station.properties.stationIdentifier.match(/^[A-Z]{4}$/));
|
||||
// filter against starting letter
|
||||
const stationsFiltered = stationsFiltered4.filter((station) => !skipStations.includes(station.properties.stationIdentifier.slice(0, 1)));
|
||||
// add each resulting station to the output
|
||||
stationsFiltered.forEach((station) => {
|
||||
const id = station.properties.stationIdentifier;
|
||||
if (output[id]) {
|
||||
console.log(`Duplicate station: ${state}-${id}`);
|
||||
return;
|
||||
}
|
||||
output[id] = {
|
||||
id,
|
||||
city: station.properties.name,
|
||||
state,
|
||||
lat: station.geometry.coordinates[1],
|
||||
lon: station.geometry.coordinates[0],
|
||||
};
|
||||
});
|
||||
next = stations?.pagination?.next;
|
||||
round += 1;
|
||||
// write the output
|
||||
writeFileSync('./datagenerators/output/stations.json', JSON.stringify(output, null, 2));
|
||||
}
|
||||
while (next && stations.features.length > 0);
|
||||
console.log(`Complete: ${state}`);
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(`Unable to get state: ${state}`);
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// look up points for each travel city
|
||||
const fs = require('fs/promises');
|
||||
const chunk = require('./chunk');
|
||||
const https = require('./https');
|
||||
|
||||
(async () => {
|
||||
// source data
|
||||
const travelCities = JSON.parse(await fs.readFile('./datagenerators/travelcities-raw.json'));
|
||||
|
||||
const result = [];
|
||||
const dataChunks = chunk(travelCities, 5);
|
||||
|
||||
// for loop intentional for use of await
|
||||
// this keeps the api from getting overwhelmed
|
||||
for (let i = 0; i < dataChunks.length; i += 1) {
|
||||
const cityChunk = dataChunks[i];
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const chunkResult = await Promise.all(cityChunk.map(async (city) => {
|
||||
try {
|
||||
const data = await https(`https://api.weather.gov/points/${city.Latitude},${city.Longitude}`);
|
||||
const point = JSON.parse(data);
|
||||
return {
|
||||
...city,
|
||||
point: {
|
||||
x: point.properties.gridX,
|
||||
y: point.properties.gridY,
|
||||
wfo: point.properties.gridId,
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return city;
|
||||
}
|
||||
}));
|
||||
|
||||
result.push(...chunkResult);
|
||||
}
|
||||
|
||||
await fs.writeFile('./datagenerators/output/travelcities.json', JSON.stringify(result, null, ' '));
|
||||
})();
|
||||
39
datagenerators/travelcities.mjs
Normal file
@@ -0,0 +1,39 @@
|
||||
// look up points for each travel city
|
||||
import { readFile, writeFile } from 'fs/promises';
|
||||
import chunk from './chunk.mjs';
|
||||
import https from './https.mjs';
|
||||
|
||||
// source data
|
||||
const travelCities = JSON.parse(await readFile('./datagenerators/travelcities-raw.json'));
|
||||
|
||||
const result = [];
|
||||
const dataChunks = chunk(travelCities, 5);
|
||||
|
||||
// for loop intentional for use of await
|
||||
// this keeps the api from getting overwhelmed
|
||||
for (let i = 0; i < dataChunks.length; i += 1) {
|
||||
const cityChunk = dataChunks[i];
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const chunkResult = await Promise.all(cityChunk.map(async (city) => {
|
||||
try {
|
||||
const data = await https(`https://api.weather.gov/points/${city.Latitude},${city.Longitude}`);
|
||||
const point = JSON.parse(data);
|
||||
return {
|
||||
...city,
|
||||
point: {
|
||||
x: point.properties.gridX,
|
||||
y: point.properties.gridY,
|
||||
wfo: point.properties.gridId,
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return city;
|
||||
}
|
||||
}));
|
||||
|
||||
result.push(...chunkResult);
|
||||
}
|
||||
|
||||
await writeFile('./datagenerators/output/travelcities.json', JSON.stringify(result, null, ' '));
|
||||
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import 'dotenv/config';
|
||||
import {
|
||||
src, dest, series, parallel,
|
||||
} from 'gulp';
|
||||
@@ -6,9 +7,9 @@ import concat from 'gulp-concat';
|
||||
import terser from 'gulp-terser';
|
||||
import ejs from 'gulp-ejs';
|
||||
import rename from 'gulp-rename';
|
||||
import htmlmin from 'gulp-htmlmin';
|
||||
import htmlmin from 'gulp-html-minifier-terser';
|
||||
import { deleteAsync } from 'del';
|
||||
import s3Upload from 'gulp-s3-upload';
|
||||
import s3Upload from 'gulp-s3-uploader';
|
||||
import webpack from 'webpack-stream';
|
||||
import TerserPlugin from 'terser-webpack-plugin';
|
||||
import { readFile } from 'fs/promises';
|
||||
@@ -32,8 +33,6 @@ const jsSourcesData = [
|
||||
|
||||
const webpackOptions = {
|
||||
mode: 'production',
|
||||
// mode: 'development',
|
||||
// devtool: 'source-map',
|
||||
output: {
|
||||
filename: 'ws.min.js',
|
||||
},
|
||||
@@ -62,8 +61,6 @@ const compressJsData = () => src(jsSourcesData)
|
||||
.pipe(dest(RESOURCES_PATH));
|
||||
|
||||
const jsVendorSources = [
|
||||
'server/scripts/vendor/auto/jquery.js',
|
||||
'server/scripts/vendor/jquery.autocomplete.min.js',
|
||||
'server/scripts/vendor/auto/nosleep.js',
|
||||
'server/scripts/vendor/auto/swiped-events.js',
|
||||
'server/scripts/vendor/auto/suncalc.js',
|
||||
@@ -79,6 +76,7 @@ const mjsSources = [
|
||||
'server/scripts/modules/hazards.mjs',
|
||||
'server/scripts/modules/currentweather.mjs',
|
||||
'server/scripts/modules/almanac.mjs',
|
||||
'server/scripts/modules/spc-outlook.mjs',
|
||||
'server/scripts/modules/icons.mjs',
|
||||
'server/scripts/modules/extendedforecast.mjs',
|
||||
'server/scripts/modules/hourly.mjs',
|
||||
@@ -140,7 +138,7 @@ const uploadSources = [
|
||||
];
|
||||
const upload = () => src(uploadSources, { base: './dist', encoding: false })
|
||||
.pipe(s3({
|
||||
Bucket: 'weatherstar',
|
||||
Bucket: process.env.BUCKET,
|
||||
StorageClass: 'STANDARD',
|
||||
maps: {
|
||||
CacheControl: (keyname) => {
|
||||
@@ -154,17 +152,21 @@ const upload = () => src(uploadSources, { base: './dist', encoding: false })
|
||||
const imageSources = [
|
||||
'server/fonts/**',
|
||||
'server/images/**',
|
||||
'!server/images/gimp/**',
|
||||
];
|
||||
const uploadImages = () => src(imageSources, { base: './server', encoding: false })
|
||||
.pipe(
|
||||
s3({
|
||||
Bucket: 'weatherstar',
|
||||
Bucket: process.env.BUCKET,
|
||||
StorageClass: 'STANDARD',
|
||||
maps: {
|
||||
CacheControl: () => 'max-age=31536000',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const invalidate = () => cloudfront.send(new CreateInvalidationCommand({
|
||||
DistributionId: 'E9171A4KV8KCW',
|
||||
DistributionId: process.env.DISTRIBUTION_ID,
|
||||
InvalidationBatch: {
|
||||
CallerReference: (new Date()).toLocaleString(),
|
||||
Paths: {
|
||||
@@ -190,4 +192,5 @@ export default publishFrontend;
|
||||
|
||||
export {
|
||||
buildDist,
|
||||
invalidate,
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ const vendorFiles = [
|
||||
'./node_modules/luxon/build/es6/luxon.js',
|
||||
'./node_modules/luxon/build/es6/luxon.js.map',
|
||||
'./node_modules/nosleep.js/dist/NoSleep.js',
|
||||
'./node_modules/jquery/dist/jquery.js',
|
||||
'./node_modules/suncalc/suncalc.js',
|
||||
'./node_modules/swiped-events/src/swiped-events.js',
|
||||
];
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import updateVendor from './gulp/update-vendor.mjs';
|
||||
import publishFrontend, { buildDist } from './gulp/publish-frontend.mjs'
|
||||
import publishFrontend, { buildDist, invalidate } from './gulp/publish-frontend.mjs';
|
||||
|
||||
export {
|
||||
updateVendor,
|
||||
publishFrontend,
|
||||
buildDist,
|
||||
invalidate,
|
||||
};
|
||||
|
||||
41
index.mjs
@@ -1,3 +1,4 @@
|
||||
import 'dotenv/config';
|
||||
import express from 'express';
|
||||
import fs from 'fs';
|
||||
import corsPassThru from './cors/index.mjs';
|
||||
@@ -12,15 +13,47 @@ const port = process.env.WS4KP_PORT ?? 8080;
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
// cors pass-thru to api.weather.gov
|
||||
app.get('/stations/*', corsPassThru);
|
||||
app.get('/Conus/*', radarPassThru);
|
||||
app.get('/products/*', outlookPassThru);
|
||||
app.get('/stations/*station', corsPassThru);
|
||||
app.get('/Conus/*radar', radarPassThru);
|
||||
app.get('/products/*product', outlookPassThru);
|
||||
app.get('/playlist.json', playlist);
|
||||
|
||||
// version
|
||||
const { version } = JSON.parse(fs.readFileSync('package.json'));
|
||||
|
||||
// read and parse environment variables to append to the query string
|
||||
// use the permalink (share) button on the web app to generate a starting point for your configuration
|
||||
// then take each key/value in the querystring and append WSQS_ to the beginning, and then replace any
|
||||
// hyphens with underscores in the key name
|
||||
// environment variables are read from the command line and .env file via the dotenv package
|
||||
|
||||
const qsVars = {};
|
||||
|
||||
Object.entries(process.env).forEach(([key, value]) => {
|
||||
// test for key matching pattern described above
|
||||
if (key.match(/^WSQS_[A-Za-z0-9_]+$/)) {
|
||||
// convert the key to a querystring formatted key
|
||||
const formattedKey = key.replace(/^WSQS_/, '').replaceAll('_', '-');
|
||||
qsVars[formattedKey] = value;
|
||||
}
|
||||
});
|
||||
|
||||
// single flag to determine if environment variables are present
|
||||
const hasQsVars = Object.entries(qsVars).length > 0;
|
||||
|
||||
// turn the environment query string into search params
|
||||
const defaultSearchParams = (new URLSearchParams(qsVars)).toString();
|
||||
|
||||
const index = (req, res) => {
|
||||
// test for no query string in request and if environment query string values were provided
|
||||
if (hasQsVars && Object.keys(req.query).length === 0) {
|
||||
// redirect the user to the query-string appended url
|
||||
const url = new URL(`${req.protocol}://${req.host}${req.url}`);
|
||||
url.search = defaultSearchParams;
|
||||
res.redirect(307, url.toString());
|
||||
return;
|
||||
}
|
||||
// return the standard page
|
||||
res.render('index', {
|
||||
production: false,
|
||||
version,
|
||||
@@ -38,7 +71,7 @@ if (process.env?.DIST === '1') {
|
||||
// debugging
|
||||
app.get('/index.html', index);
|
||||
app.get('/', index);
|
||||
app.get('*', express.static('./server'));
|
||||
app.get('*name', express.static('./server'));
|
||||
}
|
||||
|
||||
const server = app.listen(port, () => {
|
||||
|
||||
2971
package-lock.json
generated
13
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ws4kp",
|
||||
"version": "5.15.1",
|
||||
"version": "5.20.1",
|
||||
"description": "Welcome to the WeatherStar 4000+ project page!",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
@@ -32,23 +32,22 @@
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-ejs": "^5.1.0",
|
||||
"gulp-file": "^0.4.0",
|
||||
"gulp-htmlmin": "^5.0.1",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-s3-upload": "^1.7.3",
|
||||
"gulp-s3-uploader": "^1.0.6",
|
||||
"gulp-sass": "^6.0.0",
|
||||
"gulp-terser": "^2.0.0",
|
||||
"jquery": "^3.6.0",
|
||||
"jquery-touchswipe": "^1.6.19",
|
||||
"luxon": "^3.0.0",
|
||||
"nosleep.js": "^0.12.0",
|
||||
"sass": "^1.54.0",
|
||||
"suncalc": "^1.8.0",
|
||||
"swiped-events": "^1.1.4",
|
||||
"terser-webpack-plugin": "^5.3.6",
|
||||
"webpack-stream": "^7.0.0"
|
||||
"webpack-stream": "^7.0.0",
|
||||
"gulp-html-minifier-terser": "^7.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^16.5.0",
|
||||
"ejs": "^3.1.5",
|
||||
"express": "^4.17.1"
|
||||
"express": "^5.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
--Star 3000--
|
||||
|
||||
Star3000.ttf - Standard text style for most screens (and Travel Cities title header)
|
||||
Star3000 Small.ttf - Time/Date and some page headers
|
||||
Star3000 Large.ttf - Travel Cities Forecast (Forecast portion only)
|
||||
Star3000 Extra Large.ttf - Only used on some advertiser text
|
||||
Star3000 Extended.ttf - Only used on some advertiser text
|
||||
"Heavy" style is an emboldened version of the standard font (used on some STARs)
|
||||
|
||||
Star3000 Outline.ttf - A contrast border (stroke) that surrounds the Star3000.ttf base font. When used, must be as a text layer undeneath the base font (and is usually black in color).
|
||||
Star3000 Small Outline.ttf - A contrast border (stroke) that surrounds the Star3000 Small.ttf base font. When used, must be as a text layer undeneath the base font (and is usually black in color).
|
||||
Star3000 Large Outline.ttf - A contrast border (stroke) that surrounds the Star3000 Large.ttf base font. When used, must be as a text layer undeneath the base font (and is usually black in color).
|
||||
|
||||
***Outlines for other font styles are not currently available.
|
||||
|
||||
--Star 4000--
|
||||
|
||||
Star4000.ttf - Standard text style for zone forecast, observation tables, regional map cities, almanac, extended forecast day/weather/temperature headers, Current Conditions right half data and most page header titles (also Travel Cities title header before Nov. 1992)
|
||||
Star4000 Small.ttf - Time/Date, NWS Local Update page header, temperature header for Travel Cities Forecast (after Nov. 1992)
|
||||
Star4000 Large.ttf - City names and temperature data on Travel Cities Forecast (after Nov. 1992), Extended forecast temperature values (after Feb. 1991), Current Conditions temperature value (after Mar. 1991)
|
||||
Star4000 Large Compressed - Travel Cities Forecast (before Nov. 1992), regional map temperatures
|
||||
Star4000 Large Compressed Numbers - Temperature values on regional forecast/observation maps
|
||||
Star4000 Extended - A proportional width font used for the Current Conditions present weather description and wind data
|
||||
Star 4 Radar.ttf - Radar airport I.D.
|
||||
|
||||
--Star Jr.--
|
||||
|
||||
StarJr.ttf - Standard text style for most screens (and Travel Cities title header)
|
||||
StarJr Small.ttf - Time/Date and some page headers
|
||||
StarJr Compressed.ttf - Travel Cities Forecast
|
||||
@@ -1,4 +0,0 @@
|
||||
[Dolphin]
|
||||
PreviewsShown=true
|
||||
Timestamp=2020,10,1,21,36,7
|
||||
Version=4
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 582 B |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 890 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 110 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 925 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 273 B |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 982 B |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 717 B |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 110 B |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 451 B |
|
Before Width: | Height: | Size: 925 B |
|
Before Width: | Height: | Size: 467 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 358 B |