From 9c2f86b00a7d4a691c1333fb6cd3e606eb1a00e2 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 31 Jan 2022 00:30:05 -0600 Subject: [PATCH] Support loadable radar sites --- scwx-qt/res/config/radar_sites.json | 207 ++++++++++++++++++ scwx-qt/scwx-qt.cmake | 10 + scwx-qt/scwx-qt.qrc | 1 + scwx-qt/source/scwx/qt/config/radar_site.cpp | 157 +++++++++++++ scwx-qt/source/scwx/qt/config/radar_site.hpp | 45 ++++ scwx-qt/source/scwx/qt/util/json.cpp | 54 ++++- .../source/scwx/qt/config/radar_site.test.cpp | 36 +++ test/test.cmake | 3 + 8 files changed, 510 insertions(+), 3 deletions(-) create mode 100644 scwx-qt/res/config/radar_sites.json create mode 100644 scwx-qt/source/scwx/qt/config/radar_site.cpp create mode 100644 scwx-qt/source/scwx/qt/config/radar_site.hpp create mode 100644 test/source/scwx/qt/config/radar_site.test.cpp diff --git a/scwx-qt/res/config/radar_sites.json b/scwx-qt/res/config/radar_sites.json new file mode 100644 index 00000000..d0e81fdd --- /dev/null +++ b/scwx-qt/res/config/radar_sites.json @@ -0,0 +1,207 @@ +[ + { "type":"wsr88d", "id":"RODN", "lat":26.307796, "lon":127.903422, "country":"JPN", "state":"OKI", "place":"Kadena Air Base" }, + { "type":"wsr88d", "id":"RKSG", "lat":37.207652, "lon":127.285614, "country":"KOR", "state":"41", "place":"Camp Humphreys" }, + { "type":"wsr88d", "id":"RKJK", "lat":35.92417, "lon":126.62222, "country":"KOR", "state":"45", "place":"Kunsan Air Base" }, + { "type":"wsr88d", "id":"PABC", "lat":60.791987, "lon":-161.876539, "country":"USA", "state":"AK", "place":"Bethel" }, + { "type":"wsr88d", "id":"PAPD", "lat":65.0351238, "lon":-147.5014222, "country":"USA", "state":"AK", "place":"Fairbanks/Pedro Dome" }, + { "type":"wsr88d", "id":"PAHG", "lat":60.6156335, "lon":-151.2832296, "country":"USA", "state":"AK", "place":"Kenai" }, + { "type":"wsr88d", "id":"PAKC", "lat":58.6794558, "lon":-156.6293335, "country":"USA", "state":"AK", "place":"King Salmon" }, + { "type":"wsr88d", "id":"PAIH", "lat":59.46194, "lon":-146.30111, "country":"USA", "state":"AK", "place":"Middleton Island" }, + { "type":"wsr88d", "id":"PAEC", "lat":64.5114973, "lon":-165.2949071, "country":"USA", "state":"AK", "place":"Nome" }, + { "type":"wsr88d", "id":"PACG", "lat":56.85214, "lon":-135.552417, "country":"USA", "state":"AK", "place":"Sitka/Biorka Island" }, + { "type":"wsr88d", "id":"KBMX", "lat":33.1722806, "lon":-86.7698425, "country":"USA", "state":"AL", "place":"Birmingham" }, + { "type":"wsr88d", "id":"KEOX", "lat":31.4605622, "lon":-85.4592401, "country":"USA", "state":"AL", "place":"Fort Rucker" }, + { "type":"wsr88d", "id":"KHTX", "lat":34.930508, "lon":-86.0837388, "country":"USA", "state":"AL", "place":"Huntsville" }, + { "type":"wsr88d", "id":"KMXX", "lat":32.5366608, "lon":-85.7897848, "country":"USA", "state":"AL", "place":"Maxwell AFB" }, + { "type":"wsr88d", "id":"KMOB", "lat":30.6795378, "lon":-88.2397816, "country":"USA", "state":"AL", "place":"Mobile" }, + { "type":"wsr88d", "id":"KSRX", "lat":35.2904423, "lon":-94.3619075, "country":"USA", "state":"AR", "place":"Fort Smith" }, + { "type":"wsr88d", "id":"KLZK", "lat":34.8365261, "lon":-92.2621697, "country":"USA", "state":"AR", "place":"Little Rock" }, + { "type":"wsr88d", "id":"KFSX", "lat":34.574449, "lon":-111.198367, "country":"USA", "state":"AZ", "place":"Flagstaff" }, + { "type":"wsr88d", "id":"KIWA", "lat":33.289111, "lon":-111.6700092, "country":"USA", "state":"AZ", "place":"Phoenix" }, + { "type":"wsr88d", "id":"KEMX", "lat":31.8937186, "lon":-110.6304306, "country":"USA", "state":"AZ", "place":"Tucson" }, + { "type":"wsr88d", "id":"KYUX", "lat":32.4953477, "lon":-114.6567214, "country":"USA", "state":"AZ", "place":"Yuma" }, + { "type":"wsr88d", "id":"KBBX", "lat":39.4956958, "lon":-121.6316557, "country":"USA", "state":"CA", "place":"Beale AFB" }, + { "type":"wsr88d", "id":"KEYX", "lat":35.0979358, "lon":-117.5608832, "country":"USA", "state":"CA", "place":"Edwards AFB" }, + { "type":"wsr88d", "id":"KBHX", "lat":40.4986955, "lon":-124.2918867, "country":"USA", "state":"CA", "place":"Eureka" }, + { "type":"wsr88d", "id":"KVTX", "lat":34.4116386, "lon":-119.1795641, "country":"USA", "state":"CA", "place":"Los Angeles" }, + { "type":"wsr88d", "id":"KDAX", "lat":38.5011529, "lon":-121.6778487, "country":"USA", "state":"CA", "place":"Sacramento" }, + { "type":"wsr88d", "id":"KNKX", "lat":32.9189891, "lon":-117.041814, "country":"USA", "state":"CA", "place":"San Diego" }, + { "type":"wsr88d", "id":"KMUX", "lat":37.155152, "lon":-121.8984577, "country":"USA", "state":"CA", "place":"San Francisco" }, + { "type":"wsr88d", "id":"KHNX", "lat":36.3142088, "lon":-119.6320903, "country":"USA", "state":"CA", "place":"San Joaquin Valley" }, + { "type":"wsr88d", "id":"KSOX", "lat":33.8176452, "lon":-117.6359743, "country":"USA", "state":"CA", "place":"Santa Ana Mountains" }, + { "type":"wsr88d", "id":"KVBG", "lat":34.8383137, "lon":-120.3977805, "country":"USA", "state":"CA", "place":"Vandenberg AFB" }, + { "type":"wsr88d", "id":"KFTG", "lat":39.7866156, "lon":-104.5458126, "country":"USA", "state":"CO", "place":"Denver" }, + { "type":"wsr88d", "id":"KGJX", "lat":39.0619824, "lon":-108.2137012, "country":"USA", "state":"CO", "place":"Grand Junction" }, + { "type":"wsr88d", "id":"KPUX", "lat":38.4595034, "lon":-104.1816223, "country":"USA", "state":"CO", "place":"Pueblo" }, + { "type":"wsr88d", "id":"KDOX", "lat":38.8257651, "lon":-75.4400763, "country":"USA", "state":"DE", "place":"Dover AFB" }, + { "type":"wsr88d", "id":"KEVX", "lat":30.5649908, "lon":-85.921559, "country":"USA", "state":"FL", "place":"Eglin AFB" }, + { "type":"wsr88d", "id":"KJAX", "lat":30.4846878, "lon":-81.7018917, "country":"USA", "state":"FL", "place":"Jacksonville" }, + { "type":"wsr88d", "id":"KBYX", "lat":24.5974996, "lon":-81.7032355, "country":"USA", "state":"FL", "place":"Key West" }, + { "type":"wsr88d", "id":"KMLB", "lat":28.1131808, "lon":-80.6540988, "country":"USA", "state":"FL", "place":"Melbourne" }, + { "type":"wsr88d", "id":"KAMX", "lat":25.6111275, "lon":-80.412747, "country":"USA", "state":"FL", "place":"Miami" }, + { "type":"wsr88d", "id":"KTLH", "lat":30.397568, "lon":-84.3289116, "country":"USA", "state":"FL", "place":"Tallahassee" }, + { "type":"wsr88d", "id":"KTBW", "lat":27.7054701, "lon":-82.40179, "country":"USA", "state":"FL", "place":"Tampa" }, + { "type":"wsr88d", "id":"KFFC", "lat":33.3635771, "lon":-84.565866, "country":"USA", "state":"GA", "place":"Atlanta" }, + { "type":"wsr88d", "id":"KVAX", "lat":30.8903853, "lon":-83.0019021, "country":"USA", "state":"GA", "place":"Moody AFB" }, + { "type":"wsr88d", "id":"KJGX", "lat":32.6755239, "lon":-83.3508575, "country":"USA", "state":"GA", "place":"Robins AFB" }, + { "type":"wsr88d", "id":"PGUA", "lat":13.455965, "lon":144.8111022, "country":"USA", "state":"GU", "place":"Andersen AFB" }, + { "type":"wsr88d", "id":"PHKI", "lat":21.8938762, "lon":-159.5524585, "country":"USA", "state":"HI", "place":"Kauai" }, + { "type":"wsr88d", "id":"PHKM", "lat":20.1254606, "lon":-155.778054, "country":"USA", "state":"HI", "place":"Kohala" }, + { "type":"wsr88d", "id":"PHMO", "lat":21.1327531, "lon":-157.1802807, "country":"USA", "state":"HI", "place":"Molokai" }, + { "type":"wsr88d", "id":"PHWA", "lat":19.0950155, "lon":-155.5688846, "country":"USA", "state":"HI", "place":"South Shore" }, + { "type":"wsr88d", "id":"KDVN", "lat":41.611556, "lon":-90.5809987, "country":"USA", "state":"IA", "place":"Davenport" }, + { "type":"wsr88d", "id":"KDMX", "lat":41.7311788, "lon":-93.7229235, "country":"USA", "state":"IA", "place":"Des Moines" }, + { "type":"wsr88d", "id":"KCBX", "lat":43.4902104, "lon":-116.2360436, "country":"USA", "state":"ID", "place":"Boise" }, + { "type":"wsr88d", "id":"KSFX", "lat":43.1055967, "lon":-112.6860487, "country":"USA", "state":"ID", "place":"Pocatello/Idaho Falls" }, + { "type":"wsr88d", "id":"KLOT", "lat":41.6044264, "lon":-88.084361, "country":"USA", "state":"IL", "place":"Chicago" }, + { "type":"wsr88d", "id":"KILX", "lat":40.150544, "lon":-89.336842, "country":"USA", "state":"IL", "place":"Lincoln" }, + { "type":"wsr88d", "id":"KIND", "lat":39.7074962, "lon":-86.2803675, "country":"USA", "state":"IN", "place":"Indianapolis" }, + { "type":"wsr88d", "id":"KIWX", "lat":41.3586356, "lon":-85.7000488, "country":"USA", "state":"IN", "place":"North Webster" }, + { "type":"wsr88d", "id":"KVWX", "lat":38.2603901, "lon":-87.7246553, "country":"USA", "state":"IN", "place":"Owensville (Evansville)" }, + { "type":"wsr88d", "id":"KDDC", "lat":37.7608043, "lon":-99.9688053, "country":"USA", "state":"KS", "place":"Dodge City" }, + { "type":"wsr88d", "id":"KGLD", "lat":39.3667737, "lon":-101.7004341, "country":"USA", "state":"KS", "place":"Goodland" }, + { "type":"wsr88d", "id":"KTWX", "lat":38.996998, "lon":-96.232618, "country":"USA", "state":"KS", "place":"Topeka" }, + { "type":"wsr88d", "id":"KICT", "lat":37.6545724, "lon":-97.4431461, "country":"USA", "state":"KS", "place":"Wichita" }, + { "type":"wsr88d", "id":"KHPX", "lat":36.7368894, "lon":-87.2854328, "country":"USA", "state":"KY", "place":"Fort Campbell" }, + { "type":"wsr88d", "id":"KJKL", "lat":37.590762, "lon":-83.313039, "country":"USA", "state":"KY", "place":"Jackson" }, + { "type":"wsr88d", "id":"KLVX", "lat":37.9753058, "lon":-85.9438455, "country":"USA", "state":"KY", "place":"Louisville" }, + { "type":"wsr88d", "id":"KPAH", "lat":37.0683618, "lon":-88.7720257, "country":"USA", "state":"KY", "place":"Paducah" }, + { "type":"wsr88d", "id":"KPOE", "lat":31.1556923, "lon":-92.9762596, "country":"USA", "state":"LA", "place":"Fort Polk" }, + { "type":"wsr88d", "id":"KLCH", "lat":30.125382, "lon":-93.2161188, "country":"USA", "state":"LA", "place":"Lake Charles" }, + { "type":"wsr88d", "id":"KLIX", "lat":30.3367133, "lon":-89.8256618, "country":"USA", "state":"LA", "place":"New Orleans" }, + { "type":"wsr88d", "id":"KSHV", "lat":32.450813, "lon":-93.8412774, "country":"USA", "state":"LA", "place":"Shreveport" }, + { "type":"wsr88d", "id":"KBOX", "lat":41.9558919, "lon":-71.1369681, "country":"USA", "state":"MA", "place":"Boston" }, + { "type":"wsr88d", "id":"KGYX", "lat":43.8913555, "lon":-70.2565545, "country":"USA", "state":"ME", "place":"Gray/Portland" }, + { "type":"wsr88d", "id":"KCBW", "lat":46.0391944, "lon":-67.8066033, "country":"USA", "state":"ME", "place":"Houlton" }, + { "type":"wsr88d", "id":"KDTX", "lat":42.6999677, "lon":-83.471809, "country":"USA", "state":"MI", "place":"Detroit/Pontiac" }, + { "type":"wsr88d", "id":"KAPX", "lat":44.907106, "lon":-84.719817, "country":"USA", "state":"MI", "place":"Gaylord" }, + { "type":"wsr88d", "id":"KGRR", "lat":42.893872, "lon":-85.5449206, "country":"USA", "state":"MI", "place":"Grand Rapids" }, + { "type":"wsr88d", "id":"KMQT", "lat":46.5311443, "lon":-87.5487131, "country":"USA", "state":"MI", "place":"Marquette" }, + { "type":"wsr88d", "id":"KDLH", "lat":46.8368569, "lon":-92.2097433, "country":"USA", "state":"MN", "place":"Duluth" }, + { "type":"wsr88d", "id":"KMPX", "lat":44.8488029, "lon":-93.5654873, "country":"USA", "state":"MN", "place":"Minneapolis/St. Paul" }, + { "type":"wsr88d", "id":"KEAX", "lat":38.8102231, "lon":-94.2644924, "country":"USA", "state":"MO", "place":"Kansas City" }, + { "type":"wsr88d", "id":"KSGF", "lat":37.235223, "lon":-93.4006011, "country":"USA", "state":"MO", "place":"Springfield" }, + { "type":"wsr88d", "id":"KLSX", "lat":38.6986863, "lon":-90.682877, "country":"USA", "state":"MO", "place":"St. Louis" }, + { "type":"wsr88d", "id":"KDGX", "lat":32.2797358, "lon":-89.9846309, "country":"USA", "state":"MS", "place":"Brandon/Jackson" }, + { "type":"wsr88d", "id":"KGWX", "lat":33.8967796, "lon":-88.3293915, "country":"USA", "state":"MS", "place":"Columbus AFB" }, + { "type":"wsr88d", "id":"KBLX", "lat":45.8537632, "lon":-108.6068165, "country":"USA", "state":"MT", "place":"Billings" }, + { "type":"wsr88d", "id":"KGGW", "lat":48.2064536, "lon":-106.6252971, "country":"USA", "state":"MT", "place":"Glasgow" }, + { "type":"wsr88d", "id":"KTFX", "lat":47.4595023, "lon":-111.3855368, "country":"USA", "state":"MT", "place":"Great Falls" }, + { "type":"wsr88d", "id":"KMSX", "lat":47.0412971, "lon":-113.9864373, "country":"USA", "state":"MT", "place":"Missoula" }, + { "type":"wsr88d", "id":"KMHX", "lat":34.7759313, "lon":-76.8762571, "country":"USA", "state":"NC", "place":"Morehead City" }, + { "type":"wsr88d", "id":"KRAX", "lat":35.6654967, "lon":-78.4897855, "country":"USA", "state":"NC", "place":"Raleigh/Durham" }, + { "type":"wsr88d", "id":"KLTX", "lat":33.9891631, "lon":-78.4291059, "country":"USA", "state":"NC", "place":"Wilmington" }, + { "type":"wsr88d", "id":"KBIS", "lat":46.7709329, "lon":-100.7605532, "country":"USA", "state":"ND", "place":"Bismarck" }, + { "type":"wsr88d", "id":"KMVX", "lat":47.5279417, "lon":-97.3256654, "country":"USA", "state":"ND", "place":"Grand Forks (Mayville)" }, + { "type":"wsr88d", "id":"KMBX", "lat":48.39303, "lon":-100.8644378, "country":"USA", "state":"ND", "place":"Minot AFB" }, + { "type":"wsr88d", "id":"KUEX", "lat":40.320966, "lon":-98.4418559, "country":"USA", "state":"NE", "place":"Grand Island/Hastings" }, + { "type":"wsr88d", "id":"KLNX", "lat":41.9579623, "lon":-100.5759609, "country":"USA", "state":"NE", "place":"North Platte" }, + { "type":"wsr88d", "id":"KOAX", "lat":41.3202803, "lon":-96.3667971, "country":"USA", "state":"NE", "place":"Omaha" }, + { "type":"wsr88d", "id":"KABX", "lat":35.1497579, "lon":-106.8239576, "country":"USA", "state":"NM", "place":"Albuquerque" }, + { "type":"wsr88d", "id":"KFDX", "lat":34.6341569, "lon":-103.6186427, "country":"USA", "state":"NM", "place":"Cannon AFB" }, + { "type":"wsr88d", "id":"KHDX", "lat":33.0768844, "lon":-106.1200923, "country":"USA", "state":"NM", "place":"Holloman AFB" }, + { "type":"wsr88d", "id":"KLRX", "lat":40.7396933, "lon":-116.8025529, "country":"USA", "state":"NV", "place":"Elko" }, + { "type":"wsr88d", "id":"KESX", "lat":35.7012894, "lon":-114.8918277, "country":"USA", "state":"NV", "place":"Las Vegas" }, + { "type":"wsr88d", "id":"KRGX", "lat":39.7541931, "lon":-119.4620597, "country":"USA", "state":"NV", "place":"Reno" }, + { "type":"wsr88d", "id":"KENX", "lat":42.5865699, "lon":-74.0639877, "country":"USA", "state":"NY", "place":"Albany" }, + { "type":"wsr88d", "id":"KBGM", "lat":42.1997045, "lon":-75.9847015, "country":"USA", "state":"NY", "place":"Binghamton" }, + { "type":"wsr88d", "id":"KBUF", "lat":42.9488055, "lon":-78.7369108, "country":"USA", "state":"NY", "place":"Buffalo" }, + { "type":"wsr88d", "id":"KTYX", "lat":43.7556319, "lon":-75.6799918, "country":"USA", "state":"NY", "place":"Montague" }, + { "type":"wsr88d", "id":"KOKX", "lat":40.8655093, "lon":-72.8638548, "country":"USA", "state":"NY", "place":"New York City" }, + { "type":"wsr88d", "id":"KCLE", "lat":41.4131875, "lon":-81.8597451, "country":"USA", "state":"OH", "place":"Cleveland" }, + { "type":"wsr88d", "id":"KILN", "lat":39.42028, "lon":-83.82167, "country":"USA", "state":"OH", "place":"Wilmington" }, + { "type":"wsr88d", "id":"KFDR", "lat":34.3620014, "lon":-98.9766884, "country":"USA", "state":"OK", "place":"Frederick" }, + { "type":"wsr88d", "id":"KTLX", "lat":35.3333873, "lon":-97.2778255, "country":"USA", "state":"OK", "place":"Oklahoma City" }, + { "type":"wsr88d", "id":"KINX", "lat":36.1750977, "lon":-95.5642802, "country":"USA", "state":"OK", "place":"Tulsa" }, + { "type":"wsr88d", "id":"KVNX", "lat":36.7406166, "lon":-98.1279409, "country":"USA", "state":"OK", "place":"Vance AFB" }, + { "type":"wsr88d", "id":"KMAX", "lat":42.0810766, "lon":-122.7173334, "country":"USA", "state":"OR", "place":"Medford" }, + { "type":"wsr88d", "id":"KPDT", "lat":45.6906118, "lon":-118.8529301, "country":"USA", "state":"OR", "place":"Pendleton" }, + { "type":"wsr88d", "id":"KRTX", "lat":45.7150308, "lon":-122.9650542, "country":"USA", "state":"OR", "place":"Portland" }, + { "type":"wsr88d", "id":"KDIX", "lat":39.9470885, "lon":-74.4108027, "country":"USA", "state":"PA", "place":"Philadelphia" }, + { "type":"wsr88d", "id":"KPBZ", "lat":40.5316842, "lon":-80.2179515, "country":"USA", "state":"PA", "place":"Pittsburgh" }, + { "type":"wsr88d", "id":"KCCX", "lat":40.9228521, "lon":-78.0038738, "country":"USA", "state":"PA", "place":"State College" }, + { "type":"wsr88d", "id":"TJUA", "lat":18.1155998, "lon":-66.0780644, "country":"USA", "state":"PR", "place":"San Juan" }, + { "type":"wsr88d", "id":"KCLX", "lat":32.6554866, "lon":-81.0423124, "country":"USA", "state":"SC", "place":"Charleston" }, + { "type":"wsr88d", "id":"KCAE", "lat":33.9487579, "lon":-81.1184281, "country":"USA", "state":"SC", "place":"Columbia" }, + { "type":"wsr88d", "id":"KGSP", "lat":34.8833435, "lon":-82.2200757, "country":"USA", "state":"SC", "place":"Greer" }, + { "type":"wsr88d", "id":"KABR", "lat":45.4558185, "lon":-98.4132046, "country":"USA", "state":"SD", "place":"Aberdeen" }, + { "type":"wsr88d", "id":"KUDX", "lat":44.1248485, "lon":-102.8298157, "country":"USA", "state":"SD", "place":"Rapid City" }, + { "type":"wsr88d", "id":"KFSD", "lat":43.5877467, "lon":-96.7293674, "country":"USA", "state":"SD", "place":"Sioux Falls" }, + { "type":"wsr88d", "id":"KMRX", "lat":36.168538, "lon":-83.401779, "country":"USA", "state":"TN", "place":"Knoxville/Tri Cities" }, + { "type":"wsr88d", "id":"KNQA", "lat":35.3447802, "lon":-89.8734534, "country":"USA", "state":"TN", "place":"Memphis" }, + { "type":"wsr88d", "id":"KOHX", "lat":36.2472389, "lon":-86.5625185, "country":"USA", "state":"TN", "place":"Nashville" }, + { "type":"wsr88d", "id":"KAMA", "lat":35.2334827, "lon":-101.7092478, "country":"USA", "state":"TX", "place":"Amarillo" }, + { "type":"wsr88d", "id":"KEWX", "lat":29.7039802, "lon":-98.028506, "country":"USA", "state":"TX", "place":"Austin/San Antonio" }, + { "type":"wsr88d", "id":"KBRO", "lat":25.9159979, "lon":-97.4189526, "country":"USA", "state":"TX", "place":"Brownsville" }, + { "type":"wsr88d", "id":"KCRP", "lat":27.7840203, "lon":-97.511234, "country":"USA", "state":"TX", "place":"Corpus Christi" }, + { "type":"wsr88d", "id":"KFWS", "lat":32.5730186, "lon":-97.3031911, "country":"USA", "state":"TX", "place":"Dallas/Ft. Worth" }, + { "type":"wsr88d", "id":"KDYX", "lat":32.5386009, "lon":-99.2542863, "country":"USA", "state":"TX", "place":"Dyess AFB" }, + { "type":"wsr88d", "id":"KEPZ", "lat":31.8731115, "lon":-106.697942, "country":"USA", "state":"TX", "place":"El Paso" }, + { "type":"wsr88d", "id":"KGRK", "lat":30.7217637, "lon":-97.3829627, "country":"USA", "state":"TX", "place":"Fort Hood" }, + { "type":"wsr88d", "id":"KHGX", "lat":29.4718835, "lon":-95.0788593, "country":"USA", "state":"TX", "place":"Houston/Galveston" }, + { "type":"wsr88d", "id":"KDFX", "lat":29.2730823, "lon":-100.2802312, "country":"USA", "state":"TX", "place":"Laughlin AFB" }, + { "type":"wsr88d", "id":"KLBB", "lat":33.6541242, "lon":-101.814149, "country":"USA", "state":"TX", "place":"Lubbock" }, + { "type":"wsr88d", "id":"KMAF", "lat":31.9433953, "lon":-102.1894383, "country":"USA", "state":"TX", "place":"Midland/Odessa" }, + { "type":"wsr88d", "id":"KSJT", "lat":31.3712815, "lon":-100.4925227, "country":"USA", "state":"TX", "place":"San Angelo" }, + { "type":"wsr88d", "id":"KICX", "lat":37.59083, "lon":-112.86222, "country":"USA", "state":"UT", "place":"Cedar City" }, + { "type":"wsr88d", "id":"KMTX", "lat":41.2627795, "lon":-112.4480081, "country":"USA", "state":"UT", "place":"Salt Lake City" }, + { "type":"wsr88d", "id":"KAKQ", "lat":36.9840475, "lon":-77.007342, "country":"USA", "state":"VA", "place":"Norfolk/Richmond" }, + { "type":"wsr88d", "id":"KFCX", "lat":37.0242098, "lon":-80.2736664, "country":"USA", "state":"VA", "place":"Roanoke" }, + { "type":"wsr88d", "id":"KLWX", "lat":38.9753957, "lon":-77.4778444, "country":"USA", "state":"VA", "place":"Sterling" }, + { "type":"wsr88d", "id":"KCXX", "lat":44.5109941, "lon":-73.166424, "country":"USA", "state":"VT", "place":"Burlington" }, + { "type":"wsr88d", "id":"KLGX", "lat":47.116806, "lon":-124.10625, "country":"USA", "state":"WA", "place":"Langley Hill" }, + { "type":"wsr88d", "id":"KATX", "lat":48.1945614, "lon":-122.4957508, "country":"USA", "state":"WA", "place":"Seattle/Tacoma" }, + { "type":"wsr88d", "id":"KOTX", "lat":47.6803744, "lon":-117.6267797, "country":"USA", "state":"WA", "place":"Spokane" }, + { "type":"wsr88d", "id":"KGRB", "lat":44.4984644, "lon":-88.111124, "country":"USA", "state":"WI", "place":"Green Bay" }, + { "type":"wsr88d", "id":"KARX", "lat":43.822766, "lon":-91.1915767, "country":"USA", "state":"WI", "place":"La Crosse" }, + { "type":"wsr88d", "id":"KMKX", "lat":42.9678286, "lon":-88.5506335, "country":"USA", "state":"WI", "place":"Milwaukee" }, + { "type":"wsr88d", "id":"KRLX", "lat":38.3110763, "lon":-81.7229015, "country":"USA", "state":"WV", "place":"Charleston" }, + { "type":"wsr88d", "id":"KCYS", "lat":41.1519308, "lon":-104.8060325, "country":"USA", "state":"WY", "place":"Cheyenne" }, + { "type":"wsr88d", "id":"KRIW", "lat":43.0660779, "lon":-108.4773731, "country":"USA", "state":"WY", "place":"Riverton" }, + + { "type":"tdwr", "id":"TADW", "lat":38.695, "lon":-76.845, "country":"USA", "state":"MD", "place":"Andrews Air Force Base" }, + { "type":"tdwr", "id":"TATL", "lat":33.647, "lon":-84.262, "country":"USA", "state":"GA", "place":"Atlanta" }, + { "type":"tdwr", "id":"TBNA", "lat":35.98, "lon":-86.662, "country":"USA", "state":"TN", "place":"Nashville" }, + { "type":"tdwr", "id":"TBOS", "lat":42.158, "lon":-70.933, "country":"USA", "state":"MA", "place":"Boston" }, + { "type":"tdwr", "id":"TBWI", "lat":39.09, "lon":-76.63, "country":"USA", "state":"MD", "place":"Baltimore/Wash" }, + { "type":"tdwr", "id":"TCLT", "lat":35.337, "lon":-80.885, "country":"USA", "state":"NC", "place":"Charlotte" }, + { "type":"tdwr", "id":"TCMH", "lat":40.006, "lon":-82.715, "country":"USA", "state":"OH", "place":"Columbus" }, + { "type":"tdwr", "id":"TCVG", "lat":38.898, "lon":-84.58, "country":"USA", "state":"OH", "place":"Cincinnati" }, + { "type":"tdwr", "id":"TDAL", "lat":32.926, "lon":-96.968, "country":"USA", "state":"TX", "place":"Dallas Love Field" }, + { "type":"tdwr", "id":"TDAY", "lat":40.022, "lon":-84.123, "country":"USA", "state":"OH", "place":"Dayton" }, + { "type":"tdwr", "id":"TDCA", "lat":38.759, "lon":-76.962, "country":"USA", "state":"MD", "place":"Washington National" }, + { "type":"tdwr", "id":"TDEN", "lat":39.728, "lon":-104.526, "country":"USA", "state":"CO", "place":"Denver" }, + { "type":"tdwr", "id":"TDFW", "lat":33.065, "lon":-96.918, "country":"USA", "state":"TX", "place":"Dallas/Ft Worth" }, + { "type":"tdwr", "id":"TDTW", "lat":42.111, "lon":-83.515, "country":"USA", "state":"MI", "place":"Detroit" }, + { "type":"tdwr", "id":"TEWR", "lat":40.593, "lon":-74.27, "country":"USA", "state":"NJ", "place":"Newark" }, + { "type":"tdwr", "id":"TFLL", "lat":26.143, "lon":-80.344, "country":"USA", "state":"FL", "place":"Fort Lauderdale" }, + { "type":"tdwr", "id":"THOU", "lat":29.516, "lon":-95.242, "country":"USA", "state":"TX", "place":"Houston Hobby" }, + { "type":"tdwr", "id":"TIAD", "lat":39.084, "lon":-77.529, "country":"USA", "state":"VA", "place":"Dulles" }, + { "type":"tdwr", "id":"TIAH", "lat":30.065, "lon":-95.567, "country":"USA", "state":"TX", "place":"Houston International" }, + { "type":"tdwr", "id":"TICH", "lat":37.507, "lon":-97.437, "country":"USA", "state":"KS", "place":"Wichita" }, + { "type":"tdwr", "id":"TIDS", "lat":39.637, "lon":-86.436, "country":"USA", "state":"IN", "place":"Indianapolis" }, + { "type":"tdwr", "id":"TJFK", "lat":40.589, "lon":-73.881, "country":"USA", "state":"NY", "place":"New York City" }, + { "type":"tdwr", "id":"TLAS", "lat":36.144, "lon":-115.007, "country":"USA", "state":"NV", "place":"Las Vegas" }, + { "type":"tdwr", "id":"TLVE", "lat":41.29, "lon":-82.008, "country":"USA", "state":"OH", "place":"Cleveland" }, + { "type":"tdwr", "id":"TMCI", "lat":39.498, "lon":-94.742, "country":"USA", "state":"MO", "place":"Kansas City" }, + { "type":"tdwr", "id":"TMCO", "lat":28.344, "lon":-81.326, "country":"USA", "state":"FL", "place":"Orlando International" }, + { "type":"tdwr", "id":"TMDW", "lat":41.651, "lon":-87.73, "country":"USA", "state":"IL", "place":"Chicago Midway" }, + { "type":"tdwr", "id":"TMEM", "lat":34.896, "lon":-89.993, "country":"USA", "state":"TN", "place":"Memphis" }, + { "type":"tdwr", "id":"TMIA", "lat":25.758, "lon":-80.491, "country":"USA", "state":"FL", "place":"Miami" }, + { "type":"tdwr", "id":"TMKE", "lat":42.819, "lon":-88.046, "country":"USA", "state":"WI", "place":"Milwaukee" }, + { "type":"tdwr", "id":"TMSP", "lat":44.871, "lon":-92.933, "country":"USA", "state":"MN", "place":"Minneapolis" }, + { "type":"tdwr", "id":"TMSY", "lat":30.022, "lon":-90.403, "country":"USA", "state":"LA", "place":"New Orleans" }, + { "type":"tdwr", "id":"TOKC", "lat":35.276, "lon":-97.51, "country":"USA", "state":"OK", "place":"Oklahoma City" }, + { "type":"tdwr", "id":"TORD", "lat":41.797, "lon":-87.858, "country":"USA", "state":"IL", "place":"Chicago O'Hare" }, + { "type":"tdwr", "id":"TPBI", "lat":26.688, "lon":-80.273, "country":"USA", "state":"FL", "place":"West Palm Beach" }, + { "type":"tdwr", "id":"TPHL", "lat":39.949, "lon":-75.069, "country":"USA", "state":"PA", "place":"Philadelphia" }, + { "type":"tdwr", "id":"TPHX", "lat":33.421, "lon":-112.163, "country":"USA", "state":"AZ", "place":"Phoenix" }, + { "type":"tdwr", "id":"TPIT", "lat":40.501, "lon":-80.486, "country":"USA", "state":"PA", "place":"Pittsburgh" }, + { "type":"tdwr", "id":"TRDU", "lat":36.002, "lon":-78.697, "country":"USA", "state":"NC", "place":"Raleigh Durham" }, + { "type":"tdwr", "id":"TSDF", "lat":38.046, "lon":-85.61, "country":"USA", "state":"KY", "place":"Louisville" }, + { "type":"tdwr", "id":"TSJU", "lat":18.474, "lon":-66.179, "country":"USA", "state":"PR", "place":"San Juan" }, + { "type":"tdwr", "id":"TSLC", "lat":40.967, "lon":-111.93, "country":"USA", "state":"UT", "place":"Salt Lake City" }, + { "type":"tdwr", "id":"TSTL", "lat":38.805, "lon":-90.489, "country":"USA", "state":"MO", "place":"St Louis" }, + { "type":"tdwr", "id":"TTPA", "lat":27.86, "lon":-82.518, "country":"USA", "state":"FL", "place":"Tampa Bay" }, + { "type":"tdwr", "id":"TTUL", "lat":36.071, "lon":-95.827, "country":"USA", "state":"OK", "place":"Tulsa" } +] \ No newline at end of file diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index ca4cd6ed..8e513ee6 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -53,6 +53,8 @@ set(SRC_EXE_MAIN source/scwx/qt/main/main.cpp) set(HDR_MAIN source/scwx/qt/main/main_window.hpp) set(SRC_MAIN source/scwx/qt/main/main_window.cpp) set(UI_MAIN source/scwx/qt/main/main_window.ui) +set(HDR_CONFIG source/scwx/qt/config/radar_site.hpp) +set(SRC_CONFIG source/scwx/qt/config/radar_site.cpp) set(HDR_GL source/scwx/qt/gl/gl.hpp source/scwx/qt/gl/shader_program.hpp source/scwx/qt/gl/text_shader.hpp) @@ -116,10 +118,14 @@ set(SHADER_FILES gl/color.frag gl/texture1d.frag gl/texture1d.vert) +set (JSON_FILES res/config/radar_sites.json) + set(TS_FILES ts/scwx_en_US.ts) set(PROJECT_SOURCES ${HDR_MAIN} ${SRC_MAIN} + ${HDR_CONFIG} + ${SRC_CONFIG} ${HDR_GL} ${SRC_GL} ${HDR_GL_DRAW} @@ -138,12 +144,15 @@ set(PROJECT_SOURCES ${HDR_MAIN} ${HDR_VIEW} ${SRC_VIEW} ${SHADER_FILES} + ${JSON_FILES} ${RESOURCE_FILES} ${TS_FILES}) set(EXECUTABLE_SOURCES ${SRC_EXE_MAIN}) source_group("Header Files\\main" FILES ${HDR_MAIN}) source_group("Source Files\\main" FILES ${SRC_MAIN}) +source_group("Header Files\\config" FILES ${HDR_CONFIG}) +source_group("Source Files\\config" FILES ${SRC_CONFIG}) source_group("Header Files\\gl" FILES ${HDR_GL}) source_group("Source Files\\gl" FILES ${SRC_GL}) source_group("Header Files\\gl\\draw" FILES ${HDR_GL_DRAW}) @@ -163,6 +172,7 @@ source_group("Header Files\\view" FILES ${HDR_VIEW}) source_group("Source Files\\view" FILES ${SRC_VIEW}) source_group("OpenGL Shaders" FILES ${SHADER_FILES}) source_group("Resources" FILES ${RESOURCE_FILES}) +source_group("Resources\\json" FILES ${JSON_FILES}) source_group("I18N Files" FILES ${TS_FILES}) add_library(scwx-qt OBJECT ${PROJECT_SOURCES}) diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc index 614e8554..6c53610b 100644 --- a/scwx-qt/scwx-qt.qrc +++ b/scwx-qt/scwx-qt.qrc @@ -8,6 +8,7 @@ gl/text.vert gl/texture1d.frag gl/texture1d.vert + res/config/radar_sites.json res/fonts/din1451alt.ttf res/fonts/din1451alt_g.ttf diff --git a/scwx-qt/source/scwx/qt/config/radar_site.cpp b/scwx-qt/source/scwx/qt/config/radar_site.cpp new file mode 100644 index 00000000..14e50530 --- /dev/null +++ b/scwx-qt/source/scwx/qt/config/radar_site.cpp @@ -0,0 +1,157 @@ +#include +#include + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace config +{ + +static const std::string logPrefix_ = "[scwx::qt::settings::radar_site] "; + +static std::unordered_map> + radarSiteMap_; + +static bool ValidateJsonEntry(const boost::json::object& o); + +class RadarSiteImpl +{ +public: + explicit RadarSiteImpl() : + type_ {}, + id_ {}, + latitude_ {0.0}, + longitude_ {0.0}, + country_ {}, + state_ {}, + place_ {} + { + } + + ~RadarSiteImpl() {} + + std::string type_; + std::string id_; + double latitude_; + double longitude_; + std::string country_; + std::string state_; + std::string place_; +}; + +RadarSite::RadarSite() : p(std::make_unique()) {} +RadarSite::~RadarSite() = default; + +RadarSite::RadarSite(RadarSite&&) noexcept = default; +RadarSite& RadarSite::operator=(RadarSite&&) noexcept = default; + +std::string RadarSite::type() const +{ + return p->type_; +} + +std::string RadarSite::id() const +{ + return p->id_; +} + +double RadarSite::latitude() const +{ + return p->latitude_; +} + +double RadarSite::longitude() const +{ + return p->longitude_; +} + +std::string RadarSite::country() const +{ + return p->country_; +} + +std::string RadarSite::state() const +{ + return p->state_; +} + +std::string RadarSite::place() const +{ + return p->place_; +} + +std::shared_ptr RadarSite::Get(const std::string& id) +{ + std::shared_ptr radarSite = nullptr; + + if (radarSiteMap_.contains(id)) + { + radarSite = radarSiteMap_.at(id); + } + + return radarSite; +} + +size_t RadarSite::ReadConfig(const std::string& path) +{ + bool dataValid = true; + size_t sitesAdded = 0; + + boost::json::value j = util::json::ReadJsonFile(path); + + dataValid = j.is_array(); + + if (dataValid) + { + for (auto& v : j.as_array()) + { + auto& o = v.as_object(); + + if (!ValidateJsonEntry(o)) + { + BOOST_LOG_TRIVIAL(info) << logPrefix_ << "Incorrect format: " << v; + } + else + { + std::shared_ptr site = std::make_shared(); + + site->p->type_ = boost::json::value_to(o.at("type")); + site->p->id_ = boost::json::value_to(o.at("id")); + site->p->latitude_ = boost::json::value_to(o.at("lat")); + site->p->longitude_ = boost::json::value_to(o.at("lon")); + site->p->country_ = + boost::json::value_to(o.at("country")); + site->p->state_ = boost::json::value_to(o.at("state")); + site->p->place_ = boost::json::value_to(o.at("place")); + + if (!radarSiteMap_.contains(site->p->id_)) + { + radarSiteMap_[site->p->id_] = site; + ++sitesAdded; + } + } + } + } + + return sitesAdded; +} + +static bool ValidateJsonEntry(const boost::json::object& o) +{ + return (o.contains("type") && o.at("type").is_string() && // + o.contains("id") && o.at("id").is_string() && // + o.contains("lat") && o.at("lat").is_double() && // + o.contains("lon") && o.at("lon").is_double() && // + o.contains("country") && o.at("country").is_string() && // + o.contains("state") && o.at("state").is_string() && // + o.contains("place") && o.at("place").is_string()); +} + +} // namespace config +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/config/radar_site.hpp b/scwx-qt/source/scwx/qt/config/radar_site.hpp new file mode 100644 index 00000000..91d7fdf4 --- /dev/null +++ b/scwx-qt/source/scwx/qt/config/radar_site.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace config +{ + +class RadarSiteImpl; + +class RadarSite +{ +public: + explicit RadarSite(); + ~RadarSite(); + + RadarSite(const RadarSite&) = delete; + RadarSite& operator=(const RadarSite&) = delete; + + RadarSite(RadarSite&&) noexcept; + RadarSite& operator=(RadarSite&&) noexcept; + + std::string type() const; + std::string id() const; + double latitude() const; + double longitude() const; + std::string country() const; + std::string state() const; + std::string place() const; + + static std::shared_ptr Get(const std::string& id); + + static size_t ReadConfig(const std::string& path); + +private: + std::unique_ptr p; +}; + +} // namespace config +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/json.cpp b/scwx-qt/source/scwx/qt/util/json.cpp index 97c5ebb6..538a80ff 100644 --- a/scwx-qt/source/scwx/qt/util/json.cpp +++ b/scwx-qt/source/scwx/qt/util/json.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include namespace scwx { @@ -27,6 +29,9 @@ static void PrettyPrintJson(std::ostream& os, boost::json::value const& jv, std::string* indent = nullptr); +static boost::json::value ReadJsonFile(QFile& file); +static boost::json::value ReadJsonStream(std::istream& is); + bool FromJsonInt64(const boost::json::object& json, const std::string& key, int64_t& value, @@ -117,13 +122,56 @@ bool FromJsonString(const boost::json::object& json, boost::json::value ReadJsonFile(const std::string& path) { - std::ifstream ifs {path}; - std::string line; + boost::json::value json; + + if (path.starts_with(":")) + { + QFile file(path.c_str()); + json = ReadJsonFile(file); + } + else + { + std::ifstream ifs {path}; + json = ReadJsonStream(ifs); + } + + return json; +} + +static boost::json::value ReadJsonFile(QFile& file) +{ + boost::json::value json; + + if (file.open(QIODevice::ReadOnly)) + { + QTextStream jsonStream(&file); + jsonStream.setEncoding(QStringConverter::Utf8); + + std::string jsonSource = jsonStream.readAll().toStdString(); + std::istringstream is {jsonSource}; + + json = ReadJsonStream(is); + + file.close(); + } + else + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Could not open file for reading: \"" + << file.fileName().toStdString() << "\""; + } + + return json; +} + +static boost::json::value ReadJsonStream(std::istream& is) +{ + std::string line; boost::json::stream_parser p; boost::json::error_code ec; - while (std::getline(ifs, line)) + while (std::getline(is, line)) { p.write(line, ec); if (ec) diff --git a/test/source/scwx/qt/config/radar_site.test.cpp b/test/source/scwx/qt/config/radar_site.test.cpp new file mode 100644 index 00000000..f69381d1 --- /dev/null +++ b/test/source/scwx/qt/config/radar_site.test.cpp @@ -0,0 +1,36 @@ +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace config +{ + +static const std::string DEFAULT_RADAR_SITE_FILE = + ":/res/config/radar_sites.json"; + +TEST(RadarSite, DefaultConfig) +{ + size_t numSites = RadarSite::ReadConfig(DEFAULT_RADAR_SITE_FILE); + + ASSERT_GT(numSites, 0); + EXPECT_EQ(numSites, 204); + + std::shared_ptr radarSite = RadarSite::Get("KLSX"); + + ASSERT_NE(radarSite, nullptr); + + EXPECT_EQ(radarSite->type(), "wsr88d"); + EXPECT_EQ(radarSite->country(), "USA"); + EXPECT_EQ(radarSite->state(), "MO"); + EXPECT_EQ(radarSite->place(), "St. Louis"); + EXPECT_DOUBLE_EQ(radarSite->latitude(), 38.6986863); + EXPECT_DOUBLE_EQ(radarSite->longitude(), -90.682877); +} + +} // namespace config +} // namespace qt +} // namespace scwx diff --git a/test/test.cmake b/test/test.cmake index 7f7e662f..ae1805ca 100644 --- a/test/test.cmake +++ b/test/test.cmake @@ -13,6 +13,7 @@ set(SRC_AWIPS_TESTS source/scwx/awips/coded_location.test.cpp source/scwx/awips/pvtec.test.cpp source/scwx/awips/text_product_file.test.cpp) set(SRC_COMMON_TESTS source/scwx/common/color_table.test.cpp) +set(SRC_QT_CONFIG_TESTS source/scwx/qt/config/radar_site.test.cpp) set(SRC_QT_MANAGER_TESTS source/scwx/qt/manager/settings_manager.test.cpp) set(SRC_UTIL_TESTS source/scwx/util/rangebuf.test.cpp source/scwx/util/streams.test.cpp @@ -23,6 +24,7 @@ set(SRC_WSR88D_TESTS source/scwx/wsr88d/ar2v_file.test.cpp add_executable(wxtest ${SRC_MAIN} ${SRC_AWIPS_TESTS} ${SRC_COMMON_TESTS} + ${SRC_QT_CONFIG_TESTS} ${SRC_QT_MANAGER_TESTS} ${SRC_UTIL_TESTS} ${SRC_WSR88D_TESTS}) @@ -30,6 +32,7 @@ add_executable(wxtest ${SRC_MAIN} source_group("Source Files\\main" FILES ${SRC_MAIN}) source_group("Source Files\\awips" FILES ${SRC_AWIPS_TESTS}) source_group("Source Files\\common" FILES ${SRC_COMMON_TESTS}) +source_group("Source Files\\qt\\config" FILES ${SRC_QT_CONFIG_TESTS}) source_group("Source Files\\qt\\manager" FILES ${SRC_QT_MANAGER_TESTS}) source_group("Source Files\\util" FILES ${SRC_UTIL_TESTS}) source_group("Source Files\\wsr88d" FILES ${SRC_WSR88D_TESTS})