Persistence, Statistics and Evaluation Logic added. Tests still pending

This commit is contained in:
naumueller 2026-02-10 21:07:05 +01:00
parent 1fedb1d2bc
commit b68cbe795c
12 changed files with 199 additions and 90 deletions

View File

@ -43,6 +43,11 @@
<version>4.12.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.51.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -1,8 +1,6 @@
package efi.projekt.virtueller_gesundheitsassistent;
import efi.projekt.virtueller_gesundheitsassistent.service.ClassificationService;
import efi.projekt.virtueller_gesundheitsassistent.service.MqttClientService;
import efi.projekt.virtueller_gesundheitsassistent.service.UnrealWebSocketService;
import java.io.IOException;
import javafx.application.Application;
import static javafx.application.Application.launch;
@ -27,7 +25,6 @@ public class App extends Application {
// MQTT
MqttClientService mqttClientService = new MqttClientService();
new ClassificationService(mqttClientService);
// Unreal WebSocket
// new UnrealWebSocketService("ws://localhost;8080/avatar");

View File

@ -0,0 +1,26 @@
package efi.projekt.virtueller_gesundheitsassistent.model;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
/**
*
* @author naumueller
*/
public class AppState {
private final ObjectProperty<ProblemLevel> problemLevel =
new SimpleObjectProperty<>(ProblemLevel.NONE);
public ObjectProperty<ProblemLevel> problemLevelProperty() {
return problemLevel;
}
public ProblemLevel getProblemLevel() {
return problemLevel.get();
}
public void setProblemLevel(ProblemLevel level) {
problemLevel.set(level);
}
}

View File

@ -1,34 +0,0 @@
package efi.projekt.virtueller_gesundheitsassistent.model;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
/**
*
* @author naumueller
*/
public class AssistantState {
private final ObjectProperty<ClassificationType> classification =
new SimpleObjectProperty<>(ClassificationType.NORMAL);
private final BooleanProperty speaking =
new SimpleBooleanProperty(false);
private final BooleanProperty monitoring =
new SimpleBooleanProperty(true);
public ObjectProperty<ClassificationType> classificationProperty() {
return classification;
}
public BooleanProperty speakingProperty() {
return speaking;
}
public BooleanProperty monitoringProperty() {
return monitoring;
}
}

View File

@ -1,13 +0,0 @@
package efi.projekt.virtueller_gesundheitsassistent.model;
/**
*
* @author naumueller
*/
public enum ClassificationType {
NORMAL,
MUEDIGKEIT,
ABLENKUNG,
STRESS,
REAKTION
}

View File

@ -0,0 +1,12 @@
package efi.projekt.virtueller_gesundheitsassistent.model;
/**
*
* @author naumueller
*/
public enum ProblemLevel {
NONE,
WARNING,
HIGH,
DISASTER
}

View File

@ -1,37 +0,0 @@
package efi.projekt.virtueller_gesundheitsassistent.service;
import efi.projekt.virtueller_gesundheitsassistent.model.ClassificationType;
import efi.projekt.virtueller_gesundheitsassistent.util.Logger;
import javafx.application.Platform;
/**
*
* @author naumueller
*/
public class ClassificationService {
private static final String TOPIC = "Text";
public ClassificationService(MqttClientService mqtt) {
mqtt.subscribe(TOPIC, payload -> {
ClassificationType type = switch (payload) {
case "0" -> ClassificationType.NORMAL;
case "1" -> ClassificationType.MUEDIGKEIT;
case "2" -> ClassificationType.ABLENKUNG;
case "3" -> ClassificationType.REAKTION;
case "4" -> ClassificationType.STRESS;
default -> ClassificationType.NORMAL;
};
Logger.info("STATE", "Neue Klassifizierung: " + type);
Platform.runLater(() ->
StateService.getState()
.classificationProperty()
.set(type)
);
});
}
}

View File

@ -0,0 +1,55 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package efi.projekt.virtueller_gesundheitsassistent.service;
import efi.projekt.virtueller_gesundheitsassistent.util.Logger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
/**
*
* @author naumueller
*/
public class DataPersistenceService {
private static final String DB_URL = "jdbc:sqlite:data/health.db";
public DataPersistenceService() {
init();
}
private void init() {
try (
Connection c = DriverManager.getConnection(DB_URL); Statement s = c.createStatement()) {
s.execute("""
CREATE TABLE IF NOT EXISTS binary_event (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value INTEGER NOT NULL,
timestamp DATETIME NOT NULL
)
""");
Logger.info("DB", "Datenbank initialisiert");
} catch (SQLException e) {
Logger.error("DB", "Datenbank initialisierung fehlgeschlagen", e);
}
}
public void store(int value) {
try (Connection c = DriverManager.getConnection(DB_URL); PreparedStatement ps = c.prepareStatement("INSERT INTO binary_event (value, timestamp) VALUES (?, ?)")) {
ps.setInt(1, value);
ps.setString(2, LocalDateTime.now().toString());
ps.executeUpdate();
} catch (SQLException e) {
Logger.error("DB", "Database Insert fehlgeschlagen", e);
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package efi.projekt.virtueller_gesundheitsassistent.service;
import efi.projekt.virtueller_gesundheitsassistent.model.AppState;
import efi.projekt.virtueller_gesundheitsassistent.model.ProblemLevel;
/**
*
* @author naumueller
*/
public class EvaluationService {
private final StatisticsService statisticsService;
private final AppState appState;
private final UnrealWebSocketService unrealService;
public EvaluationService(
StatisticsService statisticsService,
AppState appState,
UnrealWebSocketService unrealService
) {
this.statisticsService = statisticsService;
this.appState = appState;
this.unrealService = unrealService;
}
public void evaluate() {
double ratio = statisticsService.getRatio(10);
ProblemLevel level;
if (ratio >= 0.9) {
level = ProblemLevel.DISASTER;
} else if (ratio >= 0.7) {
level = ProblemLevel.HIGH;
} else if (ratio >= 0.4) {
level = ProblemLevel.WARNING;
} else {
level = ProblemLevel.NONE;
}
if (level != appState.getProblemLevel()) {
appState.setProblemLevel(level);
unrealService.speak(level.name());
}
}
}

View File

@ -1,6 +1,6 @@
package efi.projekt.virtueller_gesundheitsassistent.service;
import efi.projekt.virtueller_gesundheitsassistent.model.AssistantState;
import efi.projekt.virtueller_gesundheitsassistent.model.AppState;
/**
*
@ -8,11 +8,11 @@ import efi.projekt.virtueller_gesundheitsassistent.model.AssistantState;
*/
public class StateService {
private static final AssistantState STATE = new AssistantState();
private static final AppState STATE = new AppState();
private StateService() {}
public static AssistantState getState() {
public static AppState getState() {
return STATE;
}
}

View File

@ -0,0 +1,46 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package efi.projekt.virtueller_gesundheitsassistent.service;
import efi.projekt.virtueller_gesundheitsassistent.util.Logger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
*
* @author naumueller
*/
public class StatisticsService {
private static final String DB_URL = "jdbc:sqlite:data/health.db";
public double getRatio(int lastN) {
String query = """
SELECT AVG(value)
FROM (
SELECT value
FROM binary_event
ORDER BY timestamp DESC
LIMIT ?
)
""";
try (Connection c = DriverManager.getConnection(DB_URL); PreparedStatement ps = c.prepareStatement(query)) {
ps.setInt(1, lastN);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return rs.getDouble(1);
}
} catch (SQLException e) {
Logger.error("Evaluation", "Couldn't get ratio.", e);
}
return 0.0;
}
}

View File

@ -6,6 +6,7 @@ module efi.projekt.virtueller_gesundheitsassistent {
requires javafx.web;
requires jakarta.websocket.client;
requires opencv;
requires java.sql;
opens efi.projekt.virtueller_gesundheitsassistent to javafx.fxml;