Skip to content

Commit

Permalink
Merge pull request #136 from olech2412/135-collaborative-filtering-ap…
Browse files Browse the repository at this point in the history
…i-adapter

135 collaborative filtering api adapter
  • Loading branch information
olech2412 authored Aug 7, 2024
2 parents 5cccf7f + e2ba163 commit 5a888d4
Show file tree
Hide file tree
Showing 12 changed files with 391 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ package-lock.json
**/vite.generated.ts
node_modules/
package.json
**/mensahub/
**/.vscode/
/.vscode/
/.vscode/
/mensahub/
95 changes: 95 additions & 0 deletions MensaHub-Collaborative-Filtering-API-Adapter/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.olech2412.mensahub</groupId>
<artifactId>MensaHub</artifactId>
<version>1.0.0</version>
</parent>
<developers>
<developer>
<id>olech2412</id>
<name>Ole Christoph</name>
<url>https://github.com/olech2412</url>
</developer>
</developers>
<version>1.0.0</version>

<artifactId>MensaHub-Collaborative-Filtering-API-Adapter</artifactId>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<!-- To upload this package to GitHub packages-->
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub MensaHub-Package</name>
<url>https://maven.pkg.github.com/olech2412/MensaHub</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
</repository>
</distributionManagement>

<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.22.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>de.olech2412.mensahub</groupId>
<artifactId>mensahub-models</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.16.1</version>
<scope>compile</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package de.olech2412.mensahub;

import de.olech2412.mensahub.request.Request;
import de.olech2412.mensahub.request.RequestPath;
import lombok.Getter;
import lombok.Setter;

import java.net.Proxy;
import java.util.List;

@Getter
public class APIConfiguration {

@Setter
private String baseUrl = "http://localhost:5000"; // Beispiel-URL für die lokale Flask-API

private List<Request> requests;

@Setter
private Proxy proxy;

public APIConfiguration() {
buildRequestList();
}

private void buildRequestList() {
requests = List.of(
new Request.RequestBuilder()
.setApiEndpoint(RequestPath.PREDICT)
.build()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package de.olech2412.mensahub;

import com.google.gson.*;
import de.olech2412.mensahub.models.addons.predictions.PredictionRequest;
import de.olech2412.mensahub.models.addons.predictions.PredictionResult;
import de.olech2412.mensahub.models.result.Result;
import de.olech2412.mensahub.models.result.errors.api.APIError;
import de.olech2412.mensahub.models.result.errors.api.APIErrors;
import de.olech2412.mensahub.request.Request;
import de.olech2412.mensahub.request.RequestPath;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Log4j2
public class CollaborativeFilteringAPIAdapter {

private final APIConfiguration apiConfiguration;
private final Gson gson;

public CollaborativeFilteringAPIAdapter(APIConfiguration apiConfiguration) {
this.apiConfiguration = apiConfiguration;
this.gson = new Gson();
}

public Result<List<Result<PredictionResult, APIError>>, APIError> predict(List<PredictionRequest> requestData) throws IOException {
Request request = getRequest(RequestPath.PREDICT);
Result<JsonArray, APIError> result = performRequest(request, gson.toJson(requestData));

if (!result.isSuccess()) {
log.error("Error while predicting ratings: {}", result.getError().message());
return Result.error(result.getError());
} else {
JsonArray jsonArray = result.getData();
List<Result<PredictionResult, APIError>> predictions = new ArrayList<>();

for (JsonElement element : jsonArray) {
JsonObject obj = element.getAsJsonObject();
if (obj.has("predicted_rating")) {
PredictionResult predictionResult = gson.fromJson(obj, PredictionResult.class);
predictions.add(Result.success(predictionResult));
} else {
APIError apiError = new APIError(obj.get("error").getAsString(), APIErrors.UNKNOWN);
predictions.add(Result.error(apiError));
}
}

return Result.success(predictions);
}
}

private Request getRequest(RequestPath requestPath) {
for (Request request : apiConfiguration.getRequests()) {
if (request.getApiEndpoint().equals(requestPath.getPath())) {
return new Request.RequestBuilder().setApiEndpoint(requestPath).build();
}
}
throw new IllegalArgumentException("Request not found");
}

private Result<JsonArray, APIError> performRequest(Request request, String jsonPayload) throws IOException {
URL url = new URL(apiConfiguration.getBaseUrl() + request.getApiEndpoint());
HttpURLConnection con = (HttpURLConnection) url.openConnection();

con.setRequestMethod("POST");
con.setDoOutput(true);
con.setConnectTimeout(10000);
con.setReadTimeout(10000);
con.setRequestProperty("Content-Type", "application/json");

try (OutputStream os = con.getOutputStream()) {
byte[] input = jsonPayload.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}

int status = con.getResponseCode();
InputStream responseStream = (status == 200) ? con.getInputStream() : con.getErrorStream();
String responseString = IOUtils.toString(responseStream, StandardCharsets.UTF_8);

if (status != 200) {
return Result.error(new APIError(responseString, APIErrors.UNKNOWN));
}

JsonArray responseObject = JsonParser.parseString(responseString).getAsJsonArray();
return Result.success(responseObject);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.olech2412.mensahub.request;

import lombok.Getter;
import lombok.Setter;

/**
* This class stores information about all possible requests
* It stores the base url and the class that represents the response
*/
@Setter
@Getter
public class Request {

// The endpoint of the api
private String apiEndpoint;

// get the endpoint of the api
private Request() {
}


public static class RequestBuilder {

// The endpoint of the api
private RequestPath apiEndpoint;

public RequestBuilder() {
}

// set the endpoint of the api
public RequestBuilder setApiEndpoint(RequestPath apiEndpoint) {
this.apiEndpoint = apiEndpoint;
return this;
}

// build the request
public Request build() {
Request request = new Request();
request.apiEndpoint = this.apiEndpoint.getPath();
return request;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.olech2412.mensahub.request;

import lombok.Getter;

public enum RequestPath {

PREDICT("/predict");

@Getter
private final String path;

RequestPath(String path) {
this.path = path;
}

@Override
public String toString() {
return path;
}
}
8 changes: 7 additions & 1 deletion MensaHub-Models/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<url>https://github.com/olech2412</url>
</developer>
</developers>
<version>2.0.9</version>
<version>2.1.0</version>


<properties>
Expand Down Expand Up @@ -85,6 +85,12 @@
<version>6.5.2.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
<scope>compile</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.olech2412.mensahub.models.addons.predictions;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class PredictionRequest {
private int userId;
private String meal;

public PredictionRequest(int userId, String meal) {
this.userId = userId;
this.meal = meal;
}

@Override
public String toString() {
return "PredictionRequest{" +
"userId=" + userId +
", meal='" + meal + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package de.olech2412.mensahub.models.addons.predictions;

import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class PredictionResult {

@SerializedName("predicted_rating")
private double predictedRating;
@SerializedName("trust_score")
private String trustScore;
private int userId;
private String meal;

@Override
public String toString() {
return "PredictionResult{" +
"predictedRating=" + predictedRating +
", trustScore='" + trustScore + '\'' +
", userId=" + userId +
", meal='" + meal + '\'' +
'}';
}
}
Loading

0 comments on commit 5a888d4

Please sign in to comment.