A Code Institute Project (PP3). Visit the live site here.
Contents
User: The Oxford Weather Data Comparison Tool allows users to compare monthly weather data (sun hours, rainfall, minimum and maximum temperatures) for Oxford for the years 1950 and 2022. Users can also input and delete weather data for the year 2024. The site is for users who are interested in comparing weather data, such as students and researchers who want insights from weather data for these years and who want to add to the data for 2024.
Site Owner: The application provides data for 1950 and 2022 and allows the user to compare data. The application also allows users to input and delete new data for 2024.
This weather data was extracted from the Met Office UK database.
This project is a command-line application, deployed via Heroku, that allows users to manage and research a weather dataset. The data is retrieved from a linked Google Sheet.
Below are the core functions and dependencies I incorporated into the site.
From my personal Google account, I created a Google Sheet and called it oxford_weather_data. I populated three worksheets. The first was a worksheet for 1950 data, the second for 2022 data and the third for the user to input or delete data for the current year (2024). I used data for this project from the Met Office station data for Oxford (link in the credits below). The data for 1950 and 2022 cannot be modified and can only be used for research purposes. The 2024 sheet however, allows the user to add and delete data as appropriate. More information on the code functions can be found below.
Linking the Google Sheet I followed the Code Institute "Love Sandwiches" tutorial to ensure my Google Sheet was linked up to my project correctly:
- I created a new project and called it oxford_weather_data.
- I selected API and services and then library to access the correct APIs.
- I first set up Googe Drive and clicked 'enable'. I generated some credentials by clicking 'create credentials'. I selected Google Drive API and the seeting 'application data'. I then created a service account name and selected 'JSON for the key type' and 'Editor' for my role. I saved the downloaded JSON file to my computer for the later stage.
- To link up my Google Sheets API to my GitHub project I first looked for the Googlesheets API and clicked 'enable'.
- In my Code Institute template, I dragged the JSON file into my workspace and renamed it creds.json.
- In the JSON file I copied the client email value and went back to my Google sheet and clicked the 'share' button. I then pasted the client email into the share box and selected 'Editor' and unticked 'notify people' and then clicked share.
- I then added the creds.JSON to the git ignore file to allow this information to be kept secure.
- I checked the file wasn't present when I went to commit the initial project to GitHub by checking via git status before pushing to GitHub.
Setting up the development workspace
Within the run.py file, I used two dependencies: google-auth and the gspread library. Again, I followed the 'Love Sandwiches' tutorial to ensure I set this up correctly.
-
I installed both of them into my workspace via the terminal using pip3 install. gspread google-auth.
-
The second stage was to add the nexessary code to the header of my .py script:
import gspread from google.oauth2.service_account import Credentials Plus I set the scope (using capitals as this is a constant variable): SCOPE = [ "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive" ]
-
I then create constant variables for the CREDS, SCOPED CREDS, then created the GSPREAD client and SHEET to allow access (making sure the sheet name matched the Google Sheet name): CREDS = Credentials.from_service_account_file('creds.json') SCOPED_CREDS = CREDS.with_scopes(SCOPE) GSPREAD_CLIENT = gspread.authorize(SCOPED_CREDS) SHEET = GSPREAD_CLIENT.open('oxford_weather_data')
-
Finally I added test data to see if the sheet was connected.
The application includes a number of functions outlined below:
-
display_menu() Purpose: Displays the menu options for the user to choose from. Returns: The user's choice as a string, stripped of any leading or trailing whitespace.
-
get_month_input() Purpose: Prompts the user to input a month number and validates the input, allowing one retry attempt. Returns: The validated month number as an integer or None if invalid input is provided after two attempts.
-
fetch_data(month, column) Purpose: Fetches weather data from the spreadsheet for a given month and column. Parameters: month: The month number (1-12). column: The column number from which to fetch data. Returns: A tuple containing the data for the specified month from 1950 and 2022 as integers, or None if the data is invalid.
-
compare_data(data_type, column) Purpose: Compares weather data (e.g., sun hours, rainfall, maximum temperature, minimum temperature) between 1950 and 2022 for a specified month. Parameters: data_type: A string describing the type of data being compared. column: The column number from which to fetch the data. Behaviour: Prompts the user for a month, fetches the corresponding data, and prints a comparison between the years 1950 and 2022.
-
input_or_delete_data() Purpose: Allows the user to choose whether to input new weather data or delete existing data for a specified month, with one retry attempt. Behaviour: Prompts the user to choose an option (input or delete), validates the choice, and then calls the corresponding function to handle the data.
-
input_weather_data(month) Purpose: Inputs new weather data for the year 2024 for a specified month, with one retry attempt. Parameters: month: The month number (1-12) for which data is to be inputted. Behaviour: Prompts the user for new data values (sun hours, minimum temperature, maximum temperature, rainfall), validates the input, and updates the spreadsheet.
-
delete_weather_data(month) Purpose: Deletes existing weather data for the year 2024 for a specified month, with one retry attempt. Parameters: month: The month number (1-12) for which data is to be deleted. Behaviour: Prompts the user to confirm data deletion, validates the input, and clears the data from the spreadsheet if confirmed.
-
main() Purpose: Main menu function for the user to choose from a list of options. Behaviour: Continuously displays the main menu, takes the user's choice, and calls the appropriate function to handle the request. Validates the user's choice and prompts for re-entry if invalid.
After writing my functions, I decided I could refactor the compare data function. However, this has caused an issue with the generated responses which don't always read in the correct grammar. For example "More -maximum temperature- in 2022" isn't the correct grammar, although it works for "More sun hours" and "More rainfall". See testing below.
I deployed the site via Heroku. These are the steps I followed, using the Code Institute 'Love Sandwiches" project to guide me.
- Within the Heroku dashboard I created a new app and called it Oxford-Weather-Data.
- I selected my region and created the app.
- I went to the settings tab and entered my environment variables (config vars). This included the CREDS.json file and the PORT with the value of 8000.
- I then added two build pack dependencies in this order: Python and NodeJs.
- I then went to the deploy section and selected GitHub. I searched for my GitHub repository and clicked connect to link up my code.
- I decided to manually deploy my app via deploy branch and successfully deployed it.
- I tested it using two browsers, Chrome and Firefox, both of which worked as expected.
Test Summary | Resolved? | Action Taken |
---|---|---|
Debugging | ||
Improve user experience. Function: delete_weather_data. Issue: If exiting the menu and 'yes' or 'no' isn't typed exactly, the user is thrown out of the loop and back to the main menu. | Y | Add a while loop to allow user two attempts before defaulting to the main menu. |
Retrieving data with no cell value. Function: compare data. Issue: If the data returns none it specifies an error | Y | Added to function to allow none to be displayed |
Issue: 2024 sheet : You can overwrite data without a warning | Y | Added in an option for the user to respond y or n to the warning that data was about to be overriden. |
Issue: Input or delete data function leaves loop if invalid month number is added and returns to main screen | Y | Added in the number of attempts the user is given to allow a second chance before returning to the main menu. |
Issue: Error when whitespace was added before user input | Y | Added .strip to inputs to avoid errors and improve user experience |
Issue: Compare data function was refactored and uses generic message '"More {data_type} in (year) however this doesn't read well for maximum and minimum temperatures | N | Future Fix to modify general function to allow 'Hotter' and "Cooler'. |
Issue: Input data for 2024 or delete existing data accepts an invalid entry which isn't 1 or 2 | Y | Added a loop which only accepts 1 or 2 as an input |
Testing | ||
Testing: compare sun hours | Y | The sun hours reflect the data accurately |
Testing: compare rainfall | Y | The rainfall data is correct |
Testing: compare maximum temperature | Y | The maximum temperature result is correct |
Testing: compare minimum temperature | Y | The minimum temperature result is correct but the 'More minimum temperature' as a response needs to be amended to 'hotter in'to make sense to the user |
Testing: input weather data via over write | Y | When over writing data the response asks the user to check if they want to overwrite, when overwritten the data is added to the Google Sheet |
Testing: input new weather data | Y | The data is added successfully to the Google Sheet for 2024 |
Testing: delete existing data | Y | The user is prompted to delete the data and the Google Sheet is successfully updated with data removed |
Testing: delete existing data from an empty month | N | The script still runs through the steps and says data successfully deleted when no data is present, however this doesn't impact on the user |
Testing: entering invalid integer and trailing whitespace into the main menu | Y | The script responds with invalid choice and returns to the menu |
Testing: entering random letters into the main menu | Y | Invalid choice is printed and the user returns to the main menu |
Testing: entering invalid numbers multiple times into the sun hours choice | Y | Returns to main menu after 2 failed attempts |
Testing: adding or deleting data in 2024 after the current month | Y | The user is blocked from entering or deleting future data and asked to enter between 1 - the current month |
The site could be expanded into a list of locations across the U.K and the years could also be expanded across a wider range. Functionality:
- The user data for 2024 could become immutable after a certain time limit had passed.
- Data could be added to historical dates if new data was discovered or more columns needed to be added.
- The user could see the results of their input in the command line after entry.
- The user could export data via PDF for example.
- A future fix to tell the user that there is no data present when the user tries to delete empty fields in 2024.
W3 Schools (Python Date Time) Link
Code Institute - Love Sandwiches project.
Replit 100 days of Python tutorials: Link
My mentor Spencer Bariball for his continued support and expertise.
The Met Office Oxford Weather Station data: Link