Martin Eyben 5dfed9ff4c fix: typo
2024-11-27 20:28:34 +00:00

123 lines
3.5 KiB
Java

package eirb.pg203;
import org.json.JSONObject;
import eirb.pg203.utils.JSONFetcher;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.time.Clock;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Locale;
import eirb.pg203.WeatherData.Condition;
// https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&hourly=temperature_2m
/**
* OpenMeteo implementation
*/
public class OpenMeteo implements WeatherDataAPI {
private static final String forecastBaseURL = "https://api.open-meteo.com/v1/forecast";
private static final String dailyQuery = "weather_code,temperature_2m_max,temperature_2m_min,wind_speed_10m_max,wind_direction_10m_dominant";
JSONFetcher JSONFetcher = new JSONFetcher();
Clock clock = Clock.systemUTC();
/**
* Default constructor
*/
public OpenMeteo() {}
// https://www.nodc.noaa.gov/archive/arc0021/0002199/1.1/data/0-data/HTML/WMO-CODE/WMO4677.HTM
private JSONObject fetchWeather(int days, City city) throws IOException {
URL url = URI.create(
String.format(Locale.ENGLISH, forecastBaseURL + "?latitude=%.2f&longitude=%.2f&forecast_days=%d&daily=" + dailyQuery,
city.getCityCoords().getLat(),
city.getCityCoords().getLon(),
days
)
).toURL();
return JSONFetcher.fetch(url);
}
/**
* return condition based on the WMOCode
* table can be found here : https://open-meteo.com/en/docs (at the end)
* @param WMOCode id code
* @return weather condition
*/
private static Condition getConditionFromCode(int WMOCode) {
return switch (WMOCode) {
case 0, 1 -> Condition.SUNNY;
case 2 -> Condition.PARTIAL;
case 3 -> Condition.CLOUDY;
case 61, 63, 65, 80, 81, 82 -> Condition.RAINY;
default -> Condition.ERROR;
};
}
private WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
JSONObject daily = response.getJSONObject("daily");
float max_temp = daily.getJSONArray("temperature_2m_max").getFloat(day);
float min_temp = daily.getJSONArray("temperature_2m_min").getFloat(day);
float temp_c = (min_temp + max_temp) / 2;
float windSpeed = daily.getJSONArray("wind_speed_10m_max").getFloat(day);
float windDirection = daily.getJSONArray("wind_direction_10m_dominant").getFloat(day);
int conditionCode = daily.getJSONArray("weather_code").getInt(day);
return new WeatherData(
new City(city),
Instant.now(clock),
temp_c,
windSpeed,
windDirection,
getConditionFromCode(conditionCode)
);
}
/**
* @param day Day, 0 ≤ day ≤ 14
*/
@Override
public WeatherData getTemperature(int day, String city) throws IOException {
JSONObject result = fetchWeather(day + 1, new City(city));
return getWeatherDataFromForecast(result, day, city);
}
@Override
public WeatherData getTemperature(int day, int hour, String city) throws IOException{
return getTemperature(day, city);
}
@Override
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
JSONObject result = fetchWeather(days, new City(city));
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
for (int day = 0; day < days; ++day) {
weatherDatas.add(
getWeatherDataFromForecast(result, day, city)
);
}
return weatherDatas;
}
@Override
public String getAPIName() {
return "OpenMeteo";
}
@Override
public String toString() {
return this.getAPIName();
}
}