From aa6b32a1c57410f53f155e7a70eba32806695744 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Sat, 24 Feb 2024 10:47:14 -0800 Subject: [PATCH 01/12] docs: add MIT license --- license.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 license.txt diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..becdfe9 --- /dev/null +++ b/license.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Cyrus Anderson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From ab5197c649a4cd942117c0d2125ac76cd12921d9 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Sat, 24 Feb 2024 10:47:27 -0800 Subject: [PATCH 02/12] docs: add readme.md file --- readme.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..518fc4b --- /dev/null +++ b/readme.md @@ -0,0 +1,41 @@ +# Project Title + +Text. + +## Getting Started + +Text. + +### Prerequisites + +Text. + +### Installing + +Text. + +## Deployment + +Text. + +## Built With + +Text. + +## Contributing + +Text. + +## Versioning + +Text. + +## Authors + +Text. + +## License + +Text. + +## Acknowledements \ No newline at end of file From 0d78e0d8edfe067009c6f7f0d199ac47532df084 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Sat, 24 Feb 2024 13:00:03 -0800 Subject: [PATCH 03/12] docs: update readme.md --- readme.md | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/readme.md b/readme.md index 518fc4b..c65560e 100644 --- a/readme.md +++ b/readme.md @@ -1,41 +1,53 @@ -# Project Title +# Ski Weather Outlook +Lift tickets are expensive. Ski area parking lots fill up. Day pass limits... There are plenty of reasons to choose wisely when planning a ski weekend. This app helps you plan by providing a dashboard view of NOAA weather forecasts for popular ski areas located in the Cascade Mountains of Washington State. The app updates once per day and summarizes precipitation, snow levels, temperature and wind data for each day of the upcoming week. -Text. +Access the [Ski Weather Outlook](https://skiforecast.z5.web.core.windows.net/) app. -## Getting Started +### Version 1.0.0 (Released: February 24, 2024) -Text. +## Getting Started +Clone the repository from the terminal using the following command: `git clone https://github.com/cander67/skiforecast.git` ### Prerequisites - -Text. +Local development can be accomplished by creating a virtual environment using Python 3.11 and installing the necessary dependencies as described in the next section. + +The following prerequisites must be met for cloud deployment: +- Azure Developer CLI +- Azure Function App +- Azure Function App Registration and Service Principal +- Azure Storage Account, standard general-purpose v2 account +- Microsoft Entra security group +- Azure RBAC assignments +- Properly configured environment variables + - AZURE_CLIENT_ID + - AZURE_TENANT_ID + - AZURE_CLIENT_SECRET + - User-Agent Header for API requests ### Installing - -Text. +Install [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview) +Install dependencies from the terminal using the following command: `pip install -r requirements.txt`. ## Deployment - -Text. +This app is setup for [continous deployment](https://learn.microsoft.com/en-us/azure/azure-functions/functions-continuous-deployment) to [Azure Functions](https://azure.microsoft.com/en-us/products/functions) using [GitHub Actions](https://docs.github.com/en/actions). ## Built With - -Text. +- [Azure Functions](https://azure.microsoft.com/en-us/products/functions) +- [Azure Static Website Hosing](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website) ## Contributing +Contributions and suggestions are welcome and may be submitted by forking this project and submitting a pull request through GitHub. -Text. - -## Versioning +## Changelog -Text. +### Version 1.0.0 (Released: February 24, 2024) +- Initial release ## Authors - -Text. +Written by Cyrus Anderson. ## License +This project is licensed under the MIT License - see the LICENSE file for details. -Text. - -## Acknowledements \ No newline at end of file +## Acknowledements +Thanks to varunr89 for brainstorming and motivation. \ No newline at end of file From 919b599e5648882e4ce0e8ae4b2b8969f7f2d3d5 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Mon, 26 Feb 2024 08:10:22 -0800 Subject: [PATCH 04/12] feat: automatically set simulated date and time --- test/test_forecast_proc.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/test_forecast_proc.py b/test/test_forecast_proc.py index 69956c8..f2dee00 100644 --- a/test/test_forecast_proc.py +++ b/test/test_forecast_proc.py @@ -2,15 +2,16 @@ import os import json -from datetime import datetime +from datetime import datetime, time import pytz import bs4 as BeautifulSoup import utils as utils -#now = datetime.now(pytz.UTC) -now = datetime(2024, 2, 23, 13, 8, 0, 0, pytz.UTC) -local_time = now.astimezone(pytz.timezone('US/Pacific')) - +# Set datetime and timezone +now = datetime.now(pytz.UTC).date() +process_time = time(13, 8, 0, 0) +simulated_time = datetime.combine(now, process_time) +local_time = simulated_time.astimezone(pytz.timezone('US/Pacific')) # Define parameters locations = { From fd14bfa4ccad6240629bcc37fe39c724b5815399 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Mon, 26 Feb 2024 09:30:19 -0800 Subject: [PATCH 05/12] update error handling for missing weather and snowfall data --- utils.py | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/utils.py b/utils.py index af01112..0178aa4 100644 --- a/utils.py +++ b/utils.py @@ -1175,6 +1175,10 @@ def create_row(self, table_data): precip_range = [] sky_cover = None wind_descr = None + weather = None + prob_precip = None + hi = None + lo = None try: # Precipitation try: @@ -1183,18 +1187,45 @@ def create_row(self, table_data): lo = day_data['quantitativePrecipitation']['data']['sum'] hi = day_data['snowfallAmount']['data']['sum'] except: - prob_precip = day_data['probabilityOfPrecipitation']['data']['avg'] - lo = day_data['quantitativePrecipitation']['data']['sum'] - hi = day_data['snowfallAmount']['data']['sum'] - if hi > 0 and lo > 0: + dt_str = dt.strftime('%Y-%m-%dT06:00:00') + try: + prob_precip = day_data['probabilityOfPrecipitation']['data']['avg'] + print(f'EXCEPT: {day}, {prob_precip}') + except: + prob_precip = 0.0 + print(f'EXCEPT: {day}, {prob_precip}') + try: + lo = day_data['quantitativePrecipitation']['data']['sum'] + print(f'EXCEPT: {day}, {lo}') + except: + lo = 0.0 + print(f'EXCEPT: {day}, {lo}') + try: + hi = day_data['snowfallAmount']['data']['sum'] + print(f'EXCEPT: {day}, {hi}') + except: + hi = 0.0 + print(f'EXCEPT: {day}, {hi}') + + if hi != None and lo != None: if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] > 32: - weather = [(dt, [['snow'], ['rain']])] + weather = [(dt_str, [['snow'], ['rain']])] if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] <= 32: - weather = [(dt, [['snow']])] - if hi == 0 and lo > 0: - weather = [(dt, [['rain']])] - if hi > 0 and lo == 0: - weather = [(dt, [['snow']])] + weather = [(dt_str, [['snow']])] + #if hi == 0 and lo > 0: + #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] > 32: + #weather = [(dt_str, [['snow'], ['rain']])] + #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] <= 32: + #weather = [(dt_str, [['snow']])] + #weather = [(dt_str, [['rain']])] + #if hi > 0 and lo == 0: + #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] > 32: + #weather = [(dt_str, [['snow'], ['rain']])] + #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] <= 32: + #weather = [(dt_str, [['snow']])] + #weather = [(dt_str, [['snow']])] + + print(f'EXCEPT: {day}, WEATHER: {weather}, LO: {lo}, HI: {hi}') if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) or ((prob_precip == None) or (lo == None) or (hi == None)): precip_string = 'NONE' From b3f80880a676ffb9e42b02f945b72d135b3ca16c Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Mon, 26 Feb 2024 09:30:40 -0800 Subject: [PATCH 06/12] update error handling for missing weather and snowfall data --- test/test_forecast_proc.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/test/test_forecast_proc.py b/test/test_forecast_proc.py index f2dee00..b012d68 100644 --- a/test/test_forecast_proc.py +++ b/test/test_forecast_proc.py @@ -8,9 +8,11 @@ import utils as utils # Set datetime and timezone -now = datetime.now(pytz.UTC).date() +now = datetime.now().date() process_time = time(13, 8, 0, 0) +tz = pytz.timezone('UTC') simulated_time = datetime.combine(now, process_time) +simulated_time = tz.localize(simulated_time) local_time = simulated_time.astimezone(pytz.timezone('US/Pacific')) # Define parameters @@ -69,7 +71,7 @@ f.close() # Instantiate TableData object - setup = utils.TableData(now, file, time_periods, properties) + setup = utils.TableData(simulated_time, file, time_periods, properties) print(f'TABLE DATA: {setup}\n') # Parse forecast data @@ -101,24 +103,17 @@ # Create table row try: row = setup.create_row(table_data) - # Append row to table - #table.append_row(row) - #print(f'ROW:\n{json.dumps(row, sort_keys=False, indent=4)}\n') except Exception as e: print(f'ERROR CREATING TABLE ROW, {file}: {e}') table.append_row(row) -#print(f'TABLE: {table.get_table()}\n') t = table.get_table() #Assign columns and rows columns = t['columns'] rows = t['rows'] -#print(f'COLUMNS:\n{columns}\n') -#print(f'ROWS:\n{rows}\n') - # Get dates day0 = datetime.strptime(columns[1][1], '%Y-%m-%d') day6 = datetime.strptime(columns[7][1], '%Y-%m-%d') From a5093e53b33b22df4c28fbf0a71c455184193d05 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Mon, 26 Feb 2024 17:58:16 -0800 Subject: [PATCH 07/12] fix: handle missing NOAA data --- utils.py | 118 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 33 deletions(-) diff --git a/utils.py b/utils.py index 0178aa4..38a93bc 100644 --- a/utils.py +++ b/utils.py @@ -1142,6 +1142,8 @@ def create_row(self, table_data): row (list) : [] ''' + #print(f'TABLE DATA: {table_data}') + now = self._time location = self._location data = table_data[location] @@ -1186,59 +1188,101 @@ def create_row(self, table_data): prob_precip = day_data['probabilityOfPrecipitation']['data']['avg'] lo = day_data['quantitativePrecipitation']['data']['sum'] hi = day_data['snowfallAmount']['data']['sum'] - except: + except Exception as e: + print(f'EXCEPT: {day}, {e}') dt_str = dt.strftime('%Y-%m-%dT06:00:00') try: prob_precip = day_data['probabilityOfPrecipitation']['data']['avg'] print(f'EXCEPT: {day}, {prob_precip}') except: - prob_precip = 0.0 + prob_precip = 0 print(f'EXCEPT: {day}, {prob_precip}') try: lo = day_data['quantitativePrecipitation']['data']['sum'] print(f'EXCEPT: {day}, {lo}') except: - lo = 0.0 - print(f'EXCEPT: {day}, {lo}') + lo = 0 + data['predictions'][day]['time_period']['24h']['status']['quantitativePrecipitation'] = 2 + #data['predictions'][day]['time_period']['24h']['data'] = {"quantitativePrecipitation": {"units": "in", "data": {'sum': 0}}} + data['predictions'][day]['time_period']['24h']['data']['quantitativePrecipitation'] = {"units": "in", "data": {'sum': 0}} + print(f'EXCEPT NEW LO: {day}, {lo}') try: hi = day_data['snowfallAmount']['data']['sum'] print(f'EXCEPT: {day}, {hi}') - except: - hi = 0.0 - print(f'EXCEPT: {day}, {hi}') - - if hi != None and lo != None: + except Exception as e: + #print(e) + hi = 0 + data['predictions'][day]['time_period']['24h']['status']['snowfallAmount'] = 2 + #data['predictions'][day]['time_period']['24h']['data'] = {"snowfallAmount": {"units": "in", "data": {'sum': 0}}} + data['predictions'][day]['time_period']['24h']['data']['snowfallAmount'] = {"units": "in", "data": {'sum': 0}} + print(f'EXCEPT NEW HI: {day}, {hi}') + + print(f'UPPER EXCEPT: {day}, WEATHER: {weather}, LO: {lo}, HI: {hi}') + + if hi == 0 and lo == 0: + weather = [(dt_str, [[None, None, None]])] + data['predictions'][day]['time_period']['24h']['status']['weather'] = 2 + snow = False + rain = False + if hi == 0 and lo > 0: + if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] > 32: + data['predictions'][day]['time_period']['24h']['status']['weather'] = 1 + weather = [(dt_str, [['rain']])] + rain = True + if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] <= 32: + data['predictions'][day]['time_period']['24h']['status']['weather'] = 3 + weather = [(dt_str, [['snow']])] + snow = True + if hi > 0 and lo == 0: if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] > 32: + data['predictions'][day]['time_period']['24h']['status']['weather'] = 2 weather = [(dt_str, [['snow'], ['rain']])] + snow = True + rain = True if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] <= 32: + data['predictions'][day]['time_period']['24h']['status']['weather'] = 3 + data['predictions'][day]['time_period']['24h']['status']['snowfallAmount'] = 3 weather = [(dt_str, [['snow']])] - #if hi == 0 and lo > 0: - #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] > 32: - #weather = [(dt_str, [['snow'], ['rain']])] - #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] <= 32: - #weather = [(dt_str, [['snow']])] - #weather = [(dt_str, [['rain']])] - #if hi > 0 and lo == 0: - #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] > 32: - #weather = [(dt_str, [['snow'], ['rain']])] - #if data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'][1] <= 32: - #weather = [(dt_str, [['snow']])] - #weather = [(dt_str, [['snow']])] - - print(f'EXCEPT: {day}, WEATHER: {weather}, LO: {lo}, HI: {hi}') + snow = True + + print(f'LOWER EXCEPT: {day}, WEATHER: {weather}, LO: {lo}, HI: {hi}') + #reference_status = data['predictions'][day]['time_period']['24h']['status']['overall'] + #for property in data['predictions'][day]['time_period']['24h']['status'].keys(): + #if data["predictions"][day]["time_period"]["24h"]["status"][property] < reference_status: + #reference_status = data["predictions"][day]["time_period"]["24h"]["status"][property] + #data['predictions'][day]['time_period']['24h']['status']['overall'] = reference_status if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) or ((prob_precip == None) or (lo == None) or (hi == None)): precip_string = 'NONE' - if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and (prob_precip < 10): + #snow = False + #rain = False + #if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and ((lo == 0) and (hi == 0)): + #precip_string = 'NONE' + #snow = False + #rain = False + if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and (prob_precip <= 10): precip_string = 'NONE' - if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and (prob_precip > 10): - max_temp = data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'] - if max_temp[1] <= 32: - precip_amt = day_data['snowfallAmount']['data']['sum'] - precip_string = f'SNOW: {precip_amt:.1f}in' - if max_temp[1] > 32: - precip_amt = day_data['quantitativePrecipitation']['data']['sum'] - precip_string = f'RAIN: {precip_amt:.1f}in' + #snow = False + #rain = False + try: + if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and (prob_precip > 10): + max_temp = data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'] + if max_temp[1] <= 32: + precip_amt = day_data['snowfallAmount']['data']['sum'] + if precip_amt >= 0.1: + precip_string = f'SNOW: {precip_amt:.1f}in' + if precip_amt < 0.1: + precip_string = 'SNOW: trace' + if max_temp[1] > 32: + precip_amt = day_data['quantitativePrecipitation']['data']['sum'] + if precip_amt >= 0.1: + precip_string = f'RAIN: {precip_amt:.1f}in' + if precip_amt < 0.1: + precip_string = 'RAIN: trace' + data['predictions'][day]['time_period']['24h']['status']['weather'] = 1 + except Exception as e: + print(f'INNER EXCEPT: {day}, {e}') + print(f"output: {data['predictions'][day]['time_period']['24h']['data']}") if (len(weather) >= 1 and weather[0][1] != [[None, None, None]]) and prob_precip != None: for i in range(len(weather)): @@ -1300,6 +1344,12 @@ def create_row(self, table_data): if snow == False and rain == False: precip_string = f'NONE' + reference_status = data['predictions'][day]['time_period']['24h']['status']['overall'] + for property in data['predictions'][day]['time_period']['24h']['status'].keys(): + if data["predictions"][day]["time_period"]["24h"]["status"][property] < reference_status: + reference_status = data["predictions"][day]["time_period"]["24h"]["status"][property] + data['predictions'][day]['time_period']['24h']['status']['overall'] = reference_status + precipitation = f'{precip_string}, {prob_precip:.0f}%' # Snow Level @@ -1389,7 +1439,8 @@ def create_row(self, table_data): temp_string = f'{temp[1]:.0f}' alt_temp = list(day_data['temperature']['data'][k]) alt_temp[1] = f'{alt_temp[1]:.0f}' - except: + except Exception as e: + #print(f'EXCEPT: {location}, {day}, {k}, {e}') temp_string = '--' alt_temp[1] = 'Incomplete Temp Data' temps.append(temp_string) @@ -1440,6 +1491,7 @@ def create_row(self, table_data): except Exception as e: logging.info(f'\n\nEXCEPT: {location}, {day}, {e}\n\n') + print(f'\n\nEXCEPT: {location}, {day}, {e}\n\n') pass self._row = row From 56561bf7132e2b06258845a0791aafaac1a8c577 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Mon, 26 Feb 2024 18:01:10 -0800 Subject: [PATCH 08/12] cleanup: remove commented out lines and print statements --- utils.py | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/utils.py b/utils.py index 38a93bc..2960e98 100644 --- a/utils.py +++ b/utils.py @@ -1193,31 +1193,20 @@ def create_row(self, table_data): dt_str = dt.strftime('%Y-%m-%dT06:00:00') try: prob_precip = day_data['probabilityOfPrecipitation']['data']['avg'] - print(f'EXCEPT: {day}, {prob_precip}') except: prob_precip = 0 - print(f'EXCEPT: {day}, {prob_precip}') try: lo = day_data['quantitativePrecipitation']['data']['sum'] - print(f'EXCEPT: {day}, {lo}') except: lo = 0 data['predictions'][day]['time_period']['24h']['status']['quantitativePrecipitation'] = 2 - #data['predictions'][day]['time_period']['24h']['data'] = {"quantitativePrecipitation": {"units": "in", "data": {'sum': 0}}} data['predictions'][day]['time_period']['24h']['data']['quantitativePrecipitation'] = {"units": "in", "data": {'sum': 0}} - print(f'EXCEPT NEW LO: {day}, {lo}') try: hi = day_data['snowfallAmount']['data']['sum'] - print(f'EXCEPT: {day}, {hi}') - except Exception as e: - #print(e) + except: hi = 0 data['predictions'][day]['time_period']['24h']['status']['snowfallAmount'] = 2 - #data['predictions'][day]['time_period']['24h']['data'] = {"snowfallAmount": {"units": "in", "data": {'sum': 0}}} data['predictions'][day]['time_period']['24h']['data']['snowfallAmount'] = {"units": "in", "data": {'sum': 0}} - print(f'EXCEPT NEW HI: {day}, {hi}') - - print(f'UPPER EXCEPT: {day}, WEATHER: {weather}, LO: {lo}, HI: {hi}') if hi == 0 and lo == 0: weather = [(dt_str, [[None, None, None]])] @@ -1245,25 +1234,10 @@ def create_row(self, table_data): weather = [(dt_str, [['snow']])] snow = True - print(f'LOWER EXCEPT: {day}, WEATHER: {weather}, LO: {lo}, HI: {hi}') - #reference_status = data['predictions'][day]['time_period']['24h']['status']['overall'] - #for property in data['predictions'][day]['time_period']['24h']['status'].keys(): - #if data["predictions"][day]["time_period"]["24h"]["status"][property] < reference_status: - #reference_status = data["predictions"][day]["time_period"]["24h"]["status"][property] - #data['predictions'][day]['time_period']['24h']['status']['overall'] = reference_status - if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) or ((prob_precip == None) or (lo == None) or (hi == None)): precip_string = 'NONE' - #snow = False - #rain = False - #if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and ((lo == 0) and (hi == 0)): - #precip_string = 'NONE' - #snow = False - #rain = False if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and (prob_precip <= 10): precip_string = 'NONE' - #snow = False - #rain = False try: if (len(weather) == 1 and weather[0][1] == [[None, None, None]]) and (prob_precip > 10): max_temp = data['predictions'][day]['time_period']['24h']['data']['temperature']['data']['max'] @@ -1439,8 +1413,7 @@ def create_row(self, table_data): temp_string = f'{temp[1]:.0f}' alt_temp = list(day_data['temperature']['data'][k]) alt_temp[1] = f'{alt_temp[1]:.0f}' - except Exception as e: - #print(f'EXCEPT: {location}, {day}, {k}, {e}') + except: temp_string = '--' alt_temp[1] = 'Incomplete Temp Data' temps.append(temp_string) From c0ec95f44873f66f4c498b5fabcc513bd77408fa Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Mon, 26 Feb 2024 18:02:42 -0800 Subject: [PATCH 09/12] docs: fix typos in readme.md --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index c65560e..f5d4463 100644 --- a/readme.md +++ b/readme.md @@ -25,8 +25,8 @@ The following prerequisites must be met for cloud deployment: - User-Agent Header for API requests ### Installing -Install [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview) -Install dependencies from the terminal using the following command: `pip install -r requirements.txt`. +- Install [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview) +- Install dependencies from the terminal using the following command: `pip install -r requirements.txt` ## Deployment This app is setup for [continous deployment](https://learn.microsoft.com/en-us/azure/azure-functions/functions-continuous-deployment) to [Azure Functions](https://azure.microsoft.com/en-us/products/functions) using [GitHub Actions](https://docs.github.com/en/actions). From c4cf298099eb0c4219cbc419e5d719c2d934c21c Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Mon, 26 Feb 2024 18:15:26 -0800 Subject: [PATCH 10/12] docs: format prerequisites in readme.md --- readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index f5d4463..ae63818 100644 --- a/readme.md +++ b/readme.md @@ -19,9 +19,9 @@ The following prerequisites must be met for cloud deployment: - Microsoft Entra security group - Azure RBAC assignments - Properly configured environment variables - - AZURE_CLIENT_ID - - AZURE_TENANT_ID - - AZURE_CLIENT_SECRET + - `AZURE_CLIENT_ID` + - `AZURE_TENANT_ID` + - `AZURE_CLIENT_SECRET` - User-Agent Header for API requests ### Installing From 81ee7676f0f269182458410432591fa23d9ded36 Mon Sep 17 00:00:00 2001 From: Cyrus Anderson Date: Tue, 27 Feb 2024 16:33:03 -0800 Subject: [PATCH 11/12] update: html output add link to doc.html page add key for status add key for abbreviations --- function_app.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/function_app.py b/function_app.py index 9ff31cc..2e2bd5a 100644 --- a/function_app.py +++ b/function_app.py @@ -137,16 +137,14 @@ def cron(skiForecastTimer: func.TimerRequest) -> None: html += "" html += f"

