commit exercice
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Python venv folder
|
||||
.venv/*
|
||||
utils/__pycache__/weather.cpython-311.pyc
|
||||
71
README.md
Normal file
71
README.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Weather API
|
||||
|
||||
## Context
|
||||
|
||||
As part of an exercise, the idea is to be able to retrieve information via [open-meteo](https://open-meteo.com/en/docs).
|
||||
The statement is as follows:
|
||||
|
||||
### First part
|
||||
|
||||
**Endpoint :** <https://open-meteo.com/en/docs#hourly=temperature_2m>
|
||||
|
||||
- **Objective:** Develop an endpoint that returns the average temperature over a specified period.
|
||||
- **Request:** `GET /temperature?x=[X]&y=[Y]&prevision_jours=[prevision_jours]`
|
||||
- **Parameters:** X and Y represent GPS coordinates.
|
||||
|
||||
**Expected output:**
|
||||
|
||||
```json
|
||||
Temperature: {
|
||||
"average_temperature": [Calculated average value]
|
||||
}
|
||||
```
|
||||
|
||||
### Second part
|
||||
|
||||
**Endpoint:** <https://open-meteo.com/en/docs#hourly=precipitation_probability>
|
||||
|
||||
- **Objective:** Create an endpoint that indicates, for the next 2 days, the time slots when it's advisable to go out with an umbrella, based on the probability of precipitation.
|
||||
- **Request:** `GET /umbrella?x=[X]&y=[Y]`
|
||||
- **Parameters:** X and Y represent GPS coordinates.
|
||||
- **How it works:** If precipitation_probability is greater than 50%, these hours are marked as requiring an umbrella.
|
||||
|
||||
**Expected output:**
|
||||
|
||||
```json
|
||||
{
|
||||
"sort_ton_parapluie": [List of time slots]
|
||||
}
|
||||
```
|
||||
|
||||
## Install and execution
|
||||
|
||||
```bash
|
||||
git clone https://github.com/MasqAs/weather-api.git
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requerements.txt
|
||||
python3 api.py
|
||||
```
|
||||
|
||||
To call API endpoint :
|
||||
|
||||
```bash
|
||||
❯ curl -X GET 'http://127.0.0.1:5000/temperature?x=52.12&y=13.4&prevision_jours=3'
|
||||
{
|
||||
"Temperature": {
|
||||
"temperature_moyenne": [
|
||||
7.68
|
||||
]
|
||||
}
|
||||
|
||||
curl -X GET 'http://127.0.0.1:5000/parapluie?x=52.12&y=13.4&prevision_jours=3'
|
||||
{
|
||||
"sort_ton_parapluie": []
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Debt
|
||||
|
||||
- Handle "," as the decimal separator
|
||||
- Add logs
|
||||
50
api.py
Normal file
50
api.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import utils.weather as weather
|
||||
from flask import Flask, jsonify, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/temperature", methods=["GET"])
|
||||
def temperature():
|
||||
# Extract query parameters
|
||||
latitude = request.args.get("x", type=float)
|
||||
longitude = request.args.get("y", type=float)
|
||||
forecast_days = request.args.get("prevision_jours", type=int)
|
||||
|
||||
# Ensure all parameters are provided
|
||||
if latitude is None or longitude is None or forecast_days is None:
|
||||
return jsonify({"error": "Missing parameters"}), 400
|
||||
|
||||
# Call the weather_average function with the parameters
|
||||
try:
|
||||
average_temperature = weather.weather_average(latitude, longitude, forecast_days)
|
||||
# Updated response format as per the requirement
|
||||
return jsonify({"Temperature": {"temperature_moyenne": [average_temperature]}})
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
|
||||
@app.route("/parapluie", methods=["GET"])
|
||||
def parapluie():
|
||||
# Extract query parameters for latitude and longitude
|
||||
latitude = request.args.get("x", type=float)
|
||||
longitude = request.args.get("y", type=float)
|
||||
|
||||
# Ensure both parameters are provided
|
||||
if latitude is None or longitude is None:
|
||||
return jsonify({"error": "Missing parameters"}), 400
|
||||
|
||||
# The forecast is fixed to 2
|
||||
forecast_days = 2
|
||||
|
||||
# Call the need_umbrella function with the parameters
|
||||
try:
|
||||
times_list = weather.need_umbrella(latitude, longitude, forecast_days)
|
||||
# Format the response as specified
|
||||
return jsonify({"sort_ton_parapluie": times_list})
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
||||
2
requierement.txt
Normal file
2
requierement.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Flask==3.0.2
|
||||
httpx==0.27.0
|
||||
0
utils/__init.py__
Normal file
0
utils/__init.py__
Normal file
55
utils/weather.py
Normal file
55
utils/weather.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import httpx
|
||||
|
||||
OPEN_METEO_URL = "https://api.open-meteo.com/v1/forecast"
|
||||
HOURLY = "temperature_2m"
|
||||
|
||||
|
||||
def weather_average(latitude: float, longitude: float, forecast: int) -> float:
|
||||
|
||||
params = {"latitude": latitude, "longitude": longitude, "hourly": "temperature_2m", "forecast_days": forecast}
|
||||
|
||||
# Using httpx to make the GET request
|
||||
with httpx.Client() as client:
|
||||
response = client.get(OPEN_METEO_URL, params=params)
|
||||
|
||||
# Check if the response status code is 200
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
else:
|
||||
# Handle non-200 responses appropriately
|
||||
response.raise_for_status()
|
||||
|
||||
# Extracting the temperature data
|
||||
weather_data = data["hourly"]["temperature_2m"]
|
||||
|
||||
# Calculating the average temperature
|
||||
average_data = round((sum(weather_data) / len(weather_data)), 2)
|
||||
|
||||
return average_data
|
||||
|
||||
|
||||
def need_umbrella(latitude: float, longitude: float, forecast: int) -> list:
|
||||
|
||||
params = {"latitude": latitude, "longitude": longitude, "hourly": "precipitation_probability", "forecast_days": forecast}
|
||||
|
||||
# Using httpx to make the GET request
|
||||
with httpx.Client() as client:
|
||||
response = client.get(OPEN_METEO_URL, params=params)
|
||||
|
||||
# Check if the response status code is 200
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
else:
|
||||
# Handle non-200 responses appropriately
|
||||
response.raise_for_status()
|
||||
|
||||
# Extracting time and precipitation probability data
|
||||
times = data["hourly"]["time"]
|
||||
precipitation_probabilities = data["hourly"]["precipitation_probability"]
|
||||
|
||||
# Filtering times where precipitation probability is >= 50
|
||||
times_with_high_precipitation = [
|
||||
times[i] for i, probability in enumerate(precipitation_probabilities) if probability >= 50
|
||||
]
|
||||
|
||||
return times_with_high_precipitation
|
||||
Reference in New Issue
Block a user