feat: use WeatherData instead of Temperature
This commit is contained in:
parent
5fe57da57e
commit
34928424ca
@ -15,6 +15,7 @@ public class Main {
|
||||
display.addAPI(openMeteo);
|
||||
display.addAPI(openWeatherMap);
|
||||
|
||||
display.display(5, "Bordeaux");
|
||||
// weatherAPI can't fetch for more than 3 days with free plan
|
||||
display.display(3, "Bordeaux");
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,18 @@ import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import eirb.pg203.WeatherData.Condition;
|
||||
|
||||
// https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&hourly=temperature_2m
|
||||
|
||||
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";
|
||||
|
||||
// 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(forecastBaseURL + "?latitude=%.2f&longitude=%.2f&forecast_days=%d&daily=apparent_temperature_min,apparent_temperature_max",
|
||||
String.format(forecastBaseURL + "?latitude=%.2f&longitude=%.2f&forecast_days=%d&daily=" + dailyQuery,
|
||||
city.getCityCoords().getLat(),
|
||||
city.getCityCoords().getLon(),
|
||||
days
|
||||
@ -27,33 +30,65 @@ public class OpenMeteo implements WeatherDataAPI {
|
||||
return JSONFetcher.fetch(url);
|
||||
}
|
||||
|
||||
private static Condition getConditionFromCode(int WMOCode) {
|
||||
if (WMOCode < 20)
|
||||
return Condition.SUNNY;
|
||||
else if (WMOCode < 30)
|
||||
return Condition.RAINY;
|
||||
else if (WMOCode < 50)
|
||||
return Condition.CLOUDY;
|
||||
else
|
||||
return Condition.RAINY;
|
||||
}
|
||||
|
||||
|
||||
private static 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(),
|
||||
temp_c,
|
||||
windSpeed,
|
||||
windDirection,
|
||||
getConditionFromCode(conditionCode)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param day Day, 0 ≤ day ≤ 14
|
||||
*/
|
||||
@Override
|
||||
public Temperature getTemperature(int day, String city) throws IOException {
|
||||
public WeatherData getTemperature(int day, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(day + 1, new City(city));
|
||||
JSONObject daily = result.getJSONObject("daily");
|
||||
float temp_c = (daily.getJSONArray("apparent_temperature_max").getFloat(0) + daily.getJSONArray("apparent_temperature_min").getFloat(0)) / 2;
|
||||
|
||||
return new Temperature(temp_c, new City(city), Instant.now());
|
||||
return getWeatherDataFromForecast(result, day, city);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Temperature getTemperature(int day, int hour, String city) throws IOException{
|
||||
public WeatherData getTemperature(int day, int hour, String city) throws IOException{
|
||||
return getTemperature(day, city);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Temperature> getTemperatures(int days, String city) throws IOException {
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(days, new City(city));
|
||||
ArrayList<Temperature> temperatures = new ArrayList<>();
|
||||
JSONObject daily = result.getJSONObject("daily");
|
||||
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
||||
|
||||
for (int day = 0; day < days; ++day) {
|
||||
float temp_c = (daily.getJSONArray("apparent_temperature_max").getFloat(day) + daily.getJSONArray("apparent_temperature_min").getFloat(day)) / 2;
|
||||
temperatures.add(new Temperature(temp_c, new City(city), Instant.now()));
|
||||
weatherDatas.add(
|
||||
getWeatherDataFromForecast(result, day, city)
|
||||
);
|
||||
}
|
||||
return temperatures;
|
||||
|
||||
return weatherDatas;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -12,6 +12,7 @@ import java.time.DayOfWeek;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import eirb.pg203.WeatherData.Condition;
|
||||
|
||||
// https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&hourly=temperature_2m
|
||||
|
||||
@ -36,43 +37,91 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
||||
return JSONFetcher.fetch(url);
|
||||
}
|
||||
|
||||
private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
|
||||
JSONArray list = response.getJSONArray("list");
|
||||
|
||||
DayOfWeek targetedDay = Instant.now().plusSeconds(day * 24 * 3600).atZone(ZoneId.systemDefault()).getDayOfWeek();
|
||||
DayOfWeek dayOfWeek;
|
||||
int dataCount = 0;
|
||||
float temp_c = 0;
|
||||
float windSpeed = 0;
|
||||
float windDirection = 0;
|
||||
float pop = 0; // probability of precipitation
|
||||
float cloudiness = 0; // percent
|
||||
|
||||
for (int i = 0 ; i < list.length() ; ++i)
|
||||
{
|
||||
JSONObject data = list.getJSONObject(i);
|
||||
int timestamp = data.getInt("dt");
|
||||
dayOfWeek = Instant.ofEpochSecond(timestamp).atZone(ZoneId.systemDefault()).getDayOfWeek();
|
||||
|
||||
if (dayOfWeek == targetedDay)
|
||||
{
|
||||
temp_c += data.getJSONObject("main").getFloat("temp");
|
||||
windSpeed += data.getJSONObject("wind").getFloat("speed");
|
||||
windDirection += data.getJSONObject("wind").getFloat("deg");
|
||||
cloudiness += data.getJSONObject("clouds").getFloat("all");
|
||||
pop += data.getFloat("pop");
|
||||
dataCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataCount != 0)
|
||||
{
|
||||
temp_c /= dataCount;
|
||||
windSpeed /= dataCount;
|
||||
windDirection /= dataCount;
|
||||
pop /= dataCount;
|
||||
cloudiness /= dataCount;
|
||||
}
|
||||
|
||||
Condition condition = Condition.SUNNY;
|
||||
if (pop > 50)
|
||||
condition = Condition.RAINY;
|
||||
else if (cloudiness > 75)
|
||||
condition = Condition.CLOUDY;
|
||||
else if (cloudiness > 25)
|
||||
condition = Condition.PARTIAL;
|
||||
|
||||
|
||||
return new WeatherData(
|
||||
new City(city),
|
||||
Instant.now().plusSeconds(day * 24 * 3600),
|
||||
temp_c,
|
||||
windSpeed,
|
||||
windDirection,
|
||||
condition
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param day Day, 0 ≤ day ≤ 14
|
||||
*/
|
||||
@Override
|
||||
public Temperature getTemperature(int day, String city) throws IOException {
|
||||
public WeatherData getTemperature(int day, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(day+1, new City(city));
|
||||
JSONArray list = result.getJSONArray("list");
|
||||
float temp_c = list.getJSONObject(0).getJSONObject("main").getFloat("temp");
|
||||
|
||||
return new Temperature(temp_c, new City(city), Instant.now());
|
||||
return getWeatherDataFromForecast(result, day, city);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Temperature getTemperature(int day, int hour, String city) throws IOException{
|
||||
public WeatherData getTemperature(int day, int hour, String city) throws IOException{
|
||||
return getTemperature(day, city);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Temperature> getTemperatures(int days, String city) throws IOException {
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(days, new City(city));
|
||||
JSONArray list = result.getJSONArray("list");
|
||||
|
||||
ArrayList<Temperature> temperatures = new ArrayList<>();
|
||||
int cnt = result.getInt("cnt");
|
||||
DayOfWeek day = Instant.now().atZone(ZoneId.systemDefault()).getDayOfWeek();
|
||||
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
JSONObject data = list.getJSONObject(i);
|
||||
int timestamp = data.getInt("dt");
|
||||
|
||||
if (day == Instant.ofEpochSecond(timestamp).atZone(ZoneId.systemDefault()).getDayOfWeek())
|
||||
{
|
||||
float temp_c = data.getJSONObject("main").getFloat("temp");
|
||||
temperatures.add(new Temperature(temp_c, new City(city), Instant.now()));
|
||||
for (int day = 0; day < days ; ++day) {
|
||||
weatherDatas.add(
|
||||
getWeatherDataFromForecast(result, day, city)
|
||||
);
|
||||
}
|
||||
}
|
||||
return temperatures;
|
||||
|
||||
return weatherDatas;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,7 @@ package eirb.pg203;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import eirb.pg203.WeatherData.Condition;
|
||||
import eirb.pg203.utils.JSONFetcher;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -31,33 +32,73 @@ public class WeatherAPI implements WeatherDataAPI{
|
||||
return JSONFetcher.fetch(url);
|
||||
}
|
||||
|
||||
private static WeatherData.Condition getConditionFromString(String str) {
|
||||
if (str.toLowerCase().contains("rain"))
|
||||
return Condition.RAINY;
|
||||
|
||||
else if (str.toLowerCase().contains("partly"))
|
||||
return Condition.PARTIAL;
|
||||
|
||||
else if (str.toLowerCase().contains("cloud"))
|
||||
return Condition.CLOUDY;
|
||||
|
||||
return Condition.SUNNY;
|
||||
}
|
||||
|
||||
private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
|
||||
JSONObject forecastDay = response.getJSONObject("forecast").getJSONArray("forecastday").getJSONObject(day);
|
||||
JSONArray forecastHour = forecastDay.getJSONArray("hour");
|
||||
float temp_c = forecastDay.getJSONObject("day").getFloat("avgtemp_c");
|
||||
|
||||
// Calculates the mean for the day
|
||||
float windSpeed = 0;
|
||||
float windDirection = 0;
|
||||
for (int i = 0 ; i < forecastHour.length() ; ++i)
|
||||
{
|
||||
windSpeed += forecastHour.getJSONObject(i).getFloat("wind_kph");
|
||||
windDirection += forecastHour.getJSONObject(i).getFloat("wind_degree");
|
||||
}
|
||||
windSpeed /= forecastHour.length();
|
||||
windDirection /= forecastHour.length();
|
||||
|
||||
String conditionStr = forecastDay.getJSONObject("day").getJSONObject("condition").getString("text");
|
||||
|
||||
return new WeatherData(
|
||||
new City(city),
|
||||
Instant.now(),
|
||||
temp_c,
|
||||
windSpeed,
|
||||
windDirection,
|
||||
getConditionFromString(conditionStr)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param day Day, 0 ≤ day ≤ 14
|
||||
*/
|
||||
@Override
|
||||
public Temperature getTemperature(int day, String city) throws IOException {
|
||||
public WeatherData getTemperature(int day, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(day+1, city);
|
||||
JSONArray forecast = result.getJSONObject("forecast").getJSONArray("forecastday");
|
||||
float temp_c = forecast.getJSONObject(day).getJSONObject("day").getFloat("avgtemp_c");
|
||||
|
||||
return new Temperature(temp_c, new City(city), Instant.now());
|
||||
return getWeatherDataFromForecast(result, day, city);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Temperature getTemperature(int day, int hour, String city) throws IOException{
|
||||
public WeatherData getTemperature(int day, int hour, String city) throws IOException{
|
||||
return getTemperature(day, city);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Temperature> getTemperatures(int days, String city) throws IOException {
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(days, city);
|
||||
ArrayList<Temperature> temperatures = new ArrayList<>();
|
||||
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
||||
|
||||
for (int day = 0; day < days; ++day) {
|
||||
JSONArray forecast = result.getJSONObject("forecast").getJSONArray("forecastday");
|
||||
float temp_c = forecast.getJSONObject(day).getJSONObject("day").getFloat("avgtemp_c");
|
||||
temperatures.add(new Temperature(temp_c, new City(city), Instant.now()));
|
||||
weatherDatas.add(
|
||||
getWeatherDataFromForecast(result, day, city)
|
||||
);
|
||||
}
|
||||
return temperatures;
|
||||
|
||||
return weatherDatas;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
96
src/main/java/eirb/pg203/WeatherData.java
Normal file
96
src/main/java/eirb/pg203/WeatherData.java
Normal file
@ -0,0 +1,96 @@
|
||||
package eirb.pg203;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
|
||||
class WeatherData {
|
||||
enum Condition {
|
||||
SUNNY("☀️"),
|
||||
PARTIAL("🌤"),
|
||||
CLOUDY("☁️"),
|
||||
RAINY("🌧"),
|
||||
ERROR("E");
|
||||
|
||||
private String desc;
|
||||
Condition(String desc) { this.desc = desc; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.desc;
|
||||
}
|
||||
}
|
||||
|
||||
private City city;
|
||||
private Instant date;
|
||||
private float temp;
|
||||
private Condition condition; // cloudly, sunny ...
|
||||
private float windSpeed;
|
||||
private float windDirection;
|
||||
|
||||
WeatherData(City city, Instant date, float temp, float windSpeed, float windDirection, Condition condition) {
|
||||
this.city = city;
|
||||
this.date = date;
|
||||
this.temp = temp;
|
||||
this.condition = condition;
|
||||
this.windSpeed = windSpeed;
|
||||
this.windDirection = windDirection;
|
||||
}
|
||||
|
||||
public City getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public Instant getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public Condition getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public float getTemp() {
|
||||
return temp;
|
||||
}
|
||||
|
||||
public float getWindSpeed() {
|
||||
return windSpeed;
|
||||
}
|
||||
|
||||
public float getWindDirection() {
|
||||
return windDirection;
|
||||
}
|
||||
|
||||
public void setCity(City city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public void setDate(Instant date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public void setCondition(Condition condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public void setTemp(float temp) {
|
||||
this.temp = temp;
|
||||
}
|
||||
|
||||
public void setWindSpeed(float windSpeed) {
|
||||
this.windSpeed = windSpeed;
|
||||
}
|
||||
|
||||
public void setWindDirection(float windDirection) {
|
||||
this.windDirection = windDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%05.2f° %s %05.2fkm/h %06.2f°",
|
||||
this.getTemp(),
|
||||
this.getCondition().toString(),
|
||||
this.getWindSpeed(),
|
||||
this.getWindDirection()
|
||||
);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ public interface WeatherDataAPI {
|
||||
* @return Temperature of the day from the city
|
||||
* @throws IOException when request failed
|
||||
*/
|
||||
Temperature getTemperature(int day, String city) throws IOException;
|
||||
WeatherData getTemperature(int day, String city) throws IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -22,9 +22,9 @@ public interface WeatherDataAPI {
|
||||
* @return Temperature of the day for a hour from the city
|
||||
* @throws IOException when request failed
|
||||
*/
|
||||
Temperature getTemperature(int day, int hour, String city) throws IOException;
|
||||
WeatherData getTemperature(int day, int hour, String city) throws IOException;
|
||||
|
||||
ArrayList<Temperature> getTemperatures(int days, String city) throws IOException;
|
||||
ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException;
|
||||
|
||||
/***
|
||||
* Name of the API
|
||||
|
@ -21,29 +21,28 @@ class WeatherDisplayBasic implements WeatherDisplay {
|
||||
System.err.println(line);
|
||||
}
|
||||
|
||||
private void displayTemperatures(String ApiName, ArrayList<Temperature> temperatures) {
|
||||
private void displayWeatherDatas(String ApiName, ArrayList<WeatherData> weatherDatas) {
|
||||
StringBuilder line = new StringBuilder();
|
||||
line.append(ApiName);
|
||||
|
||||
for (Temperature temp: temperatures) {
|
||||
for (WeatherData weatherData: weatherDatas) {
|
||||
line.append('\t')
|
||||
.append(temp.getTemp());
|
||||
.append(weatherData.toString());
|
||||
}
|
||||
|
||||
System.err.println(line);
|
||||
}
|
||||
|
||||
public void display(int days, String city) {
|
||||
ArrayList<Temperature> temperatures;
|
||||
ArrayList<WeatherData> weatherDatas;
|
||||
displayHeader(days);
|
||||
|
||||
for (WeatherDataAPI w: apis) {
|
||||
try {
|
||||
temperatures = w.getTemperatures(days, city);
|
||||
displayTemperatures(w.getAPIName(), temperatures);
|
||||
weatherDatas = w.getTemperatures(days, city);
|
||||
displayWeatherDatas(w.getAPIName(), weatherDatas);
|
||||
} catch (Exception e) {
|
||||
System.err.println(e);
|
||||
System.err.println("ntm++ martin");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user