Compare commits

...

3 commits

Author SHA1 Message Date
102eb026a7
not yet 2024-05-30 13:58:01 +02:00
5e8f08b423
back 2024-05-30 13:57:14 +02:00
ef7a32aab6
preparing for packaging 2024-05-30 13:54:02 +02:00
8 changed files with 472 additions and 6 deletions

34
pom.xml
View file

@ -6,12 +6,19 @@
<groupId>eu.m724</groupId>
<artifactId>wtapi</artifactId>
<version>1.0-SNAPSHOT</version>
<version>0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>724rocks</id>
<url>https://git.724.rocks/api/packages/Minecon724/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
@ -26,5 +33,30 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>3.0.1</version>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>724rocks</id>
<url>https://git.724.rocks/api/packages/Minecon724/maven</url>
</repository>
<snapshotRepository>
<id>724rocks</id>
<url>https://git.724.rocks/api/packages/Minecon724/maven</url>
</snapshotRepository>
</distributionManagement>
<scm>
<developerConnection>scm:git:https://git.724.rocks/Minecon724/wtapi.git</developerConnection>
</scm>
</project>

24
release.properties Normal file
View file

@ -0,0 +1,24 @@
#release configuration
#Thu May 30 13:55:56 CEST 2024
completedPhase=end-release
exec.pomFileName=pom.xml
exec.snapshotReleasePluginAllowed=false
pinExternals=false
preparationGoals=clean verify
project.dev.eu.m724\:wtapi=1.1-SNAPSHOT
project.rel.eu.m724\:wtapi=1.0
project.scm.eu.m724\:wtapi.developerConnection=scm\:git\:https\://git.724.rocks/Minecon724/wtapi.git
project.scm.eu.m724\:wtapi.tag=HEAD
projectVersionPolicyConfig=<projectVersionPolicyConfig>${projectVersionPolicyConfig}</projectVersionPolicyConfig>\n
projectVersionPolicyId=default
pushChanges=true
releaseStrategyId=default
remoteTagging=true
scm.branchCommitComment=@{prefix} prepare branch @{releaseLabel}
scm.commentPrefix=[maven-release-plugin]
scm.developmentCommitComment=@{prefix} prepare for next development iteration
scm.releaseCommitComment=@{prefix} prepare release @{releaseLabel}
scm.rollbackCommitComment=@{prefix} rollback the release of @{releaseLabel}
scm.tag=wtapi-1.0
scm.tagNameFormat=@{project.artifactId}-@{project.version}
scm.url=scm\:git\:https\://git.724.rocks/Minecon724/wtapi.git

View file

@ -0,0 +1,5 @@
package eu.m724.wtapi.object;
public enum Severity {
LIGHT, MODERATE, HEAVY
}

View file

@ -1,5 +0,0 @@
package eu.m724.wtapi.object;
public enum WeatherState {
CLEAR, RAIN, THUNDER
}

View file

