142 lines
3.5 KiB
Java
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 ≤ day ≤ 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();
|
|
}
|
|
}
|