From 301e2c116963b4d7736d82adb8761862c4f95ace Mon Sep 17 00:00:00 2001 From: ELY M <> Date: Sat, 2 Nov 2024 19:59:53 -0500 Subject: [PATCH] 55919-elys --- DOC/Todo.md | 2 + app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 4 +- .../java/joshuatee/wx/common/GlobalArrays.kt | 1004 ++++++++--------- .../java/joshuatee/wx/nhc/NhcStormDetails.kt | 2 +- .../main/java/joshuatee/wx/objects/LatLon.kt | 32 +- .../main/java/joshuatee/wx/objects/Route.kt | 233 +++- .../main/java/joshuatee/wx/objects/Site.kt | 42 + .../main/java/joshuatee/wx/objects/Sites.kt | 90 ++ app/src/main/java/joshuatee/wx/radar/Metar.kt | 64 +- .../joshuatee/wx/radar/NexradLongPressMenu.kt | 33 +- .../joshuatee/wx/settings/FavAddActivity.kt | 12 +- .../wx/settings/FavRemoveActivity.kt | 19 +- .../wx/settings/UtilityHomeScreen.kt | 112 +- .../joshuatee/wx/settings/UtilityLocation.kt | 111 +- .../joshuatee/wx/spc/SPCSoundingsActivity.kt | 34 +- .../java/joshuatee/wx/ui/CardVerticalText2.kt | 1 - .../java/joshuatee/wx/util/DownloadImage.kt | 111 +- .../java/joshuatee/wx/util/SoundingSites.kt | 502 +++++---- .../joshuatee/wx/util/UtilityFavorites.kt | 10 +- .../java/joshuatee/wx/util/UtilityMath.kt | 69 +- build.gradle | 2 +- doc/ChangeLog.md | 26 +- doc/ChangeLog_User.md | 7 +- 24 files changed, 1594 insertions(+), 932 deletions(-) create mode 100644 app/src/main/java/joshuatee/wx/objects/Site.kt create mode 100644 app/src/main/java/joshuatee/wx/objects/Sites.kt diff --git a/DOC/Todo.md b/DOC/Todo.md index 6fb08037..f7f8ef69 100644 --- a/DOC/Todo.md +++ b/DOC/Todo.md @@ -14,6 +14,8 @@ ## Features +* [ADD] text for Soundings +* [ADD] migrate Nexrad/Wfo sites to Sites/Site framework * [ADD] edge-to-edge - https://developer.android.com/about/versions/15/behavior-changes-15#ux - https://developer.android.com/develop/ui/compose/layouts/insets diff --git a/app/build.gradle b/app/build.gradle index 208b3ac5..185d46b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -125,9 +125,9 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0' // https://developer.android.com/jetpack/androidx/versions implementation 'com.google.android.material:material:1.12.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.core:core-ktx:1.13.1' + implementation 'androidx.core:core-ktx:1.15.0' implementation 'androidx.media:media:1.7.0' implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.3.2' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6af5602e..a3bcff47 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,8 +22,8 @@ + android:versionCode="55919" + android:versionName="55919-elys"> diff --git a/app/src/main/java/joshuatee/wx/common/GlobalArrays.kt b/app/src/main/java/joshuatee/wx/common/GlobalArrays.kt index 57ff219a..2606fdad 100644 --- a/app/src/main/java/joshuatee/wx/common/GlobalArrays.kt +++ b/app/src/main/java/joshuatee/wx/common/GlobalArrays.kt @@ -26,520 +26,520 @@ package joshuatee.wx.common object GlobalArrays { val nwsImageProducts = listOf( - "RAD_2KM: Radar Mosaic", - "GOES16: GOES16 product last viewed", - "VIS_CONUS: Visible CONUS", - "CONUSWV: US Water Vapor", - "SND: Sounding/Hodograph", - "USWARN: US Warning map", - "AKWARN: AK Warning map", - "HIWARN: HI Warning map", - "FMAP: National Forecast Chart Day 1", - "FMAPD2: National Forecast Chart Day 2", - "FMAPD3: National Forecast Chart Day 3", - "FMAP12: WPC Fronts/NDFD Weather Type - 12hr", - "FMAP24: WPC Fronts/NDFD Weather Type - 24hr", - "FMAP36: WPC Fronts/NDFD Weather Type - 36hr", - "FMAP48: WPC Fronts/NDFD Weather Type - 48hr", - "FMAP72: WPC Fronts/NDFD Weather Type - 72hr", - "FMAP96: WPC Fronts/NDFD Weather Type - 96hr", - "FMAP120: WPC Fronts/NDFD Weather Type - 120hr", - "FMAP144: WPC Fronts/NDFD Weather Type - 144hr", - "FMAP168: WPC Fronts/NDFD Weather Type - 168hr", - "FMAP3D: Forecast map - 3day", - "FMAP4D: Forecast map - 4day", - "FMAP5D: Forecast map - 5day", - "FMAP6D: Forecast map - 6day", - "LTG: Lightning map", - "SWOD1: SPC Convective Outlook Day 1", - "SWOD2: SPC Convective Outlook Day 2", - "SWOD3: SPC Convective Outlook Day 3", - "STRPT: SPC Storm reports for today", - "SPC_TST: SPC Thunderstorm Outlook", - "QPF1: QPF Day 1", - "QPF2: QPF Day 2", - "QPF3: QPF Day 3", - "QPF1-2: QPF Day 1-2", - "QPF1-3: QPF Day 1-3", - "QPF4-5: QPF Day 4-5", - "QPF6-7: QPF Day 6-7", - "QPF1-5: QPF 5 Day Total", - "QPF1-7: QPF 7 Day Total", - "SPCMESO1: Favorite #1 (500mb)", - "SPCMESO2: Favorite #2 (pmsl)", - "SPCMESO3: Favorite #3 (ttd)", - "SPCMESO4: Favorite #4 (rgnlrad)", - "SPCMESO5: Favorite #5 (lllr)", - "SPCMESO6: Favorite #6 (laps)", - "WPC_ANALYSIS: WPC Analysis, Radar, Warnings", - "NHC2ATL: ATL Two-Day Graphical Tropical Weather Outlook", - "NHC5ATL: ATL Seven-Day Graphical Tropical Weather Outlook", - "NHC2EPAC: EPAC Two-Day Graphical Tropical Weather Outlook", - "NHC5EPAC: EPAC Seven-Day Graphical Tropical Weather Outlook", - "NHC2CPAC: CPAC Two-Day Graphical Tropical Weather Outlook", - "NHC5CPAC: CPAC Five-Day Graphical Tropical Weather Outlook", - "AURORA: Aurora Forecast" + "RAD_2KM: Radar Mosaic", + "GOES16: GOES16 product last viewed", + "VIS_CONUS: Visible CONUS", + "CONUSWV: US Water Vapor", + "SND: Sounding/Hodograph", + "USWARN: US Warning map", + "AKWARN: AK Warning map", + "HIWARN: HI Warning map", + "FMAP: National Forecast Chart Day 1", + "FMAPD2: National Forecast Chart Day 2", + "FMAPD3: National Forecast Chart Day 3", + "FMAP12: WPC Fronts/NDFD Weather Type - 12hr", + "FMAP24: WPC Fronts/NDFD Weather Type - 24hr", + "FMAP36: WPC Fronts/NDFD Weather Type - 36hr", + "FMAP48: WPC Fronts/NDFD Weather Type - 48hr", + "FMAP72: WPC Fronts/NDFD Weather Type - 72hr", + "FMAP96: WPC Fronts/NDFD Weather Type - 96hr", + "FMAP120: WPC Fronts/NDFD Weather Type - 120hr", + "FMAP144: WPC Fronts/NDFD Weather Type - 144hr", + "FMAP168: WPC Fronts/NDFD Weather Type - 168hr", + "FMAP3D: Forecast map - 3day", + "FMAP4D: Forecast map - 4day", + "FMAP5D: Forecast map - 5day", + "FMAP6D: Forecast map - 6day", + "LTG: Lightning map", + "SWOD1: SPC Convective Outlook Day 1", + "SWOD2: SPC Convective Outlook Day 2", + "SWOD3: SPC Convective Outlook Day 3", + "STRPT: SPC Storm reports for today", + "SPC_TST: SPC Thunderstorm Outlook", + "QPF1: QPF Day 1", + "QPF2: QPF Day 2", + "QPF3: QPF Day 3", + "QPF1-2: QPF Day 1-2", + "QPF1-3: QPF Day 1-3", + "QPF4-5: QPF Day 4-5", + "QPF6-7: QPF Day 6-7", + "QPF1-5: QPF 5 Day Total", + "QPF1-7: QPF 7 Day Total", + "SPCMESO1: Favorite #1 (500mb)", + "SPCMESO2: Favorite #2 (pmsl)", + "SPCMESO3: Favorite #3 (ttd)", + "SPCMESO4: Favorite #4 (rgnlrad)", + "SPCMESO5: Favorite #5 (lllr)", + "SPCMESO6: Favorite #6 (laps)", + "WPC_ANALYSIS: WPC Analysis, Radar, Warnings", + "NHC2ATL: ATL Two-Day Graphical Tropical Weather Outlook", + "NHC5ATL: ATL Seven-Day Graphical Tropical Weather Outlook", + "NHC2EPAC: EPAC Two-Day Graphical Tropical Weather Outlook", + "NHC5EPAC: EPAC Seven-Day Graphical Tropical Weather Outlook", + "NHC2CPAC: CPAC Two-Day Graphical Tropical Weather Outlook", + "NHC5CPAC: CPAC Five-Day Graphical Tropical Weather Outlook", + "AURORA: Aurora Forecast" ) - val soundingSites = listOf( - "ABR", - "ALB", - "ABQ", - "AMA", - "BIS", - "RNK", - "BOI", - "BRO", - "BUF", - "CAR", - "ILX", - "CHS", - "MPX", - "CHH", - "CRP", - "DRT", - "DNR", - "DDC", - "LKN", - "EPZ", - "FWD", - "APX", - "GGW", - "GJT", - "GYX", - "TFX", - "GRB", - "GSO", - "INL", - "JAN", - "JAX", - "LCH", - "LZK", - "MFR", - "MFL", - "MAF", - "BNA", - "MHX", - "OUN", - "LBF", - "OAK", - "FFC", - "PIT", - "DVN", - "UIL", - "UNR", - "REV", - "RIW", - "SLE", - "SLC", - "NKX", - "BMX", - "SHV", - "OTX", - "SGF", - "LWX", - "TLH", - "TBW", - "TOP", - "TUS", - "OKX", - "OAX", - "WAL", - "DTX", - "ILN", - "LIX", - "VBG", - "1Y7", - "76405", - "76458" - ) +// val soundingSites = listOf( +// "ABR", +// "ALB", +// "ABQ", +// "AMA", +// "BIS", +// "RNK", +// "BOI", +// "BRO", +// "BUF", +// "CAR", +// "ILX", +// "CHS", +// "MPX", +// "CHH", +// "CRP", +// "DRT", +// "DNR", +// "DDC", +// "LKN", +// "EPZ", +// "FWD", +// "APX", +// "GGW", +// "GJT", +// "GYX", +// "TFX", +// "GRB", +// "GSO", +// "INL", +// "JAN", +// "JAX", +// "LCH", +// "LZK", +// "MFR", +// "MFL", +// "MAF", +// "BNA", +// "MHX", +// "OUN", +// "LBF", +// "OAK", +// "FFC", +// "PIT", +// "DVN", +// "UIL", +// "UNR", +// "REV", +// "RIW", +// "SLE", +// "SLC", +// "NKX", +// "BMX", +// "SHV", +// "OTX", +// "SGF", +// "LWX", +// "TLH", +// "TBW", +// "TOP", +// "TUS", +// "OKX", +// "OAX", +// "WAL", +// "DTX", +// "ILN", +// "LIX", +// "VBG", +// "1Y7", +// "76405", +// "76458" +// ) val wfos = listOf( - "AFC: AK, Anchorage", - "AFG: AK, Fairbanks", - "AJK: AK, Juneau", - "BMX: AL, Birmingham", - "HUN: AL, Huntsville", - "MOB: AL, Mobile", - "LZK: AR, Little Rock", - "FGZ: AZ, Flagstaff", - "PSR: AZ, Phoenix", - "TWC: AZ, Tucson", - "EKA: CA, Eureka", - "HNX: CA, Hanford", - "LOX: CA, Los Angeles", - "MTR: CA, San Francisco", - "SGX: CA, San Diego", - "STO: CA, Sacramento", - "BOU: CO, Denver/Boulder", - "GJT: CO, Grand Junction", - "PUB: CO, Pueblo", - "JAX: FL, Jacksonville", - "KEY: FL, Key West", - "MFL: FL, Miami", - "MLB: FL, Melbourne", - "TAE: FL, Tallahassee", - "TBW: FL, Tampa Bay Area", - "FFC: GA, Atlanta", - "GUM: GU, Guam", - "HFO: HI, Honolulu", - "DMX: IA, Des Moines", - "DVN: IA, Quad Cities", - "BOI: ID, Boise", - "PIH: ID, Pocatello", - "ILX: IL, Lincoln", - "LOT: IL, Chicago", - "IND: IN, Indianapolis", - "IWX: IN, Nrn. Indiana", - "DDC: KS, Dodge City", - "GLD: KS, Goodland", - "ICT: KS, Wichita", - "TOP: KS, Topeka", - "JKL: KY, Jackson", - "LMK: KY, Louisville", - "PAH: KY, Paducah", - "LCH: LA, Lake Charles", - "LIX: LA, New Orleans", - "SHV: LA, Shreveport", - "BOX: MA, Boston", - "CAR: ME, Caribou", - "GYX: ME, Gray", - "APX: MI, Gaylord", - "DTX: MI, Detroit", - "GRR: MI, Grand Rapids", - "MQT: MI, Marquette", - "DLH: MN, Duluth", - "MPX: MN, Twin Cities", - "EAX: MO, Kansas City", - "LSX: MO, St. Louis", - "SGF: MO, Springfield", - "JAN: MS, Jackson", - "BYZ: MT, Billings", - "GGW: MT, Glasgow", - "MSO: MT, Missoula", - "TFX: MT, Great Falls", - "ILM: NC, Wilmington", - "MHX: NC, Morehead City", - "RAH: NC, Raleigh", - "BIS: ND, Bismarck", - "FGF: ND, Grand Forks", - "GID: NE, Hastings", - "LBF: NE, North Platte", - "OAX: NE, Omaha", - "PHI: NJ, Mount Holly", - "ABQ: NM, Albuquerque", - "LKN: NV, Elko", - "REV: NV, Reno", - "VEF: NV, Las Vegas", - "ALY: NY, Albany", - "BGM: NY, Binghamton", - "BUF: NY, Buffalo", - "OKX: NY, New York City", - "CLE: OH, Cleveland", - "ILN: OH, Wilmington", - "OUN: OK, Norman", - "TSA: OK, Tulsa", - "MFR: OR, Medford", - "PDT: OR, Pendleton", - "PQR: OR, Portland", - "CTP: PA, State College", - "PBZ: PA, Pittsburgh", - "SJU: PR, San Juan", - "CAE: SC, Columbia", - "CHS: SC, Charleston", - "GSP: SC, Greer", - "ABR: SD, Aberdeen", - "FSD: SD, Sioux Falls", - "UNR: SD, Rapid City", - "MEG: TN, Memphis", - "MRX: TN, Morristown", - "OHX: TN, Nashville", - "AMA: TX, Amarillo", - "BRO: TX, Brownsville", - "CRP: TX, Corpus Christi", - "EPZ: TX, El Paso", - "EWX: TX, Austin/San Antonio", - "FWD: TX, Dallas/Fort Worth", - "HGX: TX, Houston", - "LUB: TX, Lubbock", - "MAF: TX, Midland/Odessa", - "SJT: TX, San Angelo", - "SLC: UT, Salt Lake City", - "AKQ: VA, Wakefield", - "LWX: VA, Sterling", - "RNK: VA, Blacksburg", - "BTV: VT, Burlington", - "OTX: WA, Spokane", - "SEW: WA, Seattle", - "ARX: WI, La Crosse", - "GRB: WI, Green Bay", - "MKX: WI, Milwaukee", - "RLX: WV, Charleston", - "CYS: WY, Cheyenne", - "RIW: WY, Riverton" + "AFC: AK, Anchorage", + "AFG: AK, Fairbanks", + "AJK: AK, Juneau", + "BMX: AL, Birmingham", + "HUN: AL, Huntsville", + "MOB: AL, Mobile", + "LZK: AR, Little Rock", + "FGZ: AZ, Flagstaff", + "PSR: AZ, Phoenix", + "TWC: AZ, Tucson", + "EKA: CA, Eureka", + "HNX: CA, Hanford", + "LOX: CA, Los Angeles", + "MTR: CA, San Francisco", + "SGX: CA, San Diego", + "STO: CA, Sacramento", + "BOU: CO, Denver/Boulder", + "GJT: CO, Grand Junction", + "PUB: CO, Pueblo", + "JAX: FL, Jacksonville", + "KEY: FL, Key West", + "MFL: FL, Miami", + "MLB: FL, Melbourne", + "TAE: FL, Tallahassee", + "TBW: FL, Tampa Bay Area", + "FFC: GA, Atlanta", + "GUM: GU, Guam", + "HFO: HI, Honolulu", + "DMX: IA, Des Moines", + "DVN: IA, Quad Cities", + "BOI: ID, Boise", + "PIH: ID, Pocatello", + "ILX: IL, Lincoln", + "LOT: IL, Chicago", + "IND: IN, Indianapolis", + "IWX: IN, Nrn. Indiana", + "DDC: KS, Dodge City", + "GLD: KS, Goodland", + "ICT: KS, Wichita", + "TOP: KS, Topeka", + "JKL: KY, Jackson", + "LMK: KY, Louisville", + "PAH: KY, Paducah", + "LCH: LA, Lake Charles", + "LIX: LA, New Orleans", + "SHV: LA, Shreveport", + "BOX: MA, Boston", + "CAR: ME, Caribou", + "GYX: ME, Gray", + "APX: MI, Gaylord", + "DTX: MI, Detroit", + "GRR: MI, Grand Rapids", + "MQT: MI, Marquette", + "DLH: MN, Duluth", + "MPX: MN, Twin Cities", + "EAX: MO, Kansas City", + "LSX: MO, St. Louis", + "SGF: MO, Springfield", + "JAN: MS, Jackson", + "BYZ: MT, Billings", + "GGW: MT, Glasgow", + "MSO: MT, Missoula", + "TFX: MT, Great Falls", + "ILM: NC, Wilmington", + "MHX: NC, Morehead City", + "RAH: NC, Raleigh", + "BIS: ND, Bismarck", + "FGF: ND, Grand Forks", + "GID: NE, Hastings", + "LBF: NE, North Platte", + "OAX: NE, Omaha", + "PHI: NJ, Mount Holly", + "ABQ: NM, Albuquerque", + "LKN: NV, Elko", + "REV: NV, Reno", + "VEF: NV, Las Vegas", + "ALY: NY, Albany", + "BGM: NY, Binghamton", + "BUF: NY, Buffalo", + "OKX: NY, New York City", + "CLE: OH, Cleveland", + "ILN: OH, Wilmington", + "OUN: OK, Norman", + "TSA: OK, Tulsa", + "MFR: OR, Medford", + "PDT: OR, Pendleton", + "PQR: OR, Portland", + "CTP: PA, State College", + "PBZ: PA, Pittsburgh", + "SJU: PR, San Juan", + "CAE: SC, Columbia", + "CHS: SC, Charleston", + "GSP: SC, Greer", + "ABR: SD, Aberdeen", + "FSD: SD, Sioux Falls", + "UNR: SD, Rapid City", + "MEG: TN, Memphis", + "MRX: TN, Morristown", + "OHX: TN, Nashville", + "AMA: TX, Amarillo", + "BRO: TX, Brownsville", + "CRP: TX, Corpus Christi", + "EPZ: TX, El Paso", + "EWX: TX, Austin/San Antonio", + "FWD: TX, Dallas/Fort Worth", + "HGX: TX, Houston", + "LUB: TX, Lubbock", + "MAF: TX, Midland/Odessa", + "SJT: TX, San Angelo", + "SLC: UT, Salt Lake City", + "AKQ: VA, Wakefield", + "LWX: VA, Sterling", + "RNK: VA, Blacksburg", + "BTV: VT, Burlington", + "OTX: WA, Spokane", + "SEW: WA, Seattle", + "ARX: WI, La Crosse", + "GRB: WI, Green Bay", + "MKX: WI, Milwaukee", + "RLX: WV, Charleston", + "CYS: WY, Cheyenne", + "RIW: WY, Riverton" ) val radars = listOf( - "ABC: AK, Bethel", - "APD: AK, Fairbanks/Pedro Dome", - "AHG: AK, Kenai", - "AKC: AK, King Salmon", - "AIH: AK, Middleton Island", - "AEC: AK, Nome", - "ACG: AK, Sitka/Biorka Island", - "BMX: AL, Birmingham", - "EOX: AL, Fort Rucker", - "HTX: AL, Huntsville", - "MXX: AL, Maxwell AFB", - "MOB: AL, Mobile", - "SRX: AR, Fort Smith", - "LZK: AR, Little Rock", - "FSX: AZ, Flagstaff", - "IWA: AZ, Phoenix", - "EMX: AZ, Tucson", - "YUX: AZ, Yuma", - "BBX: CA, Beale AFB", - "EYX: CA, Edwards AFB", - "BHX: CA, Eureka", - "VTX: CA, Los Angeles", - "DAX: CA, Sacramento", - "NKX: CA, San Diego", - "MUX: CA, San Francisco", - "HNX: CA, San Joaquin Valley", - "SOX: CA, Santa Ana Mountains", - "VBX: CA, Vandenberg AFB", - "FTG: CO, Denver", - "GJX: CO, Grand Junction", - "PUX: CO, Pueblo", - "DOX: DE, Dover AFB", - "EVX: FL, Eglin AFB", - "JAX: FL, Jacksonville", - "BYX: FL, Key West", - "MLB: FL, Melbourne", - "AMX: FL, Miami", - "TLH: FL, Tallahassee", - "TBW: FL, Tampa", - "FFC: GA, Atlanta", - "VAX: GA, Moody AFB", - "JGX: GA, Robins AFB", - "GUA: GU, Andersen AFB", - "HKI: HI, Kauai", - "HKM: HI, Kohala", - "HMO: HI, Molokai", - "HWA: HI, South Shore", - "DVN: IA, Davenport", - "DMX: IA, Des Moines", - "CBX: ID, Boise", - "SFX: ID, Pocatello/Idaho Falls", - "LOT: IL, Chicago", - "ILX: IL, Lincoln", - "VWX: IN, Evansville", - "IND: IN, Indianapolis", - "IWX: IN, North Webster", - "DDC: KS, Dodge City", - "GLD: KS, Goodland", - "TWX: KS, Topeka", - "ICT: KS, Wichita", - "HPX: KY, Fort Campbell", - "JKL: KY, Jackson", - "LVX: KY, Louisville", - "PAH: KY, Paducah", - "POE: LA, Fort Polk", - "HDC: LA, Hammond", // to Begin NEXRAD Level III Product Dissemination on or around March 31, 2024 Service Change Notice 24-11 - "LCH: LA, Lake Charles", - "LIX: LA, New Orleans", // GONE as of late 2023 - "SHV: LA, Shreveport", - "BOX: MA, Boston", - "CBW: ME, Loring AFB", - "GYX: ME, Portland", - "DTX: MI, Detroit/Pontiac", - "APX: MI, Gaylord", - "GRR: MI, Grand Rapids", - "MQT: MI, Marquette", - "DLH: MN, Duluth", - "MPX: MN, Minneapolis/St. Paul", - "EAX: MO, Kansas City", - "SGF: MO, Springfield", - "LSX: MO, St. Louis", - "DGX: MS, Brandon/Jackson", - "GWX: MS, Columbus AFB", - "BLX: MT, Billings", - "GGW: MT, Glasgow", - "TFX: MT, Great Falls", - "MSX: MT, Missoula", - "KSG: NA, Camp Humphreys, South Korea", - "ODN: NA, Kadena Air Base, Japan", - "KJK: NA, Kunsan Air Base, South Korea", - "PLA: NA, Lajes Field, Azores", - "MHX: NC, Morehead City", - "RAX: NC, Raleigh/Durham", - "LTX: NC, Wilmington", - "BIS: ND, Bismarck", - "MVX: ND, Grand Forks (Mayville)", - "MBX: ND, Minot AFB", - "UEX: NE, Grand Island/Hastings", - "LNX: NE, North Platte", - "OAX: NE, Omaha", - "ABX: NM, Albuquerque", - "FDX: NM, Cannon AFB", - "HDX: NM, Holloman AFB", - "LRX: NV, Elko", - "ESX: NV, Las Vegas", - "RGX: NV, Reno", - "ENX: NY, Albany", - "BGM: NY, Binghamton", - "BUF: NY, Buffalo", - "TYX: NY, Montague", - "OKX: NY, New York City", - "CLE: OH, Cleveland", - "ILN: OH, Wilmington", - "FDR: OK, Frederick", - "TLX: OK, Oklahoma City", - "INX: OK, Tulsa", - "VNX: OK, Vance AFB", - "MAX: OR, Medford", - "PDT: OR, Pendleton", - "RTX: OR, Portland", - "DIX: PA, Philadelphia", - "PBZ: PA, Pittsburgh", - "CCX: PA, State College", - "JUA: PR, San Juan", - "CLX: SC, Charleston", - "CAE: SC, Columbia", - "GSP: SC, Greer", - "ABR: SD, Aberdeen", - "UDX: SD, Rapid City", - "FSD: SD, Sioux Falls", - "MRX: TN, Knoxville/Tri Cities", - "NQA: TN, Memphis", - "OHX: TN, Nashville", - "AMA: TX, Amarillo", - "EWX: TX, Austin/San Antonio", - "BRO: TX, Brownsville", - "CRP: TX, Corpus Christi", - "FWS: TX, Dallas/Ft. Worth", - "DYX: TX, Dyess AFB", - "EPZ: TX, El Paso", - "GRK: TX, Fort Hood", - "HGX: TX, Houston/Galveston", - "DFX: TX, Laughlin AFB", - "LBB: TX, Lubbock", - "MAF: TX, Midland/Odessa", - "SJT: TX, San Angelo", - "ICX: UT, Cedar City", - "MTX: UT, Salt Lake City", - "AKQ: VA, Norfolk/Richmond", - "FCX: VA, Roanoke", - "LWX: VA, Sterling", - "CXX: VT, Burlington", - "LGX: WA, Langley Hill", - "ATX: WA, Seattle/Tacoma", - "OTX: WA, Spokane", - "GRB: WI, Green Bay", - "ARX: WI, La Crosse", - "MKX: WI, Milwaukee", - "RLX: WV, Charleston", - "CYS: WY, Cheyenne", - "RIW: WY, Riverton" + "ABC: AK, Bethel", + "APD: AK, Fairbanks/Pedro Dome", + "AHG: AK, Kenai", + "AKC: AK, King Salmon", + "AIH: AK, Middleton Island", + "AEC: AK, Nome", + "ACG: AK, Sitka/Biorka Island", + "BMX: AL, Birmingham", + "EOX: AL, Fort Rucker", + "HTX: AL, Huntsville", + "MXX: AL, Maxwell AFB", + "MOB: AL, Mobile", + "SRX: AR, Fort Smith", + "LZK: AR, Little Rock", + "FSX: AZ, Flagstaff", + "IWA: AZ, Phoenix", + "EMX: AZ, Tucson", + "YUX: AZ, Yuma", + "BBX: CA, Beale AFB", + "EYX: CA, Edwards AFB", + "BHX: CA, Eureka", + "VTX: CA, Los Angeles", + "DAX: CA, Sacramento", + "NKX: CA, San Diego", + "MUX: CA, San Francisco", + "HNX: CA, San Joaquin Valley", + "SOX: CA, Santa Ana Mountains", + "VBX: CA, Vandenberg AFB", + "FTG: CO, Denver", + "GJX: CO, Grand Junction", + "PUX: CO, Pueblo", + "DOX: DE, Dover AFB", + "EVX: FL, Eglin AFB", + "JAX: FL, Jacksonville", + "BYX: FL, Key West", + "MLB: FL, Melbourne", + "AMX: FL, Miami", + "TLH: FL, Tallahassee", + "TBW: FL, Tampa", + "FFC: GA, Atlanta", + "VAX: GA, Moody AFB", + "JGX: GA, Robins AFB", + "GUA: GU, Andersen AFB", + "HKI: HI, Kauai", + "HKM: HI, Kohala", + "HMO: HI, Molokai", + "HWA: HI, South Shore", + "DVN: IA, Davenport", + "DMX: IA, Des Moines", + "CBX: ID, Boise", + "SFX: ID, Pocatello/Idaho Falls", + "LOT: IL, Chicago", + "ILX: IL, Lincoln", + "VWX: IN, Evansville", + "IND: IN, Indianapolis", + "IWX: IN, North Webster", + "DDC: KS, Dodge City", + "GLD: KS, Goodland", + "TWX: KS, Topeka", + "ICT: KS, Wichita", + "HPX: KY, Fort Campbell", + "JKL: KY, Jackson", + "LVX: KY, Louisville", + "PAH: KY, Paducah", + "POE: LA, Fort Polk", + "HDC: LA, Hammond", // to Begin NEXRAD Level III Product Dissemination on or around March 31, 2024 Service Change Notice 24-11 + "LCH: LA, Lake Charles", + "LIX: LA, New Orleans", // GONE as of late 2023 + "SHV: LA, Shreveport", + "BOX: MA, Boston", + "CBW: ME, Loring AFB", + "GYX: ME, Portland", + "DTX: MI, Detroit/Pontiac", + "APX: MI, Gaylord", + "GRR: MI, Grand Rapids", + "MQT: MI, Marquette", + "DLH: MN, Duluth", + "MPX: MN, Minneapolis/St. Paul", + "EAX: MO, Kansas City", + "SGF: MO, Springfield", + "LSX: MO, St. Louis", + "DGX: MS, Brandon/Jackson", + "GWX: MS, Columbus AFB", + "BLX: MT, Billings", + "GGW: MT, Glasgow", + "TFX: MT, Great Falls", + "MSX: MT, Missoula", + "KSG: NA, Camp Humphreys, South Korea", + "ODN: NA, Kadena Air Base, Japan", + "KJK: NA, Kunsan Air Base, South Korea", + "PLA: NA, Lajes Field, Azores", + "MHX: NC, Morehead City", + "RAX: NC, Raleigh/Durham", + "LTX: NC, Wilmington", + "BIS: ND, Bismarck", + "MVX: ND, Grand Forks (Mayville)", + "MBX: ND, Minot AFB", + "UEX: NE, Grand Island/Hastings", + "LNX: NE, North Platte", + "OAX: NE, Omaha", + "ABX: NM, Albuquerque", + "FDX: NM, Cannon AFB", + "HDX: NM, Holloman AFB", + "LRX: NV, Elko", + "ESX: NV, Las Vegas", + "RGX: NV, Reno", + "ENX: NY, Albany", + "BGM: NY, Binghamton", + "BUF: NY, Buffalo", + "TYX: NY, Montague", + "OKX: NY, New York City", + "CLE: OH, Cleveland", + "ILN: OH, Wilmington", + "FDR: OK, Frederick", + "TLX: OK, Oklahoma City", + "INX: OK, Tulsa", + "VNX: OK, Vance AFB", + "MAX: OR, Medford", + "PDT: OR, Pendleton", + "RTX: OR, Portland", + "DIX: PA, Philadelphia", + "PBZ: PA, Pittsburgh", + "CCX: PA, State College", + "JUA: PR, San Juan", + "CLX: SC, Charleston", + "CAE: SC, Columbia", + "GSP: SC, Greer", + "ABR: SD, Aberdeen", + "UDX: SD, Rapid City", + "FSD: SD, Sioux Falls", + "MRX: TN, Knoxville/Tri Cities", + "NQA: TN, Memphis", + "OHX: TN, Nashville", + "AMA: TX, Amarillo", + "EWX: TX, Austin/San Antonio", + "BRO: TX, Brownsville", + "CRP: TX, Corpus Christi", + "FWS: TX, Dallas/Ft. Worth", + "DYX: TX, Dyess AFB", + "EPZ: TX, El Paso", + "GRK: TX, Fort Hood", + "HGX: TX, Houston/Galveston", + "DFX: TX, Laughlin AFB", + "LBB: TX, Lubbock", + "MAF: TX, Midland/Odessa", + "SJT: TX, San Angelo", + "ICX: UT, Cedar City", + "MTX: UT, Salt Lake City", + "AKQ: VA, Norfolk/Richmond", + "FCX: VA, Roanoke", + "LWX: VA, Sterling", + "CXX: VT, Burlington", + "LGX: WA, Langley Hill", + "ATX: WA, Seattle/Tacoma", + "OTX: WA, Spokane", + "GRB: WI, Green Bay", + "ARX: WI, La Crosse", + "MKX: WI, Milwaukee", + "RLX: WV, Charleston", + "CYS: WY, Cheyenne", + "RIW: WY, Riverton" ) val tdwrRadars = listOf( - "TPHX: AZ, Phoenix", - "TDEN: CO, Denver", - "TFLL: FL, Fort Lauderdale", - "TMIA: FL, Miami", - "TMCO: FL, Orlando International", - "TTPA: FL, Tampa Bay", - "TPBI: FL, West Palm Beach", - "TATL: GA, Atlanta", - "TMDW: IL, Chicago Midway", - "TORD: IL, Chicago O'Hare", - "TIDS: IN, Indianapolis", - "TICH: KS, Wichita", - "TSDF: KY, Louisville", - "TMSY: LA, New Orleans", - "TBOS: MA, Boston", - "TBWI: MD, Baltimore/Wash", - "TDCA: MD, Washington National", - "TDTW: MI, Detroit", - "TMSP: MN, Minneapolis", - "TMCI: MO, Kansas City", - "TSTL: MO, St Louis", - "TCLT: NC, Charlotte", - "TRDU: NC, Raleigh Durham", - "TEWR: NJ, Newark", - "TLAS: NV, Las Vegas", - "TJFK: NY, New York City", - "TLVE: OH, Cleveland", - "TCMH: OH, Columbus", - "TCVG: OH, Covington", - "TDAY: OH, Dayton", - "TOKC: OK, Oklahoma City", - "TTUL: OK, Tulsa", - "TPHL: PA, Philadelphia", - "TPIT: PA, Pittsburgh", - "TSJU: PR, San Juan", - "TMEM: TN, Memphis", - "TBNA: TN, Nashville", - "TDFW: TX, Dallas/Ft. Worth", - "TDAL: TX, Dallas Love Field", - "THOU: TX, Houston Hobby", - "TIAH: TX, Houston International", - "TSLC: UT, Salt Lake City", - "TIAD: VA, Dulles", - "TMKE: WI, Milwaukee" + "TPHX: AZ, Phoenix", + "TDEN: CO, Denver", + "TFLL: FL, Fort Lauderdale", + "TMIA: FL, Miami", + "TMCO: FL, Orlando International", + "TTPA: FL, Tampa Bay", + "TPBI: FL, West Palm Beach", + "TATL: GA, Atlanta", + "TMDW: IL, Chicago Midway", + "TORD: IL, Chicago O'Hare", + "TIDS: IN, Indianapolis", + "TICH: KS, Wichita", + "TSDF: KY, Louisville", + "TMSY: LA, New Orleans", + "TBOS: MA, Boston", + "TBWI: MD, Baltimore/Wash", + "TDCA: MD, Washington National", + "TDTW: MI, Detroit", + "TMSP: MN, Minneapolis", + "TMCI: MO, Kansas City", + "TSTL: MO, St Louis", + "TCLT: NC, Charlotte", + "TRDU: NC, Raleigh Durham", + "TEWR: NJ, Newark", + "TLAS: NV, Las Vegas", + "TJFK: NY, New York City", + "TLVE: OH, Cleveland", + "TCMH: OH, Columbus", + "TCVG: OH, Covington", + "TDAY: OH, Dayton", + "TOKC: OK, Oklahoma City", + "TTUL: OK, Tulsa", + "TPHL: PA, Philadelphia", + "TPIT: PA, Pittsburgh", + "TSJU: PR, San Juan", + "TMEM: TN, Memphis", + "TBNA: TN, Nashville", + "TDFW: TX, Dallas/Ft. Worth", + "TDAL: TX, Dallas Love Field", + "THOU: TX, Houston Hobby", + "TIAH: TX, Houston International", + "TSLC: UT, Salt Lake City", + "TIAD: VA, Dulles", + "TMKE: WI, Milwaukee" ) val states = listOf( - "AL: Alabama", - "AK: Alaska", - "AZ: Arizona", - "AR: Arkansas", - "CA: California", - "CO: Colorado", - "CT: Connecticut", - "DE: Delaware", - "FL: Florida", - "GA: Georgia", - "HI: Hawaii", - "ID: Idaho", - "IL: Illinois", - "IN: Indiana", - "IA: Iowa", - "KS: Kansas", - "KY: Kentucky", - "LA: Louisiana", - "ME: Maine", - "MD: Maryland", - "MA: Massachusetts", - "MI: Michigan", - "MN: Minnesota", - "MS: Mississippi", - "MO: Missouri", - "MT: Montana", - "NE: Nebraska", - "NV: Nevada", - "NH: New Hampshire", - "NJ: New Jersey", - "NM: New Mexico", - "NY: New York", - "NC: North Carolina", - "ND: North Dakota", - "OH: Ohio", - "OK: Oklahoma", - "OR: Oregon", - "PA: Pennsylvania", - "RI: Rhode Island", - "SC: South Carolina", - "SD: South Dakota", - "TN: Tennessee", - "TX: Texas", - "UT: Utah", - "VT: Vermont", - "VA: Virginia", - "WA: Washington", - "WV: West Virginia", - "WI: Wisconsin", - "WY: Wyoming" + "AL: Alabama", + "AK: Alaska", + "AZ: Arizona", + "AR: Arkansas", + "CA: California", + "CO: Colorado", + "CT: Connecticut", + "DE: Delaware", + "FL: Florida", + "GA: Georgia", + "HI: Hawaii", + "ID: Idaho", + "IL: Illinois", + "IN: Indiana", + "IA: Iowa", + "KS: Kansas", + "KY: Kentucky", + "LA: Louisiana", + "ME: Maine", + "MD: Maryland", + "MA: Massachusetts", + "MI: Michigan", + "MN: Minnesota", + "MS: Mississippi", + "MO: Missouri", + "MT: Montana", + "NE: Nebraska", + "NV: Nevada", + "NH: New Hampshire", + "NJ: New Jersey", + "NM: New Mexico", + "NY: New York", + "NC: North Carolina", + "ND: North Dakota", + "OH: Ohio", + "OK: Oklahoma", + "OR: Oregon", + "PA: Pennsylvania", + "RI: Rhode Island", + "SC: South Carolina", + "SD: South Dakota", + "TN: Tennessee", + "TX: Texas", + "UT: Utah", + "VT: Vermont", + "VA: Virginia", + "WA: Washington", + "WV: West Virginia", + "WI: Wisconsin", + "WY: Wyoming" ) } diff --git a/app/src/main/java/joshuatee/wx/nhc/NhcStormDetails.kt b/app/src/main/java/joshuatee/wx/nhc/NhcStormDetails.kt index 50218132..bc7a5e65 100644 --- a/app/src/main/java/joshuatee/wx/nhc/NhcStormDetails.kt +++ b/app/src/main/java/joshuatee/wx/nhc/NhcStormDetails.kt @@ -50,7 +50,7 @@ class NhcStormDetails( var center = "$lat $lon" var dateTime = lastUpdate var movement = - UtilityMath.convertWindDir(To.double(movementDir)) + " at " + movementSpeed + " mph" + UtilityMath.bearingToDirection(To.int(movementDir)) + "(${movementDir}) at " + movementSpeed + " mph" var baseUrl: String var goesUrl: String var advisoryNumber = advisoryUrl.split("/").last().replace(".shtml", "") diff --git a/app/src/main/java/joshuatee/wx/objects/LatLon.kt b/app/src/main/java/joshuatee/wx/objects/LatLon.kt index 52874333..74fa9e8b 100644 --- a/app/src/main/java/joshuatee/wx/objects/LatLon.kt +++ b/app/src/main/java/joshuatee/wx/objects/LatLon.kt @@ -25,6 +25,7 @@ import joshuatee.wx.external.ExternalPoint import joshuatee.wx.util.UtilityMath import joshuatee.wx.util.UtilityString import kotlin.math.acos +import kotlin.math.atan2 import kotlin.math.cos import kotlin.math.sin import joshuatee.wx.isEven @@ -123,6 +124,10 @@ class LatLon() { lonNum = To.double(newValue) } + private fun latInRadians() = UtilityMath.deg2rad(lat) + + private fun lonInRadians() = UtilityMath.deg2rad(lon) + val latForNws: String get() { return latNum.toBigDecimal().setScale(4, RoundingMode.UP).toDouble().toString() @@ -149,7 +154,11 @@ class LatLon() { // 1.1515 is the number of statute miles in a nautical mile // 1.609344 is the number of kilometres in a mile - fun distance(location1: LatLon, location2: LatLon, unit: DistanceUnit): Double { + fun distance( + location1: LatLon, + location2: LatLon, + unit: DistanceUnit = DistanceUnit.MILE + ): Double { val theta = location1.lon - location2.lon var dist = sin(UtilityMath.deg2rad(location1.lat)) * sin(UtilityMath.deg2rad(location2.lat)) + cos( @@ -166,6 +175,27 @@ class LatLon() { } } + private fun calculateBearing(start: LatLon, end: LatLon): Int { + val deltaLon = end.lonInRadians() - start.lonInRadians() + val x = cos(end.latInRadians()) * sin(deltaLon) + val y = + cos(start.latInRadians()) * sin(end.latInRadians()) - sin(start.latInRadians()) * cos( + end.latInRadians() + ) * cos( + deltaLon + ) + val b = atan2(x, y) + var bearing = UtilityMath.rad2deg(b).toInt() % 360 + if (bearing < 0) { + bearing += 360 + } + return bearing + } + + fun calculateDirection(start: LatLon, end: LatLon): String { + return UtilityMath.bearingToDirection(calculateBearing(start, end)) + } + // take a space separated list of numbers and return a list of LatLon, list is of the format // lon0 lat0 lon1 lat1 for watch // for UtilityWatch need to multiply Y by -1.0 diff --git a/app/src/main/java/joshuatee/wx/objects/Route.kt b/app/src/main/java/joshuatee/wx/objects/Route.kt index 4a00e612..0d01d91f 100644 --- a/app/src/main/java/joshuatee/wx/objects/Route.kt +++ b/app/src/main/java/joshuatee/wx/objects/Route.kt @@ -67,7 +67,12 @@ import joshuatee.wx.wpc.NationalTextActivity class Route() { - constructor(context: Context, clazz: Class<*>, url: String, stringArray: Array) : this() { + constructor( + context: Context, + clazz: Class<*>, + url: String, + stringArray: Array + ) : this() { val intent = Intent(context, clazz) intent.putExtra(url, stringArray) context.startActivity(intent) @@ -95,15 +100,23 @@ class Route() { fun alerts(context: Context) { Route( - context, - USAlertsActivity::class.java, - USAlertsActivity.URL, - arrayOf(".*?Tornado Warning.*?|.*?Severe Thunderstorm Warning.*?|.*?Flash Flood Warning.*?", "us") + context, + USAlertsActivity::class.java, + USAlertsActivity.URL, + arrayOf( + ".*?Tornado Warning.*?|.*?Severe Thunderstorm Warning.*?|.*?Flash Flood Warning.*?", + "us" + ) ) } fun colorPicker(context: Context, pref: String, label: String) { - Route(context, SettingsColorPickerActivity::class.java, SettingsColorPickerActivity.INFO, arrayOf(pref, label)) + Route( + context, + SettingsColorPickerActivity::class.java, + SettingsColorPickerActivity.INFO, + arrayOf(pref, label) + ) } fun favoriteAdd(context: Context, type: FavoriteType) { @@ -111,15 +124,30 @@ class Route() { } fun favoriteRemove(context: Context, type: FavoriteType) { - Route(context, FavRemoveActivity::class.java, FavRemoveActivity.TYPE, arrayOf(type.name)) + Route( + context, + FavRemoveActivity::class.java, + FavRemoveActivity.TYPE, + arrayOf(type.name) + ) } fun forecast(context: Context, latLon: LatLon) { - Route(context, ForecastActivity::class.java, ForecastActivity.URL, arrayOf(latLon.latString, latLon.lonString)) + Route( + context, + ForecastActivity::class.java, + ForecastActivity.URL, + arrayOf(latLon.latString, latLon.lonString) + ) } fun goesFd(context: Context) { - Route(context, ImageCollectionActivity::class.java, ImageCollectionActivity.TYPE, arrayOf("GOESFD")) + Route( + context, + ImageCollectionActivity::class.java, + ImageCollectionActivity.TYPE, + arrayOf("GOESFD") + ) } fun hazard(context: Context, url: String) { @@ -128,12 +156,22 @@ class Route() { fun hourly(context: Context) { if (Location.isUS) { - Route(context, HourlyActivity::class.java, HourlyActivity.LOC_NUM, Location.currentLocationStr) + Route( + context, + HourlyActivity::class.java, + HourlyActivity.LOC_NUM, + Location.currentLocationStr + ) } } fun image(context: Context, url: String, title: String) { - Route(context, ImageShowActivity::class.java, ImageShowActivity.URL, arrayOf(url, title)) + Route( + context, + ImageShowActivity::class.java, + ImageShowActivity.URL, + arrayOf(url, title) + ) } fun lightning(context: Context) { @@ -141,19 +179,39 @@ class Route() { } fun locationEdit(context: Context, locationNumber: String) { - Route(context, SettingsLocationGenericActivity::class.java, SettingsLocationGenericActivity.LOC_NUM, arrayOf(locationNumber)) + Route( + context, + SettingsLocationGenericActivity::class.java, + SettingsLocationGenericActivity.LOC_NUM, + arrayOf(locationNumber) + ) } fun lsrByWfo(context: Context) { - Route(context, LsrByWfoActivity::class.java, LsrByWfoActivity.URL, arrayOf(Location.wfo, "LSR")) + Route( + context, + LsrByWfoActivity::class.java, + LsrByWfoActivity.URL, + arrayOf(Location.wfo, "LSR") + ) } fun mcd(context: Context, number: String, type: String) { - Route(context, SpcMcdWatchShowActivity::class.java, SpcMcdWatchShowActivity.NUMBER, arrayOf(number, type)) + Route( + context, + SpcMcdWatchShowActivity::class.java, + SpcMcdWatchShowActivity.NUMBER, + arrayOf(number, type) + ) } fun model(context: Context, numberPanes: String, prefToken: String, title: String) { - Route(context, ModelsGenericActivity::class.java, ModelsGenericActivity.INFO, arrayOf(numberPanes, prefToken, title)) + Route( + context, + ModelsGenericActivity::class.java, + ModelsGenericActivity.INFO, + arrayOf(numberPanes, prefToken, title) + ) } fun modelEsrl(context: Context) { @@ -179,7 +237,12 @@ class Route() { } fun observations(context: Context) { - Route(context, ImageCollectionActivity::class.java, ImageCollectionActivity.TYPE, arrayOf("OBSERVATIONS")) + Route( + context, + ImageCollectionActivity::class.java, + ImageCollectionActivity.TYPE, + arrayOf("OBSERVATIONS") + ) } fun obsSites(context: Context) { @@ -187,7 +250,12 @@ class Route() { } fun opc(context: Context) { - Route(context, ImageCollectionActivity::class.java, ImageCollectionActivity.TYPE, arrayOf("OPC")) + Route( + context, + ImageCollectionActivity::class.java, + ImageCollectionActivity.TYPE, + arrayOf("OPC") + ) } fun playlist(context: Context) { @@ -217,7 +285,12 @@ class Route() { } fun radarMultiPane(context: Context, array: Array) { - Route(context, WXGLRadarActivityMultiPane::class.java, WXGLRadarActivityMultiPane.RID, array) + Route( + context, + WXGLRadarActivityMultiPane::class.java, + WXGLRadarActivityMultiPane.RID, + array + ) } fun radarMultiPane2(context: Context) { @@ -229,7 +302,12 @@ class Route() { } fun radarMosaic(context: Context) { - Route(context, RadarMosaicNwsActivity::class.java, RadarMosaicNwsActivity.URL, arrayOf("")) + Route( + context, + RadarMosaicNwsActivity::class.java, + RadarMosaicNwsActivity.URL, + arrayOf("") + ) } fun rtma(context: Context) { @@ -248,8 +326,14 @@ class Route() { Route(context, SevereDashboardActivity::class.java) } - fun sounding(context: Context) { - Route(context, SpcSoundingsActivity::class.java, SpcSoundingsActivity.URL, arrayOf(Location.wfo, "")) + // TODO FIXME 1st arg seems unused, changed 2nd arg from "" to site + fun sounding(context: Context, site: String = "") { + Route( + context, + SpcSoundingsActivity::class.java, + SpcSoundingsActivity.URL, + arrayOf(Location.wfo, site) + ) } fun spcCompmap(context: Context) { @@ -261,15 +345,30 @@ class Route() { } fun spcFireOutlookByDay(context: Context, index: Int) { - Route(context, SpcFireOutlookActivity::class.java, SpcFireOutlookActivity.NUMBER, arrayOf(index.toString())) + Route( + context, + SpcFireOutlookActivity::class.java, + SpcFireOutlookActivity.NUMBER, + arrayOf(index.toString()) + ) } fun spcHref(context: Context) { - Route(context, ModelsSpcHrefActivity::class.java, "", arrayOf("1", "SPCHREF", "SPC HREF")) + Route( + context, + ModelsSpcHrefActivity::class.java, + "", + arrayOf("1", "SPCHREF", "SPC HREF") + ) } fun spcHrefDualPane(context: Context) { - Route(context, ModelsSpcHrefActivity::class.java, "", arrayOf("2", "SPCHREF", "SPC HREF")) + Route( + context, + ModelsSpcHrefActivity::class.java, + "", + arrayOf("2", "SPCHREF", "SPC HREF") + ) } fun spcHrrr(context: Context) { @@ -277,23 +376,48 @@ class Route() { } fun spcMeso(context: Context) { - Route(context, SpcMesoActivity::class.java, SpcMesoActivity.INFO, arrayOf("", "1", "SPCMESO")) + Route( + context, + SpcMesoActivity::class.java, + SpcMesoActivity.INFO, + arrayOf("", "1", "SPCMESO") + ) } fun spcMesoDualPane(context: Context) { - Route(context, SpcMesoActivity::class.java, SpcMesoActivity.INFO, arrayOf("", "2", "SPCMESO")) + Route( + context, + SpcMesoActivity::class.java, + SpcMesoActivity.INFO, + arrayOf("", "2", "SPCMESO") + ) } fun spcSref(context: Context) { - Route(context, ModelsSpcHrefActivity::class.java, ModelsSpcHrefActivity.INFO, arrayOf("1", "SPCSREF", "SPCSREF")) + Route( + context, + ModelsSpcHrefActivity::class.java, + ModelsSpcHrefActivity.INFO, + arrayOf("1", "SPCSREF", "SPCSREF") + ) } fun spcSrefDualPane(context: Context) { - Route(context, ModelsSpcHrefActivity::class.java, ModelsSpcHrefActivity.INFO, arrayOf("2", "SPCSREF", "SPCSREF")) + Route( + context, + ModelsSpcHrefActivity::class.java, + ModelsSpcHrefActivity.INFO, + arrayOf("2", "SPCSREF", "SPCSREF") + ) } fun spcStormReports(context: Context) { - Route(context, SpcStormReportsActivity::class.java, SpcStormReportsActivity.DAY, arrayOf("today")) + Route( + context, + SpcStormReportsActivity::class.java, + SpcStormReportsActivity.DAY, + arrayOf("today") + ) } fun spcSwo(context: Context, day: String, sound: String = "") { @@ -330,17 +454,32 @@ class Route() { // url could be a chunk of text fun text(context: Context, url: String, title: String) { - Route(context, TextScreenActivity::class.java, TextScreenActivity.URL, arrayOf(url, title)) + Route( + context, + TextScreenActivity::class.java, + TextScreenActivity.URL, + arrayOf(url, title) + ) } // url could be a chunk of text fun textPlaySound(context: Context, url: String, title: String) { - Route(context, TextScreenActivity::class.java, TextScreenActivity.URL, arrayOf(url, title, "sound")) + Route( + context, + TextScreenActivity::class.java, + TextScreenActivity.URL, + arrayOf(url, title, "sound") + ) } fun wfoText(context: Context) { if (Location.isUS) { - Route(context, WfoTextActivity::class.java, WfoTextActivity.URL, arrayOf(Location.wfo, "")) + Route( + context, + WfoTextActivity::class.java, + WfoTextActivity.URL, + arrayOf(Location.wfo, "") + ) } } @@ -386,26 +525,44 @@ class Route() { } fun wpcRainfallByDay(context: Context, dayIndex: String) { - Route(context, RainfallOutlookActivity::class.java, RainfallOutlookActivity.NUMBER, arrayOf(dayIndex)) + Route( + context, + RainfallOutlookActivity::class.java, + RainfallOutlookActivity.NUMBER, + arrayOf(dayIndex) + ) } fun wpcText(context: Context) { - Route(context, NationalTextActivity::class.java, NationalTextActivity.URL, arrayOf("pmdspd", "Short Range Forecast Discussion")) + Route( + context, + NationalTextActivity::class.java, + NationalTextActivity.URL, + arrayOf("pmdspd", "Short Range Forecast Discussion") + ) } fun wpcText(context: Context, product: String) { - Route(context, NationalTextActivity::class.java, NationalTextActivity.URL, arrayOf(product)) + Route( + context, + NationalTextActivity::class.java, + NationalTextActivity.URL, + arrayOf(product) + ) } fun wpcTextWithSound(context: Context, product: String, label: String) { - Route(context, NationalTextActivity::class.java, NationalTextActivity.URL, arrayOf(product, label, "sound")) + Route( + context, + NationalTextActivity::class.java, + NationalTextActivity.URL, + arrayOf(product, label, "sound") + ) } - //elys mod - keeping twitter fun webViewTwitterStates(context: Context) { Route(context, WebViewTwitter::class.java) } - fun webViewTwitterTornado(context: Context) { webView(context, "https://mobile.twitter.com/hashtag/tornado", "#tornado") } diff --git a/app/src/main/java/joshuatee/wx/objects/Site.kt b/app/src/main/java/joshuatee/wx/objects/Site.kt new file mode 100644 index 00000000..af3108f4 --- /dev/null +++ b/app/src/main/java/joshuatee/wx/objects/Site.kt @@ -0,0 +1,42 @@ +/* + + Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 joshua.tee@gmail.com + + This file is part of wX. + + wX is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + wX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with wX. If not, see . + +*/ + +package joshuatee.wx.objects + +class Site( + val codeName: String, + val fullName: String, + val lat: String, + var lon: String, + lonReversed: Boolean +) { + + var distance = 0 + val latLon: LatLon + val codeAndName: String = "${codeName}: $fullName" + + init { + if (lonReversed) { + lon = "-$lon" + } + latLon = LatLon(lat, lon) + } +} diff --git a/app/src/main/java/joshuatee/wx/objects/Sites.kt b/app/src/main/java/joshuatee/wx/objects/Sites.kt new file mode 100644 index 00000000..77a3fbf9 --- /dev/null +++ b/app/src/main/java/joshuatee/wx/objects/Sites.kt @@ -0,0 +1,90 @@ +/* + + Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 joshua.tee@gmail.com + + This file is part of wX. + + wX is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + wX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with wX. If not, see . + +*/ + +package joshuatee.wx.objects + +class Sites( + private val nameDict: Map, + private val latDict: Map, + private val lonDict: Map, + lonReversed: Boolean = false +) { + + val sites = mutableListOf() + val byCode = mutableMapOf() + val codeList = mutableListOf() + val nameList = mutableListOf() + + init { + checkValidityMaps() + + nameDict.forEach { (key, value) -> + sites.add(Site(key, value, latDict[key]!!, lonDict[key]!!, lonReversed)) + byCode[key] = sites.last() + } + + sites.sortBy { it.fullName } + + sites.forEach { site -> + codeList.add(site.codeName) + nameList.add("${site.codeName}: ${site.fullName}") + } + } + + private fun checkValidityMaps() { + val k1 = nameDict.keys + val k2 = latDict.keys + val k3 = lonDict.keys + if (k1 != k2) { + println("mismatch between names and lat " + (k2 - k1).toString() + " " + (k1 - k2).toString()) + } + if (k1 != k3) { + println("mismatch between names and lon" + (k3 - k1).toString() + " " + (k1 - k3).toString()) + } + } + + fun getNearest(latLon: LatLon): String { + for (site in sites) { + site.distance = LatLon.distance(latLon, site.latLon).toInt() + } + sites.sortBy { it.distance } + return sites[0].codeName + } + + // FIXME TODO +// fun getNearestList(latLon: LatLon, count: Int = 5): List { +// for (site in sites) { +// site.distance = LatLon.distance(latLon, site.latLon).toInt() +// } +//// self.sites.sort(key=lambda x: x.distance, reverse=False) +// sites.sortBy { it.distance } +// return [site.codeName for site in self.sites[0:count]] +// } + + fun getNearestInMiles(latLon: LatLon): Int { + for (site in sites) { + site.distance = LatLon.distance(latLon, site.latLon).toInt() + } + sites.sortBy { it.distance } + return sites[0].distance + } +} + diff --git a/app/src/main/java/joshuatee/wx/radar/Metar.kt b/app/src/main/java/joshuatee/wx/radar/Metar.kt index b9e65580..34144842 100644 --- a/app/src/main/java/joshuatee/wx/radar/Metar.kt +++ b/app/src/main/java/joshuatee/wx/radar/Metar.kt @@ -152,18 +152,18 @@ internal object Metar { validWind = true windDir = windBlob.substring(0, 3) windInKt = windBlob.substring(3, 5) - val windDirD = To.double(windDir) + val windDirInt = To.int(windDir) windBlob = - windDir + " (" + UtilityMath.convertWindDir(windDirD) + ") " + windInKt + " kt" + windDir + " (" + UtilityMath.bearingToDirection(windDirInt) + ") " + windInKt + " kt" } else if (windBlob.contains("KT") && windBlob.length == 10) { validWind = true validWindGust = true windDir = windBlob.substring(0, 3) windInKt = windBlob.substring(3, 5) windGustInKt = windBlob.substring(6, 8) - val windDirD = To.double(windDir) + val windDirInt = To.int(windDir) windBlob = - windDir + " (" + UtilityMath.convertWindDir(windDirD) + ") " + windInKt + " G " + windGustInKt + " kt" + windDir + " (" + UtilityMath.bearingToDirection(windDirInt) + ") " + windInKt + " G " + windGustInKt + " kt" } if (tdArr.size > 1) { var temperature = tdArr[0] @@ -314,3 +314,59 @@ internal object Metar { return goodObsList } } + +/* + +https://aviationweather.gov/cgi-bin/data/metar.php?ids=K0F2,K13K,K1F0,K1K1,K3AU,K4O4,KAAO,KADH,KADM,KADS,KAFW,KASG,KAVK,KAXS,KBEC,KBKN,KBVO,KCDS,KCFV,KCHK,KCLK,KCNU,KCQB,KCSM,KCUH,KCWC,KDAL,KDEQ,KDFW,KDTO,KDUA,KDUC,KELK,KEND,KEQA,KEWK,KF00,KF05,KF46,KFDR,KFSI,KFSM,KFTW,KFWS,KFYV,KGAG,KGCM,KGKY,KGLE,KGMJ,KGOK,KGPM,KGVT,KGYI,KGZL,KH71,KHBR,KHHF,KHQZ,KHSD,KHUT,KIAB,KICT,KIDP,KJLN,KJSV,KJWG,KLAW,KLNC,KLTS,KLUD,KMEZ,KMIO,KMKO,KMLC,KMWL,KNFW,KOJA,KOKC,KOKM,KOUN,KOWP,KP28,KPNC,KPPF,KPRX,KPTT,KPVJ,KPWA,KRBD,KRCE,KRKR,KROG,KRPH,KRQO,KRVS,KSLG,KSLR,KSNL,KSPS,KSRE,KSWO,KTIK,KTKI,KTQH,KTRL,KTUL,KVBT,KWDG,KWLD,KWWR,KXBP,KXNA + +sample: + +K0F2 021015Z AUTO 13007KT 5SM BR OVC005 19/18 A3007 RMK AO2 T01850178 +K13K 021015Z AUTO 07007KT 10SM BKN015 OVC026 10/09 A3016 RMK AO2 LTG DSNT W T01020086 +K1F0 021015Z AUTO 13007KT 5SM BR OVC005 18/17 A3009 RMK AO2 T01820172 +K3AU 021015Z AUTO 09007KT 10SM OVC013 13/08 A3010 RMK AO2 +K4O4 021015Z AUTO 08006KT 6SM BR OVC005 17/17 A3013 RMK AO2 +KAAO 021017Z AUTO 04005KT 10SM VCTS OVC013 13/09 A3010 RMK AO2 LTG DSNT ALQDS T01330094 +KADH 021015Z AUTO 13009KT 1SM BR OVC003 17/17 A3011 RMK AO2 +KADS 021015Z AUTO 12008KT 9SM BKN010 OVC022 20/19 A3007 RMK AO2 +KAFW 021016Z 12007KT 7SM BKN010 BKN014 OVC032 20/18 A3006 RMK AO2 CIG 007V013 T02000183 +KAVK 021015Z AUTO 15008KT 10SM -RA BKN012 OVC024 16/15 A3002 RMK AO2 LTG DSNT W-NE +KAXS 021015Z AUTO 14016KT 3SM -RA BR OVC003 18/18 A3004 RMK AO2 +KBEC 021015Z AUTO 10008KT 10SM VCTS OVC013 14/10 A3009 RMK AO2 LTG DSNT SW THRU N T01350095 +KBKN 021015Z AUTO 14011KT 10SM OVC008 15/15 A3009 RMK AO2 +KBVO 020953Z AUTO 19003KT 10SM BKN030 12/11 A3014 RMK AO2 SLP200 T01220106 +KCDS 020953Z AUTO 15011KT 4SM -RA BR OVC003 17/17 A3003 RMK AO2 RAB52 SLP152 P0000 T01720172 +KCFV 020952Z AUTO 13004KT 10SM OVC026 13/11 A3014 RMK AO2 SLP202 T01330106 +KCHK 021015Z AUTO 13007KT 7SM OVC007 18/17 A3006 RMK AO2 T01760167 +KCLK 021015Z AUTO 16009KT 3SM BR OVC006 17/16 A3006 RMK AO2 LTG DSNT N AND SW +KCNU 021017Z AUTO 12008KT 10SM BKN022 OVC080 12/08 A3016 RMK AO2 T01220083 +KCQB 021015Z AUTO 11005KT 10SM OVC008 16/14 A3012 RMK AO2 T01570141 +KCSM 021001Z AUTO 16017KT 2 1/2SM -RA BR OVC004 17/17 A3005 RMK AO2 P0000 T01720167 +KCUH 021015Z AUTO 15005KT 10SM OVC012 16/13 A3010 RMK AO2 LTG DSNT NW T01600133 +KCWC 021015Z AUTO 17011G15KT 120V180 10SM BKN012 OVC017 20/18 A3007 RMK AO2 LTG DSNT W T01950176 +KDAL 021024Z 13006KT 6SM -RA BR OVC009 20/19 A3006 RMK AO2 RAB15 P0000 T02000189 +KDEQ 021006Z AUTO 08004KT 10SM OVC009 18/16 A3013 RMK AO2 T01780161 +KDFW 020953Z 11007KT 7SM OVC010 20/18 A3006 RMK AO2 SLP171 T02000183 $ +KDTO 021000Z AUTO 14006KT 10SM BKN010 OVC014 20/18 A3007 RMK AO2 T02000183 +KDUA 021015Z AUTO 11008KT 3SM BR OVC003 18/18 A3013 RMK AO2 +KDUC 021015Z AUTO 13010KT 7SM BR OVC006 18/17 A3009 RMK AO2 +KELK 021015Z AUTO 16009G16KT 5SM BR OVC003 17/17 A3004 RMK AO2 LTG DSNT N AND W RAE1013 P0001 T01690169 $ +KEND 021010Z AUTO 14006KT 10SM FEW009 BKN025 OVC033 16/14 A3003 RMK AO2 CIG 023 RWY35C SLP163 $ +KEQA 021015Z AUTO 08007KT 10SM OVC013 13/10 A3012 RMK AO2 +KEWK 021015Z AUTO 16012KT 10SM -TSRA FEW024 BKN032 OVC075 13/13 A3011 RMK AO2 LTG DSNT ALQDS PNO $ +KF00 021015Z AUTO 10005KT 5SM BR OVC004 18/18 A3011 RMK AO2 T01790178 +KF05 021020Z AUTO 13010KT 5SM OVC007 19/19 A3004 RMK AO2 LTG DSNT W T01920186 +KF46 021015Z AUTO 11005KT 7SM OVC007 20/20 A3008 RMK AO2 T01950195 +KFDR 020953Z AUTO 14011KT 8SM OVC010 19/17 A3003 RMK AO2 SLP154 T01890167 +KFSM 020953Z 08008KT 10SM OVC019 17/13 A3016 RMK AO2 SLP210 T01670128 +KFTW 020953Z 11006KT 8SM OVC009 20/18 A3006 RMK AO2 CIG 007V012 SLP171 T02000183 +KFWS 021015Z AUTO 11004KT 10SM OVC007 20/19 A3008 RMK AO2 T02010190 +KFYV 020953Z AUTO 00000KT 10SM OVC014 14/12 A3018 RMK AO2 SLP211 T01440117 +KGAG 021009Z AUTO 17016G22KT 9SM VCTS -RA OVC009 17/16 A3002 RMK AO2 LTG DSNT SW-N RAB00 CIG 004V011 P0000 T01720161 +KGCM 021015Z AUTO 11006KT 10SM OVC023 16/15 A3013 RMK AO2 +KGKY 020953Z AUTO 11007KT 10SM BKN011 OVC029 21/18 A3007 RMK AO2 CIG 009V014 SLP174 T02110183 +KGMJ 021015Z AUTO 09004KT 10SM OVC023 12/11 A3016 RMK AO2 TSNO +KGOK 020953Z AUTO 17011G17KT 10SM OVC007 17/16 A3009 RMK AO2 SLP183 T01670161 +KGPM 021015Z AUTO 09006KT 10SM SCT010 OVC024 20/20 A3008 RMK AO2 T02020201 + + */ diff --git a/app/src/main/java/joshuatee/wx/radar/NexradLongPressMenu.kt b/app/src/main/java/joshuatee/wx/radar/NexradLongPressMenu.kt index dcea5041..04c74dd7 100644 --- a/app/src/main/java/joshuatee/wx/radar/NexradLongPressMenu.kt +++ b/app/src/main/java/joshuatee/wx/radar/NexradLongPressMenu.kt @@ -36,6 +36,8 @@ import joshuatee.wx.objects.Route import joshuatee.wx.settings.RadarPreferences import joshuatee.wx.settings.UtilityLocation import joshuatee.wx.ui.ObjectDialogue +import joshuatee.wx.util.SoundingSites +import joshuatee.wx.util.To import joshuatee.wx.util.Utility import joshuatee.wx.util.UtilityMath import kotlin.math.roundToInt @@ -113,13 +115,19 @@ class NexradLongPressMenu( ) { longPressList.clear() val dist = LatLon.distance(LatLon(locX, locY), latLon, DistanceUnit.MILE) + val direction = LatLon.calculateDirection(latLon, LatLon(locX, locY)) val radarSiteLatLon = UtilityLocation.getSiteLocation(radarSite, OfficeTypeEnum.RADAR) val distRid = LatLon.distance(radarSiteLatLon, latLon, DistanceUnit.MILE) val distRidKm = LatLon.distance(radarSiteLatLon, latLon, DistanceUnit.KM) + val directionFromRadarSite = LatLon.calculateDirection(latLon, radarSiteLatLon) val latLonTitle = latLon.prettyPrint() longPressDialogue.setTitle(latLonTitle) - longPressList.add("${dist.toString().take(6)} miles from location") - longPressList.add("${distRid.toString().take(6)} miles from $radarSite") + longPressList.add("${dist.toString().take(6)} mi $direction to location") + longPressList.add( + "${ + distRid.toString().take(6) + } mi $directionFromRadarSite to $radarSite" + ) val heightAgl = UtilityMath.getRadarBeamHeight(wxglNexradLevel3.degree.toDouble(), distRidKm) val heightMsl = wxglNexradLevel3.radarHeight + heightAgl @@ -131,7 +139,12 @@ class NexradLongPressMenu( longPressList.add("WPC Fronts: ${getWpcFrontTimeStamp(context)}") } longPressList += closestRadarSites.map { - "${it.name} ${UtilityLocation.getRadarSiteName(it.name)} ${it.distance.roundToInt()} mi" + "${it.name} ${UtilityLocation.getRadarSiteName(it.name)} ${it.distance.roundToInt()} mi ${ + LatLon.calculateDirection( + latLon, + it.location + ) + }" } //elys mod if ((RadarPreferences.warnings || PolygonWarning.areAnyEnabled()) /*&& PolygonWarning.isCountNonZero()*/) { @@ -149,15 +162,24 @@ class NexradLongPressMenu( } // end Thanks to Ely val obsSite = Metar.findClosestObservation(context, latLon) + val obsDirection = LatLon.calculateDirection(latLon, obsSite.location) with(longPressList) { //elys mod add("Radar Mosaic") add("GOES Satellite") - add("Observation: ${obsSite.name} ${obsSite.distance.roundToInt()} mi") + add("Observation: ${obsSite.name} ${obsSite.distance.roundToInt()} mi $obsDirection") add("Forecast: $latLonTitle") add("Meteogram: ${obsSite.name}") add("Radar status message: ${closestRadarSites.first().name}") } + val nearestSoundingCode = SoundingSites.sites.getNearest(latLon) + val nearestSoundingLatLon = SoundingSites.sites.byCode[nearestSoundingCode]!!.latLon + val directionToSounding = LatLon.calculateDirection(latLon, nearestSoundingLatLon) + longPressList.add( + "Sounding: $nearestSoundingCode " + To.string( + SoundingSites.sites.getNearestInMiles(latLon) + ) + " mi $directionToSounding" + ) //elys mod if (RadarPreferences.spotters || RadarPreferences.spottersLabel) longPressList.add("Spotter Info") longPressList.add("Userpoint info: " + latLonTitle) @@ -183,6 +205,8 @@ class NexradLongPressMenu( radarSite: String, function: (String) -> Unit ) { + val nearestSoundingCode = SoundingSites.sites.getNearest(latLon) + when { s.contains("miles from") -> {} s.contains("Show Warning") -> NexradRenderUI.showNearestWarning(activity, latLon) @@ -216,6 +240,7 @@ class NexradLongPressMenu( radarSite ) + s.startsWith("Sounding") -> Route.sounding(activity, nearestSoundingCode) s.startsWith("Beam") -> {} //elys mod //need context.... s.contains("Spotter Info") -> NexradRenderUI.showSpotterInfo(activity, latLon) diff --git a/app/src/main/java/joshuatee/wx/settings/FavAddActivity.kt b/app/src/main/java/joshuatee/wx/settings/FavAddActivity.kt index 98ea28b6..30654cc5 100644 --- a/app/src/main/java/joshuatee/wx/settings/FavAddActivity.kt +++ b/app/src/main/java/joshuatee/wx/settings/FavAddActivity.kt @@ -30,6 +30,7 @@ import joshuatee.wx.objects.FavoriteType import joshuatee.wx.ui.BaseActivity import joshuatee.wx.spc.UtilitySpcMeso import joshuatee.wx.ui.ObjectRecyclerView +import joshuatee.wx.util.SoundingSites import joshuatee.wx.util.Utility import joshuatee.wx.util.UtilityFavorites import joshuatee.wx.wpc.UtilityWpcText @@ -64,7 +65,8 @@ class FavAddActivity : BaseActivity() { private fun setupVars() { when (type) { FavoriteType.SND -> { - data = GlobalArrays.soundingSites.map { "$it " + UtilityLocation.getSoundingSiteName(it) } +// data = GlobalArrays.soundingSites.map { "$it " + UtilityLocation.getSoundingSiteName(it) } + data = SoundingSites.sites.nameList verboseTitle = "sounding site" } @@ -98,10 +100,14 @@ class FavAddActivity : BaseActivity() { private fun itemClicked(position: Int) { val item = data[position] - var favoriteString = Utility.readPref(this, UtilityFavorites.getPrefToken(type), UtilityFavorites.INITIAL_VALUE) + var favoriteString = Utility.readPref( + this, + UtilityFavorites.getPrefToken(type), + UtilityFavorites.INITIAL_VALUE + ) val sourceString = when (type) { FavoriteType.SPCMESO -> dataTokens[position] - FavoriteType.SND -> GlobalArrays.soundingSites[position] + FavoriteType.SND -> SoundingSites.sites.nameList[position] else -> data[position] } val tokens = if (sourceString.contains(":")) { diff --git a/app/src/main/java/joshuatee/wx/settings/FavRemoveActivity.kt b/app/src/main/java/joshuatee/wx/settings/FavRemoveActivity.kt index 3b75c891..51fd5275 100644 --- a/app/src/main/java/joshuatee/wx/settings/FavRemoveActivity.kt +++ b/app/src/main/java/joshuatee/wx/settings/FavRemoveActivity.kt @@ -30,6 +30,7 @@ import joshuatee.wx.ui.BaseActivity import joshuatee.wx.util.UtilityFavorites import joshuatee.wx.spc.UtilitySpcMeso import joshuatee.wx.ui.ObjectRecyclerView +import joshuatee.wx.util.SoundingSites import joshuatee.wx.util.Utility import joshuatee.wx.wpc.UtilityWpcText @@ -86,12 +87,17 @@ class FavRemoveActivity : BaseActivity() { FavoriteType.SREF -> verboseTitle = "parameters" FavoriteType.SPCMESO -> verboseTitle = "parameters" } - favoriteString = Utility.readPref(this, UtilityFavorites.getPrefToken(type), UtilityFavorites.INITIAL_VALUE) + favoriteString = Utility.readPref( + this, + UtilityFavorites.getPrefToken(type), + UtilityFavorites.INITIAL_VALUE + ) } private fun updateList() { // strip leading " " due to add/modify labels and trailing empty - favorites = favoriteString.split(":").dropWhile { it == " " }.dropLastWhile { it.isEmpty() }.toMutableList() + favorites = favoriteString.split(":").dropWhile { it == " " }.dropLastWhile { it.isEmpty() } + .toMutableList() labels.clear() favorites.forEach { when (type) { @@ -134,7 +140,8 @@ class FavRemoveActivity : BaseActivity() { private fun initData() { favoriteString = Utility.readPref(this, UtilityFavorites.getPrefToken(type), "") - favorites = favoriteString.split(":").dropWhile { it == " " }.dropLastWhile { it.isEmpty() }.toMutableList() + favorites = favoriteString.split(":").dropWhile { it == " " }.dropLastWhile { it.isEmpty() } + .toMutableList() } private fun writeData() { @@ -148,7 +155,8 @@ class FavRemoveActivity : BaseActivity() { } private fun getFullString(shortCode: String) = when (type) { - FavoriteType.SND -> UtilityLocation.getSoundingSiteName(shortCode) +// FavoriteType.SND -> UtilityLocation.getSoundingSiteName(shortCode) + FavoriteType.SND -> SoundingSites.sites.byCode[shortCode]!!.fullName FavoriteType.WFO -> shortCode + ": " + UtilityLocation.getWfoSiteName(shortCode) FavoriteType.RID -> shortCode + ": " + UtilityLocation.getRadarSiteName(shortCode) FavoriteType.NWS_TEXT -> shortCode + ": " + UtilityWpcText.getLabel(shortCode) @@ -170,7 +178,8 @@ class FavRemoveActivity : BaseActivity() { } private fun itemClicked(position: Int) { - val bottomSheetFragment = BottomSheetFragment(this, position, objectRecyclerView.getItem(position), false) + val bottomSheetFragment = + BottomSheetFragment(this, position, objectRecyclerView.getItem(position), false) bottomSheetFragment.functions = listOf(::deleteItem, ::moveUp, ::moveDown) bottomSheetFragment.labelList = listOf("Delete Item", "Move Up", "Move Down") bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.tag) diff --git a/app/src/main/java/joshuatee/wx/settings/UtilityHomeScreen.kt b/app/src/main/java/joshuatee/wx/settings/UtilityHomeScreen.kt index 4f0e792e..c3a0b208 100644 --- a/app/src/main/java/joshuatee/wx/settings/UtilityHomeScreen.kt +++ b/app/src/main/java/joshuatee/wx/settings/UtilityHomeScreen.kt @@ -28,7 +28,6 @@ import joshuatee.wx.misc.RtmaActivity import joshuatee.wx.misc.USAlertsActivity import joshuatee.wx.models.ModelsGenericActivity import joshuatee.wx.nhc.NhcActivity -import joshuatee.wx.objects.LatLon import joshuatee.wx.objects.Route import joshuatee.wx.radar.RadarMosaicNwsActivity import joshuatee.wx.radar.WXGLRadarActivityMultiPane @@ -38,6 +37,7 @@ import joshuatee.wx.spc.SpcMesoActivity import joshuatee.wx.spc.SpcSoundingsActivity import joshuatee.wx.spc.SpcThunderStormOutlookActivity import joshuatee.wx.ui.CardHSImage +import joshuatee.wx.util.SoundingSites import joshuatee.wx.vis.GoesActivity import joshuatee.wx.wpc.NationalImagesActivity import joshuatee.wx.wpc.NationalTextActivity @@ -50,24 +50,24 @@ internal object UtilityHomeScreen { val classId = mutableMapOf() val localChoicesText = listOf( - "CC: Current Conditions", - "CC2: Current Conditions with image", - "HAZ: Hazards", - "7DAY2: 7 Day Forecast with images", - "AFDLOC: Area Forecast Discussion", - "HWOLOC: Hazardous Weather Outlook", - "VFDLOC: Aviation only Area Forecast Discussion", - "HOURLY: Hourly Forecast", - "CTOF: Celsius to Fahrenheit table" + "CC: Current Conditions", + "CC2: Current Conditions with image", + "HAZ: Hazards", + "7DAY2: 7 Day Forecast with images", + "AFDLOC: Area Forecast Discussion", + "HWOLOC: Hazardous Weather Outlook", + "VFDLOC: Aviation only Area Forecast Discussion", + "HOURLY: Hourly Forecast", + "CTOF: Celsius to Fahrenheit table" ) val localChoicesImg = listOf( - "RADAR: Local NEXRAD Radar", - "WEATHERSTORY: Local NWS Weather Story", - "WFOWARNINGS: Local NWS Office Warnings", - "RTMA_DEW: Real-Time Mesoscale Analysis Dew Point", - "RTMA_TEMP: Real-Time Mesoscale Analysis Temperature", - "RTMA_WIND: Real-Time Mesoscale Analysis Wind" + "RADAR: Local NEXRAD Radar", + "WEATHERSTORY: Local NWS Weather Story", + "WFOWARNINGS: Local NWS Office Warnings", + "RTMA_DEW: Real-Time Mesoscale Analysis Dew Point", + "RTMA_TEMP: Real-Time Mesoscale Analysis Temperature", + "RTMA_WIND: Real-Time Mesoscale Analysis Wind" ) fun launch(context: Context, homeScreenImageCards: List) { @@ -79,8 +79,9 @@ internal object UtilityHomeScreen { if (argsOrig != null) { val args = argsOrig.copyOf(argsOrig.size) args.indices.forEach { z -> - if (args[z] == "WFO_FOR_SND") - args[z] = UtilityLocation.getNearestSoundingSite(LatLon(Location.x, Location.y)) + if (args[z] == "WFO_FOR_SND") // Check that this is not needed TODO FIXME + args[z] = SoundingSites.sites.getNearest(Location.latLon) +// args[z] = UtilityLocation.getNearestSoundingSite(LatLon(Location.x, Location.y)) if (args[z] == "WFO_FOR_GOES") args[z] = Location.wfo.lowercase(Locale.US) if (args[z] == "STATE_LOWER") @@ -191,53 +192,56 @@ internal object UtilityHomeScreen { classId["RAD_2KM"] = RadarMosaicNwsActivity.URL listOf( - "FMAP", - "FMAPD2", - "FMAPD3", - "FMAP12", - "FMAP24", - "FMAP36", - "FMAP48", - "FMAP72", - "FMAP96", - "FMAP120", - "FMAP144", - "FMAP168", - "FMAP3D", - "FMAP4D", - "FMAP5D", - "FMAP6D", - "WPC_ANALYSIS", - "QPF1", - "QPF2", - "QPF3", - "QPF1-2", - "QPF1-3", - "QPF4-5", - "QPF6-7", - "QPF1-5", - "QPF1-7" + "FMAP", + "FMAPD2", + "FMAPD3", + "FMAP12", + "FMAP24", + "FMAP36", + "FMAP48", + "FMAP72", + "FMAP96", + "FMAP120", + "FMAP144", + "FMAP168", + "FMAP3D", + "FMAP4D", + "FMAP5D", + "FMAP6D", + "WPC_ANALYSIS", + "QPF1", + "QPF2", + "QPF3", + "QPF1-2", + "QPF1-3", + "QPF4-5", + "QPF6-7", + "QPF1-5", + "QPF1-7" ).forEach { classes[it] = NationalImagesActivity::class.java classArgs[it] = arrayOf("HS", it) classId[it] = NationalImagesActivity.URL } listOf( - "USWARN", - "AKWARN", - "HIWARN" + "USWARN", + "AKWARN", + "HIWARN" ).forEach { classes[it] = USAlertsActivity::class.java - classArgs[it] = arrayOf(".*?Tornado Warning.*?|.*?Severe Thunderstorm Warning.*?|.*?Flash Flood Warning.*?", "us") + classArgs[it] = arrayOf( + ".*?Tornado Warning.*?|.*?Severe Thunderstorm Warning.*?|.*?Flash Flood Warning.*?", + "us" + ) classId[it] = USAlertsActivity.URL } listOf( - "NHC2ATL", - "NHC5ATL", - "NHC2EPAC", - "NHC5EPAC", - "NHC2CPAC", - "NHC5CPAC" + "NHC2ATL", + "NHC5ATL", + "NHC2EPAC", + "NHC5EPAC", + "NHC2CPAC", + "NHC5CPAC" ).forEach { classes[it] = NhcActivity::class.java classId[it] = "" diff --git a/app/src/main/java/joshuatee/wx/settings/UtilityLocation.kt b/app/src/main/java/joshuatee/wx/settings/UtilityLocation.kt index 9d66b02a..c7b5f20c 100644 --- a/app/src/main/java/joshuatee/wx/settings/UtilityLocation.kt +++ b/app/src/main/java/joshuatee/wx/settings/UtilityLocation.kt @@ -72,8 +72,15 @@ object UtilityLocation { val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager val providers = locationManager.getProviders(true) var location: Location? = null - if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED - || ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + if (ContextCompat.checkSelfPermission( + context, + android.Manifest.permission.ACCESS_FINE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + || ContextCompat.checkSelfPermission( + context, + android.Manifest.permission.ACCESS_COARSE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + ) { for (i in providers.indices.reversed()) { location = locationManager.getLastKnownLocation(providers[i]) if (location != null) @@ -100,7 +107,17 @@ object UtilityLocation { val sites = mutableListOf() officeArray.forEach { val labelArr = it.split(":") - sites.add(RID(labelArr[0], getSiteLocation(labelArr[0], prefToken), LatLon.distance(location, getSiteLocation(labelArr[0], prefToken), DistanceUnit.KM))) + sites.add( + RID( + labelArr[0], + getSiteLocation(labelArr[0], prefToken), + LatLon.distance( + location, + getSiteLocation(labelArr[0], prefToken), + DistanceUnit.KM + ) + ) + ) } sites.sortBy { it.distance } return sites[0].name @@ -110,28 +127,48 @@ object UtilityLocation { val radarSites = mutableListOf() GlobalArrays.radars.forEach { val labels = it.split(":") - radarSites.add(RID(labels[0], getSiteLocation(labels[0], OfficeTypeEnum.RADAR), LatLon.distance(location, getSiteLocation(labels[0], OfficeTypeEnum.RADAR), DistanceUnit.MILE))) + radarSites.add( + RID( + labels[0], + getSiteLocation(labels[0], OfficeTypeEnum.RADAR), + LatLon.distance( + location, + getSiteLocation(labels[0], OfficeTypeEnum.RADAR), + DistanceUnit.MILE + ) + ) + ) } if (includeTdwr) { GlobalArrays.tdwrRadars.forEach { val labels = it.split(":") - radarSites.add(RID(labels[0], getSiteLocation(labels[0], OfficeTypeEnum.RADAR), LatLon.distance(location, getSiteLocation(labels[0], OfficeTypeEnum.RADAR), DistanceUnit.MILE))) + radarSites.add( + RID( + labels[0], + getSiteLocation(labels[0], OfficeTypeEnum.RADAR), + LatLon.distance( + location, + getSiteLocation(labels[0], OfficeTypeEnum.RADAR), + DistanceUnit.MILE + ) + ) + ) } } radarSites.sortBy { it.distance } return radarSites.subList(0, count) } - fun getNearestSoundingSite(location: LatLon): String { - val sites = GlobalArrays.soundingSites.map { - RID(it, getSiteLocation(it, OfficeTypeEnum.SOUNDING), LatLon.distance(location, getSiteLocation(it, OfficeTypeEnum.SOUNDING), DistanceUnit.KM)) - }.toMutableList() - sites.forEach { - it.distance = LatLon.distance(location, it.location, DistanceUnit.KM) - } - sites.sortBy { it.distance } - return sites[0].name - } +// fun getNearestSoundingSite(location: LatLon): String { +// val sites = GlobalArrays.soundingSites.map { +// RID(it, getSiteLocation(it, OfficeTypeEnum.SOUNDING), LatLon.distance(location, getSiteLocation(it, OfficeTypeEnum.SOUNDING), DistanceUnit.KM)) +// }.toMutableList() +// sites.forEach { +// it.distance = LatLon.distance(location, it.location, DistanceUnit.KM) +// } +// sites.sortBy { it.distance } +// return sites[0].name +// } fun getSiteLocation(site: String, officeType: OfficeTypeEnum): LatLon { // SND, NWS, or RID @@ -154,8 +191,11 @@ object UtilityLocation { } OfficeTypeEnum.SOUNDING -> { - x = getSoundingSiteX(site.uppercase(Locale.US)) - y = addChar + getSoundingSiteY(site.uppercase(Locale.US)) +// x = getSoundingSiteX(site.uppercase(Locale.US)) +// y = addChar + getSoundingSiteY(site.uppercase(Locale.US)) + val latLon = SoundingSites.sites.byCode[site.uppercase(Locale.US)]!! + x = latLon.lat + y = latLon.lon } } return LatLon(x, y) @@ -173,17 +213,17 @@ object UtilityLocation { fun getWfoSiteName(wfo: String): String = WfoSites.name[wfo] ?: "" - private fun getSoundingSiteX(site: String): String = SoundingSites.lat[site] ?: "" - - private fun getSoundingSiteY(site: String): String = SoundingSites.lon[site] ?: "" - - fun getSoundingSiteName(wfo: String): String { - var site = WfoSites.name[wfo] ?: "" - if (site == "") { - site = SoundingSites.name[wfo] ?: "" - } - return site - } +// private fun getSoundingSiteX(site: String): String = SoundingSites.lat[site] ?: "" +// +// private fun getSoundingSiteY(site: String): String = SoundingSites.lon[site] ?: "" +// +// fun getSoundingSiteName(wfo: String): String { +// var site = WfoSites.name[wfo] ?: "" +// if (site == "") { +// site = SoundingSites.name[wfo] ?: "" +// } +// return site +// } fun getNearest(latLon: LatLon, sectorToLatLon: Map): String { val sites = mutableListOf() @@ -194,11 +234,12 @@ object UtilityLocation { return sites[0].name } - fun hasAlerts(locNum: Int): Boolean = joshuatee.wx.settings.Location.locations[locNum].notification - || joshuatee.wx.settings.Location.locations[locNum].notificationMcd - || joshuatee.wx.settings.Location.locations[locNum].ccNotification - || joshuatee.wx.settings.Location.locations[locNum].sevenDayNotification - || joshuatee.wx.settings.Location.locations[locNum].notificationSpcFw - || joshuatee.wx.settings.Location.locations[locNum].notificationSwo - || joshuatee.wx.settings.Location.locations[locNum].notificationWpcMpd + fun hasAlerts(locNum: Int): Boolean = + joshuatee.wx.settings.Location.locations[locNum].notification + || joshuatee.wx.settings.Location.locations[locNum].notificationMcd + || joshuatee.wx.settings.Location.locations[locNum].ccNotification + || joshuatee.wx.settings.Location.locations[locNum].sevenDayNotification + || joshuatee.wx.settings.Location.locations[locNum].notificationSpcFw + || joshuatee.wx.settings.Location.locations[locNum].notificationSwo + || joshuatee.wx.settings.Location.locations[locNum].notificationWpcMpd } diff --git a/app/src/main/java/joshuatee/wx/spc/SPCSoundingsActivity.kt b/app/src/main/java/joshuatee/wx/spc/SPCSoundingsActivity.kt index 7159b87f..8d51ce27 100644 --- a/app/src/main/java/joshuatee/wx/spc/SPCSoundingsActivity.kt +++ b/app/src/main/java/joshuatee/wx/spc/SPCSoundingsActivity.kt @@ -38,12 +38,12 @@ import joshuatee.wx.objects.FavoriteType import joshuatee.wx.objects.FutureBytes2 import joshuatee.wx.objects.Route import joshuatee.wx.settings.Location -import joshuatee.wx.settings.UtilityLocation import joshuatee.wx.ui.BaseActivity import joshuatee.wx.ui.ObjectDialogue import joshuatee.wx.ui.ObjectImageMap import joshuatee.wx.ui.TouchImage import joshuatee.wx.ui.UtilityToolbar +import joshuatee.wx.util.SoundingSites import joshuatee.wx.util.Utility import joshuatee.wx.util.UtilityFavorites import joshuatee.wx.util.UtilityImg @@ -64,6 +64,7 @@ class SpcSoundingsActivity : BaseActivity(), OnMenuItemClickListener { private lateinit var star: MenuItem private var locations = listOf() private var upperAir = "" + private lateinit var arguments: Array override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.spcsoundings_top, menu) @@ -77,7 +78,13 @@ class SpcSoundingsActivity : BaseActivity(), OnMenuItemClickListener { @SuppressLint("MissingSuperCall") override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState, R.layout.activity_spcsoundings, R.menu.spcsoundings, true) + super.onCreate( + savedInstanceState, + R.layout.activity_spcsoundings, + R.menu.spcsoundings, + true + ) + arguments = intent.getStringArrayExtra(URL)!! setupUI() getContent() } @@ -86,8 +93,20 @@ class SpcSoundingsActivity : BaseActivity(), OnMenuItemClickListener { objectToolbarBottom.connect(this) star = objectToolbarBottom.getFavIcon() touchImage = TouchImage(this, toolbar, toolbarBottom, R.id.iv) - office = UtilityLocation.getNearestSoundingSite(Location.latLon) - imageMap = ObjectImageMap(this, R.id.map, objectToolbar, objectToolbarBottom, listOf(touchImage.get())) +// office = UtilityLocation.getNearestSoundingSite(Location.latLon) + + office = if (arguments.size > 1 && arguments[1] != "") { + arguments[1] + } else { + SoundingSites.sites.getNearest(Location.latLon) + } + imageMap = ObjectImageMap( + this, + R.id.map, + objectToolbar, + objectToolbarBottom, + listOf(touchImage.get()) + ) imageMap.connect(::mapSwitch, UtilityImageMap::mapToSnd) } @@ -140,7 +159,12 @@ class SpcSoundingsActivity : BaseActivity(), OnMenuItemClickListener { R.id.action_sfc -> setPlotAndGet("sfc") R.id.action_map -> imageMap.toggleMap() R.id.action_fav -> toggleFavorite() - R.id.action_spc_help -> Route.webView(this, "${GlobalVariables.NWS_SPC_WEBSITE_PREFIX}/exper/mesoanalysis/help/begin.html", office) + R.id.action_spc_help -> Route.webView( + this, + "${GlobalVariables.NWS_SPC_WEBSITE_PREFIX}/exper/mesoanalysis/help/begin.html", + office + ) + else -> return super.onOptionsItemSelected(item) } return true diff --git a/app/src/main/java/joshuatee/wx/ui/CardVerticalText2.kt b/app/src/main/java/joshuatee/wx/ui/CardVerticalText2.kt index e6cc9298..de8491bd 100644 --- a/app/src/main/java/joshuatee/wx/ui/CardVerticalText2.kt +++ b/app/src/main/java/joshuatee/wx/ui/CardVerticalText2.kt @@ -24,7 +24,6 @@ package joshuatee.wx.ui import android.content.Context import android.view.Gravity import android.view.View -import android.widget.TextView import androidx.appcompat.widget.Toolbar import joshuatee.wx.objects.TextSize diff --git a/app/src/main/java/joshuatee/wx/util/DownloadImage.kt b/app/src/main/java/joshuatee/wx/util/DownloadImage.kt index f88e6298..fcb7b4bf 100644 --- a/app/src/main/java/joshuatee/wx/util/DownloadImage.kt +++ b/app/src/main/java/joshuatee/wx/util/DownloadImage.kt @@ -26,7 +26,6 @@ import android.content.Context import android.graphics.Bitmap import joshuatee.wx.common.GlobalVariables import joshuatee.wx.settings.Location -import joshuatee.wx.settings.UtilityLocation import joshuatee.wx.misc.UtilityRtma import joshuatee.wx.getImage import joshuatee.wx.objects.FavoriteType @@ -44,7 +43,11 @@ object DownloadImage { fun radarMosaic(context: Context): Bitmap = try { val prefTokenSector = "REMEMBER_NWSMOSAIC_SECTOR" - val sector = Utility.readPref(context, prefTokenSector, UtilityNwsRadarMosaic.getNearest(Location.latLon)) + val sector = Utility.readPref( + context, + prefTokenSector, + UtilityNwsRadarMosaic.getNearest(Location.latLon) + ) UtilityNwsRadarMosaic.get(sector).getImage() } catch (e: Exception) { UtilityLog.handleException(e) @@ -59,7 +62,10 @@ object DownloadImage { "GOES16" -> { needsBitmap = false val index = Utility.readPrefInt(context, "GOES16_IMG_FAV_IDX", 0) - bitmap = UtilityGoes.getImage(UtilityGoes.codes[index], Utility.readPref(context, "GOES16_SECTOR", "cgl")).getImage() + bitmap = UtilityGoes.getImage( + UtilityGoes.codes[index], + Utility.readPref(context, "GOES16_SECTOR", "cgl") + ).getImage() } "VIS_1KM", "VIS_MAIN" -> needsBitmap = false @@ -87,11 +93,21 @@ object DownloadImage { "FMAP24" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/basicwx/94fwbg.gif" "FMAP36" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/basicwx/96fwbg.gif" "FMAP48" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/basicwx/98fwbg.gif" - "FMAP72" -> url = GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf072.gif" - "FMAP96" -> url = GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf096.gif" - "FMAP120" -> url = GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf120.gif" - "FMAP144" -> url = GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf144.gif" - "FMAP168" -> url = GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf168.gif" + "FMAP72" -> url = + GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf072.gif" + + "FMAP96" -> url = + GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf096.gif" + + "FMAP120" -> url = + GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf120.gif" + + "FMAP144" -> url = + GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf144.gif" + + "FMAP168" -> url = + GlobalVariables.NWS_WPC_WEBSITE_PREFIX + "/medr/display/wpcwx+frontsf168.gif" + "FMAP3D" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/medr/9jhwbg_conus.gif" "FMAP4D" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/medr/9khwbg_conus.gif" "FMAP5D" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/medr/9lhwbg_conus.gif" @@ -105,7 +121,9 @@ object DownloadImage { "QPF6-7" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/qpf/97ep48iwbg_fill.gif" "QPF1-5" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/qpf/p120i.gif" "QPF1-7" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/qpf/p168i.gif" - "WPC_ANALYSIS" -> url = "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/images/wwd/radnat/NATRAD_24.gif" + "WPC_ANALYSIS" -> url = + "${GlobalVariables.NWS_WPC_WEBSITE_PREFIX}/images/wwd/radnat/NATRAD_24.gif" + "NHC2ATL" -> url = "${GlobalVariables.NWS_NHC_WEBSITE_PREFIX}/xgtwo/two_atl_2d0.png" "NHC5ATL" -> url = "${GlobalVariables.NWS_NHC_WEBSITE_PREFIX}/xgtwo/two_atl_7d0.png" "NHC2EPAC" -> url = "${GlobalVariables.NWS_NHC_WEBSITE_PREFIX}/xgtwo/two_pac_2d0.png" @@ -125,12 +143,14 @@ object DownloadImage { "WEATHERSTORY" -> { needsBitmap = false - bitmap = ("https://www.weather.gov/images/" + Location.wfo.lowercase(Locale.US) + "/wxstory/Tab2FileL.png").getImage() + bitmap = + ("https://www.weather.gov/images/" + Location.wfo.lowercase(Locale.US) + "/wxstory/Tab2FileL.png").getImage() } "WFOWARNINGS" -> { needsBitmap = false - bitmap = ("https://www.weather.gov/wwamap/png/" + Location.wfo.lowercase(Locale.US) + ".png").getImage() + bitmap = + ("https://www.weather.gov/wwamap/png/" + Location.wfo.lowercase(Locale.US) + ".png").getImage() } "SWOD2" -> { @@ -150,16 +170,21 @@ object DownloadImage { "SPCMESO1" -> { var param = "500mb" - val items = UIPreferences.favorites[FavoriteType.SPCMESO]!!.split(":").dropLastWhile { it.isEmpty() } + val items = UIPreferences.favorites[FavoriteType.SPCMESO]!!.split(":") + .dropLastWhile { it.isEmpty() } if (items.size > 3) { param = items[3] } needsBitmap = false bitmap = UtilitySpcMesoInputOutput.getImage( + context, + param, + Utility.readPref( context, - param, - Utility.readPref(context, "SPCMESO" + 1 + "_SECTOR_LAST_USED", UtilitySpcMeso.DEFAULT_SECTOR), - UtilitySpcMesoInputOutput.getLayers(context) + "SPCMESO" + 1 + "_SECTOR_LAST_USED", + UtilitySpcMeso.DEFAULT_SECTOR + ), + UtilitySpcMesoInputOutput.getLayers(context) ) } @@ -171,10 +196,14 @@ object DownloadImage { } needsBitmap = false bitmap = UtilitySpcMesoInputOutput.getImage( + context, + param, + Utility.readPref( context, - param, - Utility.readPref(context, "SPCMESO" + 1 + "_SECTOR_LAST_USED", UtilitySpcMeso.DEFAULT_SECTOR), - UtilitySpcMesoInputOutput.getLayers(context) + "SPCMESO" + 1 + "_SECTOR_LAST_USED", + UtilitySpcMeso.DEFAULT_SECTOR + ), + UtilitySpcMesoInputOutput.getLayers(context) ) } @@ -186,10 +215,14 @@ object DownloadImage { } needsBitmap = false bitmap = UtilitySpcMesoInputOutput.getImage( + context, + param, + Utility.readPref( context, - param, - Utility.readPref(context, "SPCMESO" + 1 + "_SECTOR_LAST_USED", UtilitySpcMeso.DEFAULT_SECTOR), - UtilitySpcMesoInputOutput.getLayers(context) + "SPCMESO" + 1 + "_SECTOR_LAST_USED", + UtilitySpcMeso.DEFAULT_SECTOR + ), + UtilitySpcMesoInputOutput.getLayers(context) ) } @@ -201,10 +234,14 @@ object DownloadImage { } needsBitmap = false bitmap = UtilitySpcMesoInputOutput.getImage( + context, + param, + Utility.readPref( context, - param, - Utility.readPref(context, "SPCMESO" + 1 + "_SECTOR_LAST_USED", UtilitySpcMeso.DEFAULT_SECTOR), - UtilitySpcMesoInputOutput.getLayers(context) + "SPCMESO" + 1 + "_SECTOR_LAST_USED", + UtilitySpcMeso.DEFAULT_SECTOR + ), + UtilitySpcMesoInputOutput.getLayers(context) ) } @@ -216,10 +253,14 @@ object DownloadImage { } needsBitmap = false bitmap = UtilitySpcMesoInputOutput.getImage( + context, + param, + Utility.readPref( context, - param, - Utility.readPref(context, "SPCMESO" + 1 + "_SECTOR_LAST_USED", UtilitySpcMeso.DEFAULT_SECTOR), - UtilitySpcMesoInputOutput.getLayers(context) + "SPCMESO" + 1 + "_SECTOR_LAST_USED", + UtilitySpcMeso.DEFAULT_SECTOR + ), + UtilitySpcMesoInputOutput.getLayers(context) ) } @@ -231,10 +272,14 @@ object DownloadImage { } needsBitmap = false bitmap = UtilitySpcMesoInputOutput.getImage( + context, + param, + Utility.readPref( context, - param, - Utility.readPref(context, "SPCMESO" + 1 + "_SECTOR_LAST_USED", UtilitySpcMeso.DEFAULT_SECTOR), - UtilitySpcMesoInputOutput.getLayers(context) + "SPCMESO" + 1 + "_SECTOR_LAST_USED", + UtilitySpcMeso.DEFAULT_SECTOR + ), + UtilitySpcMesoInputOutput.getLayers(context) ) } @@ -250,7 +295,11 @@ object DownloadImage { "SND" -> { needsBitmap = false - bitmap = UtilitySpcSoundings.getImage(context, UtilityLocation.getNearestSoundingSite(Location.latLon)) +// bitmap = UtilitySpcSoundings.getImage(context, UtilityLocation.getNearestSoundingSite(Location.latLon)) + bitmap = UtilitySpcSoundings.getImage( + context, + SoundingSites.sites.getNearest(Location.latLon) + ) } "STRPT" -> url = UtilitySpc.getStormReportsTodayUrl() diff --git a/app/src/main/java/joshuatee/wx/util/SoundingSites.kt b/app/src/main/java/joshuatee/wx/util/SoundingSites.kt index 7b7a2281..856f63c8 100644 --- a/app/src/main/java/joshuatee/wx/util/SoundingSites.kt +++ b/app/src/main/java/joshuatee/wx/util/SoundingSites.kt @@ -21,234 +21,298 @@ package joshuatee.wx.util +import joshuatee.wx.objects.Sites + @Suppress("SpellCheckingInspection") object SoundingSites { - // grep NWS_LOC UtilityPref.dart |sed "s/Utility.writePref(.NWS_LOCATION_/\"/" | sed 's/",/" to/' | sed "s/);/,/" - val name = mapOf( - "VBG" to "CA, Vandenberg AFB", - "1Y7" to "AZ, Yuma", - "76405" to "MX, La Paz", - "76458" to "MX, Mazatlan", - "SLE" to "OR, Salem", - "UIL" to "WA, Quillayute", - "YLW" to ", KELOWNA APT", - "OAK" to "CA, Oakland", - "NKX" to "CA, San Diego", - "TUS" to "AZ, Tucson", - "DRT" to "TX, Del Rio", - "RAP" to "SD, Rapid City", - "INL" to "MN, International Falls", - "BNA" to "TN, Nashville", - "YMO" to ", MOOSONEE", - "GSO" to "NC, Greensboro", - "WAL" to "VA, Wallops Island", - "IAD" to "DC, Washington", - "PIT" to "PA, Pittsburgh", - "ALB" to "NY, Albany", - "CHH" to "MA, Chatham", - "YQI" to "Nova Scotia, Yarmouth", - "XMR" to "FL, Cape Canaveral", - "TLH" to "FL, Tallahassee", - "WPL" to "ON, Pickle Lake", - "DNR" to "CO, Denver" + "1Y7" to "AZ, Yuma", + "76225" to "MX, Chihuahua", + "76405" to "MX, La Paz", + "76458" to "MX, Mazatlan", + "ABQ" to "NM, Albuquerque", + "ABR" to "SD, Aberdeen", + "ALB" to "NY, Albany", + "AMA" to "TX, Amarillo", + "APX" to "Gaylord, MI", + "BIS" to "ND, Bismarck", + "BMX" to "AL, Birmingham", + "BNA" to "TN, Nashville", + "BOI" to "ID, Boise", + "BRO" to "TX, Brownsville", + "BUF" to "NY, Buffalo", + "CAR" to "ME, Caribou", + "CHS" to "SC, Charleston", + "CRP" to "TX, Corpus Christi", + "DDC" to "KS, Dodge City", + "DRT" to "TX, Del Rio", + "DTX" to "MI, Detroit", + "DVN" to "IA, Davenport", + "EPZ" to "TX, El Paso", + "FFC" to "GA, Atlanta", + "FWD" to "TX, Dallas", + "GGW" to "MT, Glasgow", + "GJT" to "CO, Grand Junction", + "GRB" to "WI, Green Bay", + "GSO" to "NC, Greensboro", + "GYX" to "ME, Gray", + "IAD" to "DC, Washington", + "ILN" to "OH, Wilmington", + "ILX" to "IL, Lincoln", + "INL" to "MN, International Falls", + "JAN" to "MS, Jackson", + "JAX" to "FL, Jacksonville", + "KEY" to "FL, Key West", + "LBF" to "NE, North Platte", + "LCH" to "LA, Lake Charles", + "LIX" to "LA, New Orleans", + "LKN" to "NV, Elko", + "LZK" to "AR, Little Rock", + "MAF" to "TX, Midland", + "MDSD" to "Dominican Republic, Santo Domingo", + "MFL" to "FL, Miami", + "MFR" to "OR, Medford", + "MHX" to "NC, Morehead City", + "MKJP" to "Jamaica, Port Royal", + "MPX" to "MN, Twin Cities", + "NKX" to "CA, San Diego", + "NSTU" to "AS, Pago Pago", + "OAK" to "CA, Oakland", + "OAX" to "NE, Omaha", + "OKX" to "NY, New York City", + "OTX" to "WA, Spokane", + "OUN" to "OK, Norman", + "OYU" to "CAN, FIXME", + "PABE" to "AK, Bethel", + "PABR" to "AK, Barrow", + "PACD" to "AK, Cold Bay", + "PADQ" to "AK, Kodiak", + "PAFA" to "AK, Fairbanks", + "PAKN" to "AK, King Salmon", + "PAMC" to "AK, McGrath", + "PANC" to "AK, Anchorage", + "PANT" to "AK, Annette", + "PAOM" to "AK, Nome", + "PAOT" to "AK, Kotzebue", + "PASN" to "AK, St Paul Island", + "PAYA" to "AK, Yakutat", + "PHLI" to "HI, Lihue", + "PHTO" to "HI, Hilo", + "PIT" to "PA, Pittsburgh", + "REV" to "NV, Reno", + "RIW" to "WY, Riverton", + "RNK" to "VA, Blacksburg", + "SGF" to "MO, Springfield", + "SHV" to "LA, Shreveport", + "SLC" to "UT, Salt Lake City", + "SLE" to "OR, Salem", + "TBW" to "FL, Tampa Bay", + "TFX" to "MT, Great Falls", + "TNCC" to "CuraƧao, Willemstad", + "TOP" to "KS, Topeka", + "TUS" to "AZ, Tucson", + "UIL" to "WA, Quillayute", + "UNR" to "SD, Rapid City", + "VBG" to "CA, Vandenberg AFB", + "VEF" to "NV, Las Vegas", + "WAL" to "VA, Wallops Island", + "WMW" to "CAN, QC, Maniwaki", + "WPL" to "CAN, ON, Pickle Lake", + "YQI" to "CAN, NS, Yarmouth", ) val lat = mapOf( - "76225" to "28.70", - "76405" to "24.07", - "76458" to "23.18", - "ABE" to "60.78", - "ABQ" to "35.03", - "ABR" to "45.45", - "ACD" to "55.20", - "ADQ" to "57.75", - "AFA" to "64.82", - "AKN" to "58.68", - "ALB" to "42.75", - "AMA" to "35.23", - "AMC" to "62.95", - "ANC" to "61.17", - "ANT" to "55.03", - "AOM" to "64.52", - "AOT" to "66.87", - "APX" to "44.90", - "ASN" to "57.15", - "ASY" to "52.72", - "AYA" to "59.52", - "BIS" to "46.77", - "BMX" to "33.17", - "BNA" to "36.12", - "BOI" to "43.57", - "BRO" to "25.90", - "BUF" to "42.93", - "CAR" to "46.87", - "CHH" to "41.67", - "CHS" to "32.90", - "CRP" to "27.77", - "DDC" to "37.77", - "DNR" to "39.75", - "DRA" to "36.62", - "DRT" to "29.37", - "DTX" to "42.68", - "DVN" to "41.60", - "EPZ" to "31.90", - "EYW" to "24.55", - "FFC" to "33.36", - "FLG" to "35.23", - "FWD" to "32.80", - "GGW" to "48.21", - "GJT" to "39.12", - "GRB" to "44.48", - "GSO" to "36.08", - "GYX" to "43.89", - "IAD" to "39.083667", - "ILN" to "39.42", - "ILX" to "40.10", - "INL" to "48.57", - "JAN" to "32.32", - "JAX" to "30.43", - "KEY" to "24.55", - "LBF" to "41.13", - "LCH" to "30.12", - "LIX" to "30.337", - "LKN" to "40.87", - "LWX" to "38.98", - "LZK" to "34.83", - "MAF" to "31.95", - "MFL" to "25.75", - "MFR" to "42.37", - "MFX" to "25.80", - "MHX" to "34.70", - "MPX" to "44.85", - "NJM" to "34.69", - "NKX" to "32.73", - "OAK" to "37.73", - "OAX" to "41.32", - "OKX" to "40.86", - "OTX" to "47.68", - "OUN" to "35.23", - "PIT" to "40.50", - "REV" to "39.57", - "RIW" to "43.00", - "RNK" to "37.21", - "SGF" to "37.14", - "SHV" to "32.45", - "SIL" to "30.25", - "SLC" to "40.78", - "SLE" to "44.92", - "TBW" to "27.70", - "TFX" to "47.45", - "TLH" to "30.56", - "TOP" to "39.07", - "TUS" to "32.12", - "UIL" to "47.95", - "UNR" to "44.07", - "VBG" to "34.72", - "WAL" to "37.85", - "WMW" to "46.0", - "WPL" to "51.47", - "YLW" to "49.97", - "YMO" to "51.27" + "1Y7" to "32.86", + "76225" to "28.70", + "76405" to "24.07", + "76458" to "23.18", + "ABQ" to "35.03", + "ABR" to "45.45", + "ALB" to "42.75", + "AMA" to "35.23", + "APX" to "44.90", + "BIS" to "46.77", + "BMX" to "33.17", + "BNA" to "36.12", + "BOI" to "43.57", + "BRO" to "25.90", + "BUF" to "42.93", + "CAR" to "46.87", + "CHS" to "32.90", + "CRP" to "27.77", + "DDC" to "37.77", + "DRT" to "29.37", + "DTX" to "42.68", + "DVN" to "41.60", + "EPZ" to "31.90", + "FFC" to "33.36", + "FWD" to "32.80", + "GGW" to "48.21", + "GJT" to "39.12", + "GRB" to "44.48", + "GSO" to "36.08", + "GYX" to "43.89", + "IAD" to "39.083667", + "ILN" to "39.42", + "ILX" to "40.10", + "INL" to "48.57", + "JAN" to "32.32", + "JAX" to "30.43", + "KEY" to "24.55", + "LBF" to "41.13", + "LCH" to "30.12", + "LIX" to "30.337", + "LKN" to "40.87", + "LZK" to "34.83", + "MAF" to "31.95", + "MDSD" to "18.43", + "MFL" to "25.75", + "MFR" to "42.37", + "MHX" to "34.70", + "MKJP" to "17.93", + "MPX" to "44.85", + "NKX" to "32.73", + "NSTU" to "14.30", + "OAK" to "37.73", + "OAX" to "41.32", + "OKX" to "40.86", + "OTX" to "47.68", + "OUN" to "35.23", + "OYU" to "49.68", // approx based off spc image + "PABE" to "60.78", + "PABR" to "71.30", + "PACD" to "55.20", + "PADQ" to "57.75", + "PAFA" to "64.82", + "PAKN" to "58.68", + "PAMC" to "62.95", + "PANC" to "61.17", + "PANT" to "55.03", + "PAOM" to "64.50", + "PAOT" to "66.87", + "PASN" to "57.15", + "PAYA" to "59.52", + "PHLI" to "21.98", + "PHTO" to "19.72", + "PIT" to "40.50", + "REV" to "39.57", + "RIW" to "43.00", + "RNK" to "37.21", + "SGF" to "37.14", + "SHV" to "32.45", + "SLC" to "40.78", + "SLE" to "44.92", + "TBW" to "27.70", + "TFX" to "47.45", + "TNCC" to "12.20", + "TOP" to "39.07", + "TUS" to "32.12", + "UIL" to "47.95", + "UNR" to "44.07", + "VBG" to "34.72", + "VEF" to "36.05", + "WAL" to "37.85", + "WMW" to "46.0", + "WPL" to "51.47", + "YQI" to "43.87", ) val lon = mapOf( - "1Y7" to "114.40", - "76225" to "106.07", - "76405" to "110.33", - "76458" to "106.42", - "ABE" to "161.80", - "ABQ" to "106.62", - "ABR" to "98.41", - "ACD" to "162.73", - "ADQ" to "152.50", - "AFA" to "147.87", - "AKN" to "156.65", - "ALB" to "73.80", - "AMA" to "101.70", - "AMC" to "155.60", - "ANC" to "150.02", - "ANT" to "131.57", - "AOM" to "165.45", - "AOT" to "162.63", - "APX" to "84.72", - "ASN" to "170.22", - "ASY" to "174.12", - "AYA" to "139.67", - "BIS" to "100.75", - "BMX" to "86.77", - "BNA" to "86.68", - "BOI" to "116.22", - "BRO" to "97.43", - "BUF" to "78.73", - "CAR" to "68.02", - "CHH" to "69.97", - "CHS" to "80.03", - "CRP" to "97.50", - "DDC" to "99.97", - "DNR" to "104.87", - "DRA" to "116.02", - "DRT" to "100.92", - "DTX" to "83.47", - "DVN" to "90.60", - "EPZ" to "106.70", - "EYW" to "81.75", - "FFC" to "84.56", - "FLG" to "111.82", - "FWD" to "97.30", - "GGW" to "106.63", - "GJT" to "108.53", - "GRB" to "88.13", - "GSO" to "79.95", - "GYX" to "70.25", - "IAD" to "77.529224", - "ILN" to "83.82", - "ILX" to "89.30", - "INL" to "93.38", - "JAN" to "90.08", - "JAX" to "81.61", - "KEY" to "81.75", - "LBF" to "100.68", - "LCH" to "93.22", - "LIX" to "89.825", - "LKN" to "115.73", - "LWX" to "77.47", - "LZK" to "92.25", - "MAF" to "102.18", - "MFL" to "80.38", - "MFR" to "122.87", - "MFX" to "80.38", - "MHX" to "76.80", - "MPX" to "93.57", - "NJM" to "77.03", - "NKX" to "117.17", - "OAK" to "122.22", - "OAX" to "96.37", - "OKX" to "72.86", - "OTX" to "117.63", - "OUN" to "97.47", - "PIT" to "80.22", - "REV" to "119.80", - "RIW" to "108.50", - "RNK" to "80.41", - "SGF" to "93.23", - "SHV" to "93.83", - "SIL" to "89.77", - "SLC" to "111.97", - "SLE" to "123.00", - "TBW" to "82.40", - "TFX" to "111.38", - "TLH" to "84.45", - "TOP" to "95.62", - "TUS" to "110.93", - "UIL" to "124.55", - "UNR" to "103.21", - "VBG" to "120.57", - "WAL" to "75.48", - "WMW" to "76.87", - "WPL" to "90.20", - "YLW" to "119.38", - "YMO" to "80.65" + "1Y7" to "114.40", + "76225" to "106.07", + "76405" to "110.33", + "76458" to "106.42", + "ABQ" to "106.62", + "ABR" to "98.41", + "ALB" to "73.80", + "AMA" to "101.70", + "APX" to "84.72", + "BIS" to "100.75", + "BMX" to "86.77", + "BNA" to "86.68", + "BOI" to "116.22", + "BRO" to "97.43", + "BUF" to "78.73", + "CAR" to "68.02", + "CHS" to "80.03", + "CRP" to "97.50", + "DDC" to "99.97", + "DRT" to "100.92", + "DTX" to "83.47", + "DVN" to "90.60", + "EPZ" to "106.70", + "FFC" to "84.56", + "FWD" to "97.30", + "GGW" to "106.63", + "GJT" to "108.53", + "GRB" to "88.13", + "GSO" to "79.95", + "GYX" to "70.25", + "IAD" to "77.529224", + "ILN" to "83.82", + "ILX" to "89.30", + "INL" to "93.38", + "JAN" to "90.08", + "JAX" to "81.61", + "KEY" to "81.75", + "LBF" to "100.68", + "LCH" to "93.22", + "LIX" to "89.825", + "LKN" to "115.73", + "LZK" to "92.25", + "MAF" to "102.18", + "MDSD" to "69.67", + "MFL" to "80.38", + "MFR" to "122.87", + "MHX" to "76.80", + "MKJP" to "76.78", + "MPX" to "93.57", + "NKX" to "117.17", + "NSTU" to "170.70", + "OAK" to "122.22", + "OAX" to "96.37", + "OKX" to "72.86", + "OTX" to "117.63", + "OUN" to "97.47", + "OYU" to "83.66", // approx based off spc image + "PABE" to "161.80", + "PABR" to "156.78", + "PACD" to "162.73", + "PADQ" to "152.50", + "PAFA" to "147.87", + "PAKN" to "156.65", + "PAMC" to "155.60", + "PANC" to "150.02", + "PANT" to "131.57", + "PAOM" to "165.43", + "PAOT" to "162.63", + "PASN" to "170.22", + "PAYA" to "139.67", + "PHLI" to "159.35", + "PHTO" to "155.07", + "PIT" to "80.22", + "REV" to "119.80", + "RIW" to "108.50", + "RNK" to "80.41", + "SGF" to "93.23", + "SHV" to "93.83", + "SLC" to "111.97", + "SLE" to "123.00", + "TBW" to "82.40", + "TFX" to "111.38", + "TNCC" to "68.97", + "TOP" to "95.62", + "TUS" to "110.93", + "UIL" to "124.55", + "UNR" to "103.21", + "VBG" to "120.57", + "VEF" to "115.18", + "WAL" to "75.48", + "WMW" to "76.87", + "WPL" to "90.20", + "YQI" to "66.100", ) + + val sites: Sites = Sites(name, lat, lon, true) } diff --git a/app/src/main/java/joshuatee/wx/util/UtilityFavorites.kt b/app/src/main/java/joshuatee/wx/util/UtilityFavorites.kt index be572fba..eed521ca 100644 --- a/app/src/main/java/joshuatee/wx/util/UtilityFavorites.kt +++ b/app/src/main/java/joshuatee/wx/util/UtilityFavorites.kt @@ -40,7 +40,8 @@ object UtilityFavorites { savePref(context, newFav, type) } if (!UIPreferences.favorites[type]!!.contains(GlobalVariables.PREFERENCE_SEPARATOR)) { - val newFav = GlobalVariables.PREFERENCE_SEPARATOR + UIPreferences.favorites[type]!!.trimStart() + val newFav = + GlobalVariables.PREFERENCE_SEPARATOR + UIPreferences.favorites[type]!!.trimStart() savePref(context, newFav, type) } } @@ -52,7 +53,8 @@ object UtilityFavorites { fun setupMenu(context: Context, value: String, type: FavoriteType): List { checkAndCorrect(context, type) - var favorites = UIPreferences.favorites[type]!!.split(":").dropLastWhile { it.isEmpty() }.toMutableList() + var favorites = UIPreferences.favorites[type]!!.split(":").dropLastWhile { it.isEmpty() } + .toMutableList() if (favorites.size < 3) { favorites = MutableList(3) { "" } } @@ -61,10 +63,12 @@ object UtilityFavorites { favorites[2] = "Modify..." val returnList = MutableList(favorites.size) { "" } favorites.forEachIndexed { k, fav -> + UtilityLog.d("wxFAV", fav) val name = when (type) { FavoriteType.RID -> UtilityLocation.getRadarSiteName(fav) FavoriteType.WFO -> UtilityLocation.getWfoSiteName(fav) - FavoriteType.SND -> UtilityLocation.getSoundingSiteName(fav) +// FavoriteType.SND -> UtilityLocation.getSoundingSiteName(fav) + FavoriteType.SND -> SoundingSites.sites.byCode[fav]?.fullName FavoriteType.NWS_TEXT -> UtilityWpcText.getLabel(fav) FavoriteType.SPCMESO -> UtilitySpcMeso.getLabelFromParam(fav) FavoriteType.SREF -> "" diff --git a/app/src/main/java/joshuatee/wx/util/UtilityMath.kt b/app/src/main/java/joshuatee/wx/util/UtilityMath.kt index 776c0a3e..0c695686 100644 --- a/app/src/main/java/joshuatee/wx/util/UtilityMath.kt +++ b/app/src/main/java/joshuatee/wx/util/UtilityMath.kt @@ -29,9 +29,15 @@ import kotlin.math.* object UtilityMath { fun distanceOfLine(x1: Double, y1: Double, x2: Double, y2: Double): Double = - sqrt((x2 - x1).pow(2.0) + (y2 - y1).pow(2.0)) - - fun computeTipPoint(x0: Double, y0: Double, x1: Double, y1: Double, right: Boolean): List { + sqrt((x2 - x1).pow(2.0) + (y2 - y1).pow(2.0)) + + fun computeTipPoint( + x0: Double, + y0: Double, + x1: Double, + y1: Double, + right: Boolean + ): List { val dx = x1 - x0 val dy = y1 - y0 val length = sqrt(dx * dx + dy * dy) @@ -53,15 +59,22 @@ object UtilityMath { return listOf(rx, ry) } - fun computeMidPoint(x0: Double, y0: Double, x1: Double, y1: Double, fraction: Double): List = - listOf(x0 + fraction * (x1 - x0), y0 + fraction * (y1 - y0)) + fun computeMidPoint( + x0: Double, + y0: Double, + x1: Double, + y1: Double, + fraction: Double + ): List = + listOf(x0 + fraction * (x1 - x0), y0 + fraction * (y1 - y0)) // 42.98888 to 42.99 fun latLonFix(x: String): String { val dblX = To.double(x) var newX = "0.0" try { - newX = String.format(Locale.US, "%.2f", dblX).replace("00$".toRegex(), "").replace("0$".toRegex(), "").replace("\\.$".toRegex(), "") + newX = String.format(Locale.US, "%.2f", dblX).replace("00$".toRegex(), "") + .replace("0$".toRegex(), "").replace("\\.$".toRegex(), "") } catch (e: Exception) { UtilityLog.handleException(e) } @@ -70,7 +83,7 @@ object UtilityMath { // convert polar cords to rect fun toRect(r: Float, t: Float): FloatArray = - floatArrayOf((r * cos(t / (180.0f / PI))).toFloat(), (r * sin(t / (180.0f / PI))).toFloat()) + floatArrayOf((r * cos(t / (180.0f / PI))).toFloat(), (r * sin(t / (180.0f / PI))).toFloat()) fun unitsPressure(value: String): String { val num = To.double(value) @@ -88,22 +101,22 @@ object UtilityMath { } fun knotsToMph(value: String): String = - (To.double(value) * 1.151).roundToInt().toString() + (To.double(value) * 1.151).roundToInt().toString() internal fun fahrenheitToCelsius(value: Double): String = - ((value - 32.0) * 5.0 / 9.0).roundToInt().toString() + ((value - 32.0) * 5.0 / 9.0).roundToInt().toString() // used by celsiusToFahrenheitTable only private fun celsiusToFahrenheitAsInt(value: Int): String = - (value * 9.0 / 5.0 + 32.0).roundToInt().toString() + (value * 9.0 / 5.0 + 32.0).roundToInt().toString() fun celsiusToFahrenheitTable(): String = - (40 downTo -40).joinToString("") { - it.toString() + " " + celsiusToFahrenheitAsInt(it) + GlobalVariables.newline - } + (40 downTo -40).joinToString("") { + it.toString() + " " + celsiusToFahrenheitAsInt(it) + GlobalVariables.newline + } internal fun pressureMBtoIn(value: String): String = - To.stringFromFloatFixed((To.double(value) / 33.8637526), 2) + " in" + To.stringFromFloatFixed((To.double(value) / 33.8637526), 2) + " in" fun pixPerDegreeLon(centerX: Double, factor: Double): Double { val radius = 180.0 / PI * (1.0 / cos(Math.toRadians(30.51))) * factor @@ -114,17 +127,35 @@ object UtilityMath { fun rad2deg(rad: Double): Double = rad * 180.0 / PI - private val windDirections = listOf("N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N") - - fun convertWindDir(direction: Double): String { - val normalizedDirection = direction.toInt() % 360 + private val windDirections = listOf( + "N", + "NNE", + "NE", + "ENE", + "E", + "ESE", + "SE", + "SSE", + "S", + "SSW", + "SW", + "WSW", + "W", + "WNW", + "NW", + "NNW", + "N" + ) + + fun bearingToDirection(direction: Int): String { + val normalizedDirection = direction % 360 val listIndex = (normalizedDirection.toDouble() / 22.5).roundToInt() return windDirections[listIndex] } // https://training.weather.gov/wdtd/tools/misc/beamwidth/index.htm fun getRadarBeamHeight(degree: Double, distance: Double): Double = - 3.281 * (sin(Math.toRadians(degree)) * distance + distance * distance / 15417.82) * 1000.0 + 3.281 * (sin(Math.toRadians(degree)) * distance + distance * distance / 15417.82) * 1000.0 fun heatIndex(temp: String, rh: String): String { val t = To.double(temp) diff --git a/build.gradle b/build.gradle index 572175ee..15f902ad 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.7.1' + classpath 'com.android.tools.build:gradle:8.7.2' // https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.23" } diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index bdb807d3..a62c9ba5 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -2,10 +2,34 @@ # Developer ChangeLog -## 55918 2024_10_14 +## 55919 2024_11_02 * [ADD] +## 55918 2024_11_02 + +* [ADD] additional Soundings sites (especially AK/HI), remove some that were obsolete +* [ADD] Sites/Site framework to be used by Sounding sites and wfo/radar in the future +* [ADD] Nearest Sounding option to Nexrad "Long press" (press and hold) menu - added to bottom ( + includes direction) +* [ADD] Nexrad "Long press" now shows direction in addition to distance for closest radars and + observation point +* [ADD] Nexrad "Long press" more concise verbiage: miles to mi (in 2 spots) +* [ADD] Nexrad "Long press" miles to location/radar site enhanced to show direction to +* [ADD] NHC Storm card - show bearing after direction +* [ADD] tool/lib updates + +``` +- classpath 'com.android.tools.build:gradle:8.7.1' ++ classpath 'com.android.tools.build:gradle:8.7.2' + +- implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6' ++ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7' + +- implementation 'androidx.core:core-ktx:1.13.1' ++ implementation 'androidx.core:core-ktx:1.15.0' +``` + ## 55917 2024_10_14 * [ADD] reinstate wX Android setting "Main screen radar button (requires restart)" diff --git a/doc/ChangeLog_User.md b/doc/ChangeLog_User.md index 3cafd10f..abd7ea1a 100644 --- a/doc/ChangeLog_User.md +++ b/doc/ChangeLog_User.md @@ -8,11 +8,16 @@ Please also review [Upcoming changes](https://gitlab.com/joshua.tee/wxl23/-/blob/master/doc/UPCOMING_CHANGES.md) impacting all or some users. +## 55917 2024_10_15 (BETA) + +* [ADD] reinstate wX Android setting "Main screen radar button (requires restart)" + ## 55916 2024_10_12 (BETA) * [ADD] NHC storm summary in NHC activity - show more headlines * [ADD] NHC Storm activity title was not showing wind speed in mph -* [ADD] change how hourly is displayed to work better with larger fonts (it was unusable with large fonts) +* [ADD] change how hourly is displayed to work better with larger fonts (it was unusable with large + fonts) * [ADD] In Hourly, abbreviate "Isolated" as "Iso" * [FIX] SPC Compmap - remove product which is no longer available via the website: **3-hr surface pressure change**