@ -0,0 +1,230 @@
package eu.m724.wtapi.provider.impl.openweathermap;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import eu.m724.wtapi.object.Coordinates;
import eu.m724.wtapi.object.Severity;
import eu.m724.wtapi.object.Weather;
public class OWMResponseConverter {
static Weather convert(JsonObject json) {
Weather weather = new Weather();
int conditionCode = json.getAsJsonArray("weather")
.get(0).getAsJsonObject()
.getAsJsonPrimitive("id").getAsInt();
switch (conditionCode) {
// Group 2xx: Thunderstorm
case 200: // thunderstorm with light rain
weather.thunderstormSeverity = Severity.LIGHT;
weather.rainSeverity = Severity.LIGHT;
break;
case 201: // thunderstorm with rain
weather.thunderstormSeverity = Severity.MODERATE;
weather.rainSeverity = Severity.MODERATE;
break;
case 202: // thunderstorm with heavy rain
weather.thunderstormSeverity = Severity.HEAVY;
weather.rainSeverity = Severity.HEAVY;
break;
case 210: // light thunderstorm
weather.thunderstormSeverity = Severity.LIGHT;
break;
case 211: // thunderstorm
weather.thunderstormSeverity = Severity.MODERATE;
break;
case 212: // heavy thunderstorm
weather.thunderstormSeverity = Severity.HEAVY;
break;
case 221: // ragged thunderstorm
weather.thunderstormSeverity = Severity.MODERATE;
break;
case 230: // thunderstorm with light drizzle
weather.thunderstormSeverity = Severity.LIGHT;
weather.drizzleSeverity = Severity.LIGHT;
break;
case 231: // thunderstorm with drizzle
weather.thunderstormSeverity = Severity.MODERATE;
weather.drizzleSeverity = Severity.MODERATE;
break;
case 232: // thunderstorm with heavy drizzle
weather.thunderstormSeverity = Severity.HEAVY;
weather.drizzleSeverity = Severity.HEAVY;
break;
// Group 3xx: Drizzle
case 300: // light intensity drizzle
weather.drizzleSeverity = Severity.LIGHT;
break;
case 301: // drizzle
weather.drizzleSeverity = Severity.MODERATE;
break;
case 302: // heavy intensity drizzle
weather.drizzleSeverity = Severity.HEAVY;
break;
case 310: // light intensity drizzle rain
weather.drizzleSeverity = Severity.LIGHT;
break;
case 311: // drizzle rain
weather.drizzleSeverity = Severity.MODERATE;
break;
case 312: // heavy intensity drizzle rain
weather.drizzleSeverity = Severity.HEAVY;
break;
case 313: // shower rain and drizzle
weather.rainSeverity = Severity.MODERATE;
weather.drizzleSeverity = Severity.MODERATE;
weather.shower = true;
break;
case 314: // heavy shower rain and drizzle
weather.rainSeverity = Severity.HEAVY;
weather.drizzleSeverity = Severity.HEAVY;
weather.shower = true;
break;
case 321: // shower drizzle
weather.drizzleSeverity = Severity.MODERATE;
weather.shower = true;
break;
// Group 5xx: Rain
case 500: // light rain
weather.rainSeverity = Severity.LIGHT;
break;
case 501: // moderate rain
weather.rainSeverity = Severity.MODERATE;
break;
case 502: // heavy intensity rain
weather.rainSeverity = Severity.HEAVY;
break;
case 503: // very heavy rain
weather.rainSeverity = Severity.HEAVY;
break;
case 504: // extreme rain
weather.rainSeverity = Severity.HEAVY;
break;
case 511: // freezing rain
weather.rainSeverity = Severity.MODERATE;
break;
case 520: // light intensity shower rain
weather.rainSeverity = Severity.LIGHT;
weather.shower = true;
break;
case 521: // shower rain
weather.rainSeverity = Severity.MODERATE;
weather.shower = true;
break;
case 522: // heavy intensity shower rain
weather.rainSeverity = Severity.HEAVY;
weather.shower = true;
break;
case 531: // ragged shower rain
weather.rainSeverity = Severity.MODERATE;
weather.shower = true;
break;
// Group 6xx: Snow
case 600: // light snow
weather.snowSeverity = Severity.LIGHT;
break;
case 601: // snow
weather.snowSeverity = Severity.MODERATE;
break;
case 602: // heavy snow
weather.snowSeverity = Severity.HEAVY;
break;
case 611: // sleet
weather.sleetSeverity = Severity.MODERATE;
break;
case 612: // light shower sleet
weather.sleetSeverity = Severity.LIGHT;
weather.shower = true;
break;
case 613: // shower sleet
weather.sleetSeverity = Severity.MODERATE;
weather.shower = true;
break;
case 615: // light rain and snow
weather.rainSeverity = Severity.LIGHT;
weather.snowSeverity = Severity.LIGHT;
break;
case 616: // rain and snow
weather.rainSeverity = Severity.MODERATE;
weather.snowSeverity = Severity.MODERATE;
break;
case 620: // light shower snow
weather.snowSeverity = Severity.LIGHT;
weather.shower = true;
break;
case 621: // shower snow
weather.snowSeverity = Severity.MODERATE;
weather.shower = true;
break;
case 622: // heavy shower snow
weather.snowSeverity = Severity.HEAVY;
weather.shower = true;
break;
}
weather.coordinates =
new Coordinates(
json.getAsJsonObject("coord").getAsJsonPrimitive("lon").getAsDouble(),
json.getAsJsonObject("coord").getAsJsonPrimitive("lat").getAsDouble()
);
weather.temperature = json
.getAsJsonObject("main")
.getAsJsonPrimitive("temp")
.getAsFloat();
weather.temperatureApparent = json
.getAsJsonObject("main")
.getAsJsonPrimitive("feels_like")
.getAsFloat();
weather.windSpeed = json
.getAsJsonObject("wind")
.getAsJsonPrimitive("speed")
.getAsFloat();
JsonPrimitive pri = json
.getAsJsonObject("wind")
.getAsJsonPrimitive("gust");
if (pri != null)
weather.windSpeed = pri.getAsFloat();
weather.humidity = json
.getAsJsonObject("main")
.getAsJsonPrimitive("humidity")
.getAsInt() / 100f;
weather.cloudiness = json
.getAsJsonObject("clouds")
.getAsJsonPrimitive("all")
.getAsInt() / 100f;
weather.sunrise = json
.getAsJsonObject("sys")
.getAsJsonPrimitive("sunrise")
.getAsLong();
weather.sunset = json
.getAsJsonObject("sys")
.getAsJsonPrimitive("sunrise")
.getAsLong();
weather.city = json
.getAsJsonPrimitive("name")
.getAsString();
weather.description = json
.getAsJsonArray("weather")
.get(0).getAsJsonObject()
.getAsJsonPrimitive("description")
.getAsString();
return weather;
}
}

View file

@ -0,0 +1,113 @@
package eu.m724.wtapi.provider.impl.openweathermap;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import eu.m724.wtapi.object.Coordinates;
import eu.m724.wtapi.object.Weather;
import eu.m724.wtapi.provider.WeatherProvider;
import eu.m724.wtapi.provider.exception.AuthorizationException;
import eu.m724.wtapi.provider.exception.ProviderException;
import eu.m724.wtapi.provider.exception.QuotaExceededException;
import eu.m724.wtapi.provider.exception.ServerProviderException;
public class OpenWeatherMapProvider extends WeatherProvider {
private String requestUrlFormat;
private String apiKey;
public OpenWeatherMapProvider(String apiKey) {
this.apiKey = apiKey;
this.requestUrlFormat = "https://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&appid=" + apiKey;
}
@Override
public void init() throws ProviderException {
CompletableFuture<Weather> weatherFuture =
getWeather(new Coordinates(0, 0));
try {
weatherFuture.get();
} catch (InterruptedException e) {
throw new ProviderException("unexpected interruptedexception");
} catch (ExecutionException e) {
throw (ProviderException) e.getSuppressed()[0]; // TODO
}
}
@Override
public CompletableFuture<Weather> getWeather(Coordinates coordinates) {
String url = String.format(
requestUrlFormat, coordinates.latitude, coordinates.longitude);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.build();
CompletableFuture<HttpResponse<String>> responseFuture =
HttpClient.newBuilder()
.proxy(ProxySelector.getDefault()).build()
.sendAsync(request, BodyHandlers.ofString());
CompletableFuture<Weather> weatherFuture =
responseFuture.thenApply((response) -> {
int code = response.statusCode();
if (code == 401)
throw new AuthorizationException("invalid api key");
if (code == 429)
throw new QuotaExceededException("ratelimited", 1000);
if (code != 200)
throw new ServerProviderException(String.format("status code %d", code));
JsonObject jsonResponse =
JsonParser.parseString(response.body())
.getAsJsonObject();
Weather weather = OWMResponseConverter.convert(jsonResponse);
return weather;
});
return weatherFuture;
}
@Override
public CompletableFuture<Weather[]> getWeatherBulk(Coordinates[] coordinateses) {
ArrayList<CompletableFuture<Weather>> weatherFutures = new ArrayList<>();
for (Coordinates coordinates : coordinateses) {
weatherFutures.add(getWeather(coordinates));
}
CompletableFuture<Weather[]> weathersFuture =
CompletableFuture.allOf(
weatherFutures.toArray(new CompletableFuture[0]))
.thenApply(v ->
weatherFutures.stream()
.map(CompletableFuture::join)
.toArray(Weather[]::new));
return weathersFuture;
}
@Override
public int getQuotaHourly() {
return 1370;
}
@Override
public int getBulkLimit() {
return 1;
}
}

View file

@ -0,0 +1,20 @@
package eu.m724.wtapi;
import org.junit.Test;
import eu.m724.wtapi.object.Coordinates;
public class CoordinateTest {
@Test
public void testCoordinates() {
Coordinates coordinates = new Coordinates(-91.1, 180.01);
System.out.println(coordinates.longitude);
assert coordinates.latitude == 88.9;
assert coordinates.longitude == -179.99;
coordinates = new Coordinates(-91.1, 180.1);
assert coordinates.longitude != -179.9; // TODO
}
}

View file

@ -0,0 +1,47 @@
package eu.m724.wtapi;
import static org.junit.Assert.assertNotNull;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import eu.m724.wtapi.object.Coordinates;
import eu.m724.wtapi.object.Weather;
import eu.m724.wtapi.provider.WeatherProvider;
import eu.m724.wtapi.provider.impl.openweathermap.OpenWeatherMapProvider;
public class TestOWM {
@Test
public void openWeatherMapTest() throws InterruptedException, ExecutionException {
String apiKey = "f3198d2a4ae3076e0aa47c821a253447";
WeatherProvider provider = new OpenWeatherMapProvider(apiKey);
provider.init();
CompletableFuture<Weather> weatherFuture =
provider.getWeather(new Coordinates(53.2232, -4.2008));
Weather weather = weatherFuture.get();
assertNotNull(weather);
System.out.printf("current weather in %s: %s\n", weather.city, weather.description);
CompletableFuture<Weather[]> weatherBulkFuture =
provider.getWeatherBulk(
new Coordinates[] {
new Coordinates(54.6606714, -3.3827237),
new Coordinates(47.5705952, -53.5556464),
new Coordinates(34.2073721, -84.1402857),
});
Weather[] weathers = weatherBulkFuture.get();
assert weathers.length == 3;
for (Weather weather1 : weathers) {
System.out.printf("current weather in %s: %s\n", weather1.city, weather1.description);
}
}
}