weather-aggregator/src/main/java/eirb/pg203/OpenWeatherMap.java
2024-11-24 13:12:17 +01:00

142 lines
3.5 KiB
Java

package eirb.pg203;
import org.json.JSONObject;
import org.json.JSONArray;
import eirb.pg203.utils.JSONFetcher;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.time.Clock;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Locale;
import eirb.pg203.WeatherData.Condition;
/**
* OpenWeatherMap api implementation
*/
public class OpenWeatherMap implements WeatherDataAPI {
private static final String forecastBaseURL = "https://api.openweathermap.org/data/2.5/forecast";
private String APIKey;
Clock clock = Clock.systemUTC();
JSONFetcher JSONFetcher = new JSONFetcher();
OpenWeatherMap(String APIKey) {
this.APIKey = APIKey;
}
private JSONObject fetchWeather(City city) throws IOException {
URL url = URI.create(
String.format(Locale.ENGLISH, forecastBaseURL + "?appid=%s&lat=%.2f&lon=%.2f&units=metric",
APIKey,
city.getCityCoords().getLat(),
city.getCityCoords().getLon()
)
).toURL();
return JSONFetcher.fetch(url);
}
private WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
JSONArray list = response.getJSONArray("list");
DayOfWeek targetedDay = Instant.now(clock).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(clock).plusSeconds(day * 24 * 3600),
temp_c,
windSpeed,
windDirection,
condition
);
}
/**
* @param day Day, 0 &leq; day &leq; 14
*/
@Override
public WeatherData getTemperature(int day, String city) throws IOException {
JSONObject result = fetchWeather(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(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 "OpenWeatherMap";
}
@Override
public String toString() {
return this.getAPIName();
}
}