Updated: {local_time.strftime('%Y-%m-%d %H:%M')} (PT)

\n" html += '
\n

NOTES

\n' - html += "
\n
- Data compiled from NOAA and scored according to subjective criteria for what makes a great ski day
\n" - html += '
- Hover over table cells for more data
\n' - html += "
- STATUS: RED = Don't Bother | YELLOW = Maybe | GREEN = Shred on!
\n" - html += '
- MIX: Rain/Snow mixture; forecast snowfall amount reported
\n' - html += '
- Trace = < 0.1in forecast precip
\n' - html += '
- SLVL: Snow level; min & max for 24 hrs (6am to 6am) starting on the forecast date
\n' - html += '
- AM|PM|ON: avg temp, morning = 6am - 12pm | afternoon = 12pm - 6pm | overnight = 6pm - 6am
\n' - html += '
- MIN|MAX: min & max temp for 24 hrs (6am to 6am) starting on the forecast date
\n' - html += '
- Questions? Comments? Suggestions? See email link below.
\n' - html += '
\n' + html += '

\nHover over table cells for more data.\n

\n' + html += '

\nKey:\n

\n' + html += '
    \n
  • GREEN = Shred on!
  • \n
  • YELLOW = Meh
  • \n
  • RED = Don't Bother!
  • \n
\n' + html += '

\nAbbreviations:\n

\n' + html += '
    \n
  • MIX: Rain/Snow mixture; forecast snowfall amount reported
  • \n
  • Trace ≤ 0.1 in forecast precipitation
  • \n
  • SLVL: Snow level; min & max for 24 hours (6am–6am) starting on the forecast date
  • \n
  • AM|PM|ON: avg temp, morning = 6am–12pm | afternoon = 12pm–6pm | overnight = 6pm–6am
  • \n
  • MIN|MAX: min & max temp for 24 hours (6am–6am) starting on the forecast date
  • \n
\n' + html += '

\nRead the docs.\n

\n' + html += '

\nData compiled from NOAA.\n

\n' + html += '

\nQuestions? Comments? Suggestions? Send an email.\n

\n' html += '