draft: continue cache
This commit is contained in:
parent
6d0e8f9786
commit
932e272cc5
@ -61,12 +61,20 @@ public class Main {
|
||||
OpenMeteo openMeteo = new OpenMeteo();
|
||||
OpenWeatherMap openWeatherMap = new OpenWeatherMap(OpenWMapKey);
|
||||
WeatherDisplay display = new WeatherDisplayBasic();
|
||||
WeatherDisplay display2 = new WeatherDisplayBasic();
|
||||
WeatherDisplay display3 = new WeatherDisplayBasic();
|
||||
|
||||
display.addAPI(weatherAPI);
|
||||
display.addAPI(weatherAPI);
|
||||
display.addAPI(openMeteo);
|
||||
display.addAPI(openWeatherMap);
|
||||
|
||||
display2.addAPI(weatherAPI);
|
||||
display3.addAPI(weatherAPI);
|
||||
|
||||
// weatherAPI can't fetch for more than 3 days with free plan
|
||||
display.display(days, city);
|
||||
display2.display(days, city);
|
||||
display3.display(days, city);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import eirb.pg203.WeatherData.Condition;
|
||||
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";
|
||||
private final WeatherDataCache cache = new WeatherDataCache();
|
||||
|
||||
// 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 {
|
||||
@ -28,8 +29,7 @@ public class OpenMeteo implements WeatherDataAPI {
|
||||
)
|
||||
).toURL();
|
||||
|
||||
JSONArray jsonArray = JSONFetcher.fetchArray(url);
|
||||
return jsonArray.getJSONObject(0);
|
||||
return JSONFetcher.fetch(url);
|
||||
}
|
||||
|
||||
private static Condition getConditionFromCode(int WMOCode) {
|
||||
@ -44,7 +44,7 @@ public class OpenMeteo implements WeatherDataAPI {
|
||||
}
|
||||
|
||||
|
||||
private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
|
||||
private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String cityName) {
|
||||
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);
|
||||
@ -55,7 +55,7 @@ public class OpenMeteo implements WeatherDataAPI {
|
||||
int conditionCode = daily.getJSONArray("weather_code").getInt(day);
|
||||
|
||||
return new WeatherData(
|
||||
new City(city),
|
||||
new City(cityName),
|
||||
Instant.now(),
|
||||
temp_c,
|
||||
windSpeed,
|
||||
@ -68,28 +68,33 @@ public class OpenMeteo implements WeatherDataAPI {
|
||||
* @param day Day, 0 ≤ day ≤ 14
|
||||
*/
|
||||
@Override
|
||||
public WeatherData getTemperature(int day, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(day + 1, new City(city));
|
||||
public WeatherData getTemperature(int day, String cityName) throws IOException {
|
||||
JSONObject result = fetchWeather(day + 1, new City(cityName));
|
||||
|
||||
return getWeatherDataFromForecast(result, day, city);
|
||||
return getWeatherDataFromForecast(result, day, cityName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherData getTemperature(int day, int hour, String city) throws IOException{
|
||||
return getTemperature(day, city);
|
||||
public WeatherData getTemperature(int day, int hour, String cityName) throws IOException{
|
||||
return getTemperature(day, cityName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(days, new City(city));
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String cityName) throws IOException {
|
||||
if (!this.cache.needsUpdate(cityName, days))
|
||||
return this.cache.get(cityName, days);
|
||||
|
||||
JSONObject result = fetchWeather(days, new City(cityName));
|
||||
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
||||
|
||||
for (int day = 0; day < days; ++day) {
|
||||
weatherDatas.add(
|
||||
getWeatherDataFromForecast(result, day, city)
|
||||
getWeatherDataFromForecast(result, day, cityName)
|
||||
);
|
||||
}
|
||||
|
||||
this.cache.set(cityName, days, weatherDatas, Instant.now());
|
||||
|
||||
return weatherDatas;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ import eirb.pg203.WeatherData.Condition;
|
||||
public class OpenWeatherMap implements WeatherDataAPI {
|
||||
private static final String forecastBaseURL = "https://api.openweathermap.org/data/2.5/forecast";
|
||||
private String APIKey;
|
||||
private final WeatherDataCache cache = new WeatherDataCache();
|
||||
|
||||
OpenWeatherMap(String APIKey) {
|
||||
this.APIKey = APIKey;
|
||||
@ -37,7 +38,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
||||
return JSONFetcher.fetch(url);
|
||||
}
|
||||
|
||||
private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
|
||||
private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String cityName) {
|
||||
JSONArray list = response.getJSONArray("list");
|
||||
|
||||
DayOfWeek targetedDay = Instant.now().plusSeconds(day * 24 * 3600).atZone(ZoneId.systemDefault()).getDayOfWeek();
|
||||
@ -85,7 +86,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
||||
|
||||
|
||||
return new WeatherData(
|
||||
new City(city),
|
||||
new City(cityName),
|
||||
Instant.now().plusSeconds(day * 24 * 3600),
|
||||
temp_c,
|
||||
windSpeed,
|
||||
@ -98,29 +99,33 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
||||
* @param day Day, 0 ≤ day ≤ 14
|
||||
*/
|
||||
@Override
|
||||
public WeatherData getTemperature(int day, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(day+1, new City(city));
|
||||
public WeatherData getTemperature(int day, String cityName) throws IOException {
|
||||
JSONObject result = fetchWeather(day+1, new City(cityName));
|
||||
|
||||
return getWeatherDataFromForecast(result, day, city);
|
||||
return getWeatherDataFromForecast(result, day, cityName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherData getTemperature(int day, int hour, String city) throws IOException{
|
||||
return getTemperature(day, city);
|
||||
public WeatherData getTemperature(int day, int hour, String cityname) throws IOException{
|
||||
return getTemperature(day, cityname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(days, new City(city));
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String cityName) throws IOException {
|
||||
if (!this.cache.needsUpdate(cityName, days))
|
||||
return this.cache.get(cityName, days);
|
||||
|
||||
JSONObject result = fetchWeather(days, new City(cityName));
|
||||
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
||||
|
||||
for (int day = 0; day < days ; ++day) {
|
||||
weatherDatas.add(
|
||||
getWeatherDataFromForecast(result, day, city)
|
||||
getWeatherDataFromForecast(result, day, cityName)
|
||||
);
|
||||
}
|
||||
|
||||
this.cache.set(cityName, days, weatherDatas, Instant.now());
|
||||
|
||||
return weatherDatas;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import java.util.ArrayList;
|
||||
public class WeatherAPI implements WeatherDataAPI{
|
||||
private final String weatherAPIKey;
|
||||
private static final String forecastBaseURL = "https://api.weatherapi.com/v1/forecast.json";
|
||||
private final WeatherDataCache cache = new WeatherDataCache();
|
||||
|
||||
WeatherAPI(String weatherAPIKey) {
|
||||
this.weatherAPIKey = weatherAPIKey;
|
||||
@ -80,27 +81,32 @@ public class WeatherAPI implements WeatherDataAPI{
|
||||
* @param day Day, 0 ≤ day ≤ 14
|
||||
*/
|
||||
@Override
|
||||
public WeatherData getTemperature(int day, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(day+1, city);
|
||||
return getWeatherDataFromForecast(result, day, city);
|
||||
public WeatherData getTemperature(int day, String cityName) throws IOException {
|
||||
JSONObject result = fetchWeather(day+1, cityName);
|
||||
return getWeatherDataFromForecast(result, day, cityName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherData getTemperature(int day, int hour, String city) throws IOException{
|
||||
return getTemperature(day, city);
|
||||
public WeatherData getTemperature(int day, int hour, String cityName) throws IOException{
|
||||
return getTemperature(day, cityName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
||||
JSONObject result = fetchWeather(days, city);
|
||||
public ArrayList<WeatherData> getTemperatures(int days, String cityName) throws IOException {
|
||||
if (!this.cache.needsUpdate(cityName, days))
|
||||
return this.cache.get(cityName, days);
|
||||
|
||||
JSONObject result = fetchWeather(days, cityName);
|
||||
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
||||
|
||||
for (int day = 0; day < days; ++day) {
|
||||
weatherDatas.add(
|
||||
getWeatherDataFromForecast(result, day, city)
|
||||
getWeatherDataFromForecast(result, day, cityName)
|
||||
);
|
||||
}
|
||||
|
||||
this.cache.set(cityName, days, weatherDatas, Instant.now());
|
||||
|
||||
return weatherDatas;
|
||||
}
|
||||
|
||||
|
10
src/main/java/eirb/pg203/WeatherCachedAPI.java
Normal file
10
src/main/java/eirb/pg203/WeatherCachedAPI.java
Normal file
@ -0,0 +1,10 @@
|
||||
package eirb.pg203;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
abstract class WeatherCachedAPI implements WeatherDataAPI {
|
||||
private final WeatherDataCache cache = new WeatherDataCache();
|
||||
|
||||
public void loadCache(JSONObject cache)
|
||||
|
||||
}
|
@ -7,9 +7,7 @@ import org.json.JSONObject;
|
||||
|
||||
import com.sun.net.httpserver.Authenticator.Retry;
|
||||
|
||||
import eirb.pg203.utils.JSONCachable;
|
||||
|
||||
class WeatherData implements JSONCachable {
|
||||
class WeatherData {
|
||||
enum Condition {
|
||||
SUNNY("☀️"),
|
||||
PARTIAL("🌤"),
|
||||
@ -188,7 +186,6 @@ class WeatherData implements JSONCachable {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJSON() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
|
||||
@ -203,8 +200,7 @@ class WeatherData implements JSONCachable {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONCachable fromJSON(JSONObject data) {
|
||||
public static WeatherData fromJSON(JSONObject data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
94
src/main/java/eirb/pg203/WeatherDataCache.java
Normal file
94
src/main/java/eirb/pg203/WeatherDataCache.java
Normal file
@ -0,0 +1,94 @@
|
||||
package eirb.pg203;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class WeatherDataCache {
|
||||
static class CacheValue {
|
||||
private ArrayList<WeatherData> value;
|
||||
private Instant timestamp;
|
||||
|
||||
CacheValue(ArrayList<WeatherData> value, Instant timestamp) {
|
||||
this.value = value;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public ArrayList<WeatherData> getWeatherData() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Instant getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Will parse CacheValues with { "api": apiName } from JSON
|
||||
*/
|
||||
JSONObject toJSON(String apiName, String cityName) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
JSONArray values = new JSONArray();
|
||||
|
||||
jsonObject.put("city", cityName);
|
||||
jsonObject.put("api", apiName);
|
||||
jsonObject.put("timestamp", this.timestamp.getEpochSecond());
|
||||
|
||||
for (int i = 0 ; i < this.value.size() ; ++i)
|
||||
values.put(this.value.get(i));
|
||||
|
||||
jsonObject.put("value", values);
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public static CacheValue fromJSON(JSONObject data) {
|
||||
ArrayList<WeatherData> value = new ArrayList<>();
|
||||
|
||||
JSONArray values = data.getJSONArray("value");
|
||||
for (int i = 0 ; i < values.length() ; ++i)
|
||||
value.add(WeatherData.fromJSON(values.getJSONObject(i)));
|
||||
|
||||
Instant timestamp = Instant.ofEpochSecond(data.getLong("timestamp"));
|
||||
|
||||
return new CacheValue(value, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<String, CacheValue> cache = new HashMap<>();
|
||||
private long cacheTTL = 3600; // Cache data Time To Live
|
||||
|
||||
public boolean has(String cityName, int days) {
|
||||
CacheValue cacheValue = this.cache.get(cityName);
|
||||
|
||||
return cacheValue != null;
|
||||
}
|
||||
|
||||
public boolean needsUpdate(String cityName, int days) {
|
||||
if (!has(cityName, days)) // if (cityName, days) isn't cached, needs udpate
|
||||
return true;
|
||||
|
||||
CacheKey cacheKey = new CacheKey(cityName, days);
|
||||
CacheValue cacheValue = this.cache.get(cacheKey);
|
||||
|
||||
long dt = Instant.now().getEpochSecond() - cacheValue.getTimestamp().getEpochSecond();
|
||||
|
||||
return dt > this.cacheTTL; // if older than TTL, needs update
|
||||
}
|
||||
|
||||
public ArrayList<WeatherData> get(String cityName, int days) {
|
||||
CacheKey cacheKey = new CacheKey(cityName, days);
|
||||
ArrayList<WeatherData> weatherData = this.cache.get(cacheKey).getWeatherData();
|
||||
|
||||
return weatherData;
|
||||
}
|
||||
|
||||
public void set(String cityName, int days, ArrayList<WeatherData> value, Instant timestamp) {
|
||||
CacheKey cacheKey = new CacheKey(cityName, days);
|
||||
CacheValue cacheValue = new CacheValue(value, timestamp);
|
||||
|
||||
this.cache.put(cacheKey, cacheValue);
|
||||
}
|
||||
}
|
@ -97,7 +97,6 @@ class WeatherDisplayBasic implements WeatherDisplay {
|
||||
displayWeatherDatas(api.getAPIName(), weatherDataAPIArrayListHashMap.get(api), startColumnString, sourceColumnSize, dayColumnSize);
|
||||
this.displaySeparatorLine(days, sourceColumnSize, dayColumnSizeSeparator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void display(int days, String city) {
|
||||
@ -110,6 +109,7 @@ class WeatherDisplayBasic implements WeatherDisplay {
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
this.displayAllWeatherDatas(weatherDatasMap, days);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ public class JSONFetcher {
|
||||
result.append(line);
|
||||
}
|
||||
}
|
||||
System.out.println(url);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user