From 66b0b821f602b5620a1873556e9eaa03c371e165 Mon Sep 17 00:00:00 2001 From: amorozov Date: Wed, 21 May 2025 16:53:21 +0300 Subject: [PATCH] feature: added openweathermap weather provider --- build.gradle | 1 + src/main/java/ru/dima/weather/WeatherApp.java | 10 +++- .../weather/{ => city}/CityByIpResolver.java | 6 +- .../weather/{ => http}/HttpRequester.java | 2 +- .../provider/MultiDaysWeatherInfo.java | 15 +++++ .../OpenWeatherMapWeatherProvider.java | 59 +++++++++++++++++++ .../ru/dima/weather/provider/WeatherInfo.java | 16 +++++ .../weather/provider/WeatherProvider.java | 6 ++ 8 files changed, 111 insertions(+), 4 deletions(-) rename src/main/java/ru/dima/weather/{ => city}/CityByIpResolver.java (65%) rename src/main/java/ru/dima/weather/{ => http}/HttpRequester.java (94%) create mode 100644 src/main/java/ru/dima/weather/provider/MultiDaysWeatherInfo.java create mode 100644 src/main/java/ru/dima/weather/provider/OpenWeatherMapWeatherProvider.java create mode 100644 src/main/java/ru/dima/weather/provider/WeatherInfo.java create mode 100644 src/main/java/ru/dima/weather/provider/WeatherProvider.java diff --git a/build.gradle b/build.gradle index de77e4d..9892fca 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ repositories { dependencies { testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' + implementation 'org.json:json:20250517' } test { diff --git a/src/main/java/ru/dima/weather/WeatherApp.java b/src/main/java/ru/dima/weather/WeatherApp.java index 1f788b9..815e388 100644 --- a/src/main/java/ru/dima/weather/WeatherApp.java +++ b/src/main/java/ru/dima/weather/WeatherApp.java @@ -1,5 +1,9 @@ package ru.dima.weather; +import ru.dima.weather.city.CityByIpResolver; +import ru.dima.weather.http.HttpRequester; +import ru.dima.weather.provider.OpenWeatherMapWeatherProvider; + /* 1. Брать текущий IP 2. Определять город по текущему IP @@ -8,7 +12,11 @@ package ru.dima.weather; public class WeatherApp { public static void main(String[] args) { - var cityByIpResolver = new CityByIpResolver(new HttpRequester()); + var httpRequester = new HttpRequester(); + var cityByIpResolver = new CityByIpResolver(httpRequester); System.out.println(cityByIpResolver.getCurrentCityViaIP()); + + var openWeatherMapProvider = new OpenWeatherMapWeatherProvider(httpRequester, "29ed5ca47c3d0c32385b18f1e82e522f"); + System.out.println(openWeatherMapProvider.getWeeklyWeatherInCity(cityByIpResolver.getCurrentCityViaIP())); } } diff --git a/src/main/java/ru/dima/weather/CityByIpResolver.java b/src/main/java/ru/dima/weather/city/CityByIpResolver.java similarity index 65% rename from src/main/java/ru/dima/weather/CityByIpResolver.java rename to src/main/java/ru/dima/weather/city/CityByIpResolver.java index 8952aa6..7a44c63 100644 --- a/src/main/java/ru/dima/weather/CityByIpResolver.java +++ b/src/main/java/ru/dima/weather/city/CityByIpResolver.java @@ -1,4 +1,6 @@ -package ru.dima.weather; +package ru.dima.weather.city; + +import ru.dima.weather.http.HttpRequester; public class CityByIpResolver { @@ -11,6 +13,6 @@ public class CityByIpResolver { } public String getCurrentCityViaIP() { - return httpRequester.getString(IP_INFO_URL); + return httpRequester.getString(IP_INFO_URL).replace("\n", "").replace("\r", ""); } } diff --git a/src/main/java/ru/dima/weather/HttpRequester.java b/src/main/java/ru/dima/weather/http/HttpRequester.java similarity index 94% rename from src/main/java/ru/dima/weather/HttpRequester.java rename to src/main/java/ru/dima/weather/http/HttpRequester.java index ef52835..6bf8d67 100644 --- a/src/main/java/ru/dima/weather/HttpRequester.java +++ b/src/main/java/ru/dima/weather/http/HttpRequester.java @@ -1,4 +1,4 @@ -package ru.dima.weather; +package ru.dima.weather.http; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/ru/dima/weather/provider/MultiDaysWeatherInfo.java b/src/main/java/ru/dima/weather/provider/MultiDaysWeatherInfo.java new file mode 100644 index 0000000..744f1ea --- /dev/null +++ b/src/main/java/ru/dima/weather/provider/MultiDaysWeatherInfo.java @@ -0,0 +1,15 @@ +package ru.dima.weather.provider; + +import java.util.ArrayList; +import java.util.List; + +public class MultiDaysWeatherInfo { + List perDayWeather = new ArrayList<>(); + + @Override + public String toString() { + return "MultiDaysWeatherInfo{" + + "perDayWeather=" + perDayWeather + + '}'; + } +} diff --git a/src/main/java/ru/dima/weather/provider/OpenWeatherMapWeatherProvider.java b/src/main/java/ru/dima/weather/provider/OpenWeatherMapWeatherProvider.java new file mode 100644 index 0000000..facf42c --- /dev/null +++ b/src/main/java/ru/dima/weather/provider/OpenWeatherMapWeatherProvider.java @@ -0,0 +1,59 @@ +package ru.dima.weather.provider; + +import org.json.JSONObject; +import ru.dima.weather.http.HttpRequester; + +import java.util.Map; +import java.util.stream.Collectors; + +public class OpenWeatherMapWeatherProvider implements WeatherProvider { + + private HttpRequester httpRequester; + private String openWeatherMapAccessToken; + + public static final String OPEN_WEATHER_MAP_BASE_FORECAST_URL = "https://api.openweathermap.org/data/2.5/forecast"; + public static final String OPEN_WEATHER_MAP_CITY_NAME_QUERY = "q"; + public static final String OPEN_WEATHER_MAP_ACCESS_TOKEN_QUERY = "appid"; + + public static final String NAME = "open-weather-map"; + + public OpenWeatherMapWeatherProvider(HttpRequester httpRequester, String openWeatherMapAccessToken) { + this.httpRequester = httpRequester; + this.openWeatherMapAccessToken = openWeatherMapAccessToken; + } + + @Override + public MultiDaysWeatherInfo getWeeklyWeatherInCity(String cityName) { + var weatherResponse = httpRequester.getString(getWeeklyWeatherRequestUrl(cityName)); + var jsonObject = new JSONObject(weatherResponse); + var weatherArray = jsonObject.getJSONArray("list"); + var resultWeeklyWeather = new MultiDaysWeatherInfo(); + + for (var day = 0; day < 7; day ++) { + var forecast = weatherArray.getJSONObject(day); + var mainData = forecast.getJSONObject("main"); + + var temperature = mainData.getDouble("temp"); + resultWeeklyWeather.perDayWeather.add(new WeatherInfo(temperature)); + } + + return resultWeeklyWeather; + } + + @Override + public String getName() { + return NAME; + } + + private String getWeeklyWeatherRequestUrl(String cityName) { + var queryString = Map.of( + OPEN_WEATHER_MAP_CITY_NAME_QUERY, cityName, + OPEN_WEATHER_MAP_ACCESS_TOKEN_QUERY, openWeatherMapAccessToken, + "units", "metric" + ).entrySet().stream() + .map(queryParameter -> queryParameter.getKey() + "=" + queryParameter.getValue()) + .collect(Collectors.joining("&")); + + return OPEN_WEATHER_MAP_BASE_FORECAST_URL + "?" + queryString; + } +} diff --git a/src/main/java/ru/dima/weather/provider/WeatherInfo.java b/src/main/java/ru/dima/weather/provider/WeatherInfo.java new file mode 100644 index 0000000..05f4442 --- /dev/null +++ b/src/main/java/ru/dima/weather/provider/WeatherInfo.java @@ -0,0 +1,16 @@ +package ru.dima.weather.provider; + +public class WeatherInfo { + public double temperature; + + public WeatherInfo(double temperature) { + this.temperature = temperature; + } + + @Override + public String toString() { + return "WeatherInfo{" + + "temperature=" + temperature + + '}'; + } +} diff --git a/src/main/java/ru/dima/weather/provider/WeatherProvider.java b/src/main/java/ru/dima/weather/provider/WeatherProvider.java new file mode 100644 index 0000000..8425ab9 --- /dev/null +++ b/src/main/java/ru/dima/weather/provider/WeatherProvider.java @@ -0,0 +1,6 @@ +package ru.dima.weather.provider; + +public interface WeatherProvider { + MultiDaysWeatherInfo getWeeklyWeatherInCity(String cityName); + String getName(); +}