ProgessLevelBar, ProcessManagement with SignallingServer
This commit is contained in:
parent
f2846aa46a
commit
99e768313d
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
7
.idea/misc.xml
generated
7
.idea/misc.xml
generated
@ -1,5 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.12 (gesundheitsassistent)" />
|
||||||
|
</component>
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="MavenProjectsManager">
|
<component name="MavenProjectsManager">
|
||||||
<option name="originalFiles">
|
<option name="originalFiles">
|
||||||
@ -8,7 +11,5 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" project-jdk-name="ms-17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" project-jdk-name="ms-17" project-jdk-type="JavaSDK" />
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
|
||||||
</component>
|
|
||||||
</project>
|
</project>
|
||||||
@ -10,7 +10,7 @@ public class ApplicationContext {
|
|||||||
private DataPersistenceService persistenceService;
|
private DataPersistenceService persistenceService;
|
||||||
private StatisticsService statisticsService;
|
private StatisticsService statisticsService;
|
||||||
private EvaluationService evaluationService;
|
private EvaluationService evaluationService;
|
||||||
private UnrealWebSocketService unrealService;
|
private AnimationFileService unrealService;
|
||||||
private MqttClientService mqttService;
|
private MqttClientService mqttService;
|
||||||
private BinaryEventService binaryEventService;
|
private BinaryEventService binaryEventService;
|
||||||
private ProcessManagerService processManagerService;
|
private ProcessManagerService processManagerService;
|
||||||
@ -31,7 +31,7 @@ public class ApplicationContext {
|
|||||||
this.evaluationService = evaluationService;
|
this.evaluationService = evaluationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUnrealService(UnrealWebSocketService unrealService) {
|
public void setAnimationFileService(AnimationFileService unrealService) {
|
||||||
this.unrealService = unrealService;
|
this.unrealService = unrealService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ public class ApplicationContext {
|
|||||||
return evaluationService;
|
return evaluationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnrealWebSocketService getUnrealService() {
|
public AnimationFileService getAnimationFileService() {
|
||||||
return unrealService;
|
return unrealService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,11 @@
|
|||||||
package vassistent.bootstrap;
|
package vassistent.bootstrap;
|
||||||
|
|
||||||
import com.formdev.flatlaf.FlatDarkLaf;
|
import com.formdev.flatlaf.FlatDarkLaf;
|
||||||
import vassistent.controller.DashboardController;
|
|
||||||
import vassistent.model.AppState;
|
import vassistent.model.AppState;
|
||||||
import vassistent.service.*;
|
import vassistent.service.*;
|
||||||
import vassistent.util.ConfigLoader;
|
import vassistent.util.ConfigLoader;
|
||||||
import vassistent.util.Logger;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class ApplicationInitializer {
|
public class ApplicationInitializer {
|
||||||
@ -26,8 +23,8 @@ public class ApplicationInitializer {
|
|||||||
context.setAppState(new AppState());
|
context.setAppState(new AppState());
|
||||||
|
|
||||||
// ===== Infrastructure Services =====
|
// ===== Infrastructure Services =====
|
||||||
context.setUnrealService(
|
context.setAnimationFileService(
|
||||||
new UnrealWebSocketService("ws://localhost:8888/avatar")
|
new AnimationFileService()
|
||||||
);
|
);
|
||||||
|
|
||||||
context.setMqttService(new MqttClientService(context.getAppState()));
|
context.setMqttService(new MqttClientService(context.getAppState()));
|
||||||
@ -42,7 +39,7 @@ public class ApplicationInitializer {
|
|||||||
new EvaluationService(
|
new EvaluationService(
|
||||||
context.getStatisticsService(),
|
context.getStatisticsService(),
|
||||||
context.getAppState(),
|
context.getAppState(),
|
||||||
context.getUnrealService()
|
context.getAnimationFileService()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,25 +1,58 @@
|
|||||||
package vassistent.bootstrap;
|
package vassistent.bootstrap;
|
||||||
|
|
||||||
|
import vassistent.service.MqttClientService;
|
||||||
|
import vassistent.service.ProcessManagerService;
|
||||||
|
import vassistent.util.Logger;
|
||||||
|
|
||||||
public class ApplicationShutdownManager {
|
public class ApplicationShutdownManager {
|
||||||
|
|
||||||
private final ApplicationContext context;
|
private final ApplicationContext context;
|
||||||
|
|
||||||
public ApplicationShutdownManager(ApplicationContext context) {
|
public ApplicationShutdownManager(ApplicationContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
|
Runtime.getRuntime().addShutdownHook(
|
||||||
|
new Thread(this::shutdown)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|
||||||
if (context.getMqttService() != null) {
|
Logger.info("SHUTDOWN", "Shutdown Sequencing gestartet");
|
||||||
context.getMqttService().disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.getUnrealService() != null) {
|
disconnectMqtt();
|
||||||
context.getUnrealService().disconnect();
|
stopExternalProcesses();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.getProcessManagerService() != null) {
|
private void disconnectMqtt() {
|
||||||
context.getProcessManagerService().shutdown();
|
|
||||||
|
try {
|
||||||
|
MqttClientService mqtt = context.getMqttService();
|
||||||
|
|
||||||
|
if (mqtt != null) {
|
||||||
|
mqtt.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.info("SHUTDOWN", "MQTT getrennt");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.error("SHUTDOWN", "MQTT Shutdown Fehler", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopExternalProcesses() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
ProcessManagerService pm = context.getProcessManagerService();
|
||||||
|
|
||||||
|
if (pm != null) {
|
||||||
|
pm.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.info("SHUTDOWN", "Externe Prozesse beendet");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.error("SHUWTDOWN", "Process Shutdown Fehler", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,11 @@ import vassistent.bootstrap.ApplicationShutdownManager;
|
|||||||
import vassistent.model.AppState;
|
import vassistent.model.AppState;
|
||||||
import vassistent.ui.AppWindow;
|
import vassistent.ui.AppWindow;
|
||||||
import vassistent.ui.DashboardView;
|
import vassistent.ui.DashboardView;
|
||||||
|
import vassistent.ui.PixelStreamingView;
|
||||||
import vassistent.util.Logger;
|
import vassistent.util.Logger;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
|
|
||||||
@ -28,6 +31,7 @@ public class AppWindowController {
|
|||||||
window = new AppWindow();
|
window = new AppWindow();
|
||||||
|
|
||||||
DashboardView dashboardView = window.getDashboardView();
|
DashboardView dashboardView = window.getDashboardView();
|
||||||
|
PixelStreamingView pixelStreamingView = window.getStreamingView();
|
||||||
|
|
||||||
DashboardController dashboardController =
|
DashboardController dashboardController =
|
||||||
new DashboardController(
|
new DashboardController(
|
||||||
@ -36,8 +40,16 @@ public class AppWindowController {
|
|||||||
context.getAppState()
|
context.getAppState()
|
||||||
);
|
);
|
||||||
|
|
||||||
window.getRefreshDashboardButton()
|
StreamingController previewController = new StreamingController(pixelStreamingView);
|
||||||
.addActionListener(e -> dashboardController.loadChartData());
|
|
||||||
|
dashboardView.getReloadPixelStreamingViewButton()
|
||||||
|
.addActionListener(e ->
|
||||||
|
previewController.reloadStream("http://141.75.215.233")
|
||||||
|
);
|
||||||
|
|
||||||
|
dashboardView.getOpenFullscreenButton()
|
||||||
|
.addActionListener(e ->
|
||||||
|
window.getStreamingView().requestFocus());
|
||||||
|
|
||||||
window.addWindowListener(new WindowAdapter() {
|
window.addWindowListener(new WindowAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@ -66,17 +78,21 @@ public class AppWindowController {
|
|||||||
|
|
||||||
AppState state = context.getAppState();
|
AppState state = context.getAppState();
|
||||||
|
|
||||||
state.addListener(appState -> {
|
state.addListener(this::onStateChanged);
|
||||||
|
|
||||||
/*Logger.debug("Controller",
|
Logger.info("Controller",
|
||||||
"AppState Update erhalten: " +
|
"AppState Observer registriert");
|
||||||
appState.getProblemLevel());*/
|
}
|
||||||
|
|
||||||
if (window == null) {
|
private void onStateChanged(AppState appState) {
|
||||||
Logger.warn("Controller",
|
|
||||||
"Window ist null, UI Update übersprungen");
|
if (window == null) {
|
||||||
return;
|
Logger.warn("Controller",
|
||||||
}
|
"Window ist null, UI Update übersprungen");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
|
||||||
window.updateProblemLevel(
|
window.updateProblemLevel(
|
||||||
appState.getProblemLevel().name()
|
appState.getProblemLevel().name()
|
||||||
@ -87,11 +103,8 @@ public class AppWindowController {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Logger.debug("Controller",
|
Logger.debug("Controller",
|
||||||
"ProblemLevel UI aktualisiert → " +
|
"ProblemLevel UI aktualisiert → "
|
||||||
appState.getProblemLevel());
|
+ appState.getProblemLevel());
|
||||||
});
|
});
|
||||||
|
|
||||||
Logger.info("Controller",
|
|
||||||
"AppState Observer registriert");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import vassistent.model.RatioPoint;
|
|||||||
import vassistent.service.StatisticsService;
|
import vassistent.service.StatisticsService;
|
||||||
import vassistent.ui.DashboardView;
|
import vassistent.ui.DashboardView;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DashboardController {
|
public class DashboardController {
|
||||||
@ -21,14 +22,23 @@ public class DashboardController {
|
|||||||
this.statisticsService = statisticsService;
|
this.statisticsService = statisticsService;
|
||||||
this.dashboardView = dashboardView;
|
this.dashboardView = dashboardView;
|
||||||
|
|
||||||
appState.addListener(state -> {
|
appState.addListener(this::onStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
if (state.getDataVersion() != lastDataVersion) {
|
private void onStateChanged(AppState state) {
|
||||||
lastDataVersion = state.getDataVersion();
|
|
||||||
|
|
||||||
List<RatioPoint> points = statisticsService.getLastNAverages(20);
|
List<RatioPoint> points =
|
||||||
dashboardView.updateChart(points);
|
statisticsService.getLastNAverages(20);
|
||||||
}
|
|
||||||
|
if (points.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
double ratio = points.get(points.size() - 1).getRatio();
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
|
||||||
|
dashboardView.updateChart(points);
|
||||||
|
dashboardView.updateProblemLevel(ratio);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class AppState {
|
|||||||
|
|
||||||
public void setProblemLevel(ProblemLevel problemLevel) {
|
public void setProblemLevel(ProblemLevel problemLevel) {
|
||||||
this.problemLevel = problemLevel;
|
this.problemLevel = problemLevel;
|
||||||
|
dataVersion++;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,13 +41,4 @@ public class AppState {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDataVersion() {
|
|
||||||
return dataVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void incrementDataVersion() {
|
|
||||||
dataVersion++;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
50
src/main/java/vassistent/service/AnimationFileService.java
Normal file
50
src/main/java/vassistent/service/AnimationFileService.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package vassistent.service;
|
||||||
|
|
||||||
|
import vassistent.model.ProblemLevel;
|
||||||
|
import vassistent.util.Logger;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import jakarta.websocket.*;
|
||||||
|
|
||||||
|
public class AnimationFileService {
|
||||||
|
private static final String PATH = "C:\\Privat\\Dokumente\\Niklas_Aumueller\\TH\\MSY\\Semester_2\\animation.json";
|
||||||
|
|
||||||
|
public void wirteAnimationState(ProblemLevel level) {
|
||||||
|
|
||||||
|
String animation = mapLevelToAnimation(level);
|
||||||
|
|
||||||
|
File file = new File(PATH);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
String json = """
|
||||||
|
{
|
||||||
|
"animation": "%s"
|
||||||
|
}
|
||||||
|
""".formatted(animation);
|
||||||
|
|
||||||
|
try (FileWriter writer = new FileWriter(file, false)) {
|
||||||
|
writer.write(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.info("ANIMATION FILE", "Animation json geschrieben");
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.error("ANIMATION FILE", "Fehler beim Schreiben der Animation Datei", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String mapLevelToAnimation(ProblemLevel level) {
|
||||||
|
|
||||||
|
return switch (level) {
|
||||||
|
case NONE -> "no";
|
||||||
|
case WARNING -> "warning";
|
||||||
|
case HIGH -> "high";
|
||||||
|
case DISASTER -> "disaster";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,28 +7,26 @@ import vassistent.model.ProblemLevel;
|
|||||||
public class EvaluationService {
|
public class EvaluationService {
|
||||||
private final StatisticsService statisticsService;
|
private final StatisticsService statisticsService;
|
||||||
private final AppState appState;
|
private final AppState appState;
|
||||||
private final UnrealWebSocketService unrealService;
|
private final AnimationFileService animationFileService;
|
||||||
|
|
||||||
public EvaluationService(
|
public EvaluationService(
|
||||||
StatisticsService statisticsService,
|
StatisticsService statisticsService,
|
||||||
AppState appState,
|
AppState appState,
|
||||||
UnrealWebSocketService unrealService
|
AnimationFileService animationFileService
|
||||||
) {
|
) {
|
||||||
|
|
||||||
this.statisticsService = statisticsService;
|
this.statisticsService = statisticsService;
|
||||||
this.appState = appState;
|
this.appState = appState;
|
||||||
this.unrealService = unrealService;
|
this.animationFileService = animationFileService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void evaluate() {
|
public void evaluate() {
|
||||||
double ratio = statisticsService.getRatio(10);
|
double ratio = statisticsService.getRatio(20);
|
||||||
|
|
||||||
ProblemLevel level = calculateLevel(ratio);
|
ProblemLevel level = calculateLevel(ratio);
|
||||||
|
|
||||||
appState.setProblemLevel(level);
|
appState.setProblemLevel(level);
|
||||||
unrealService.speak(level.name());
|
animationFileService.wirteAnimationState(level);
|
||||||
|
|
||||||
appState.incrementDataVersion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProblemLevel calculateLevel(Double ratio) {
|
private ProblemLevel calculateLevel(Double ratio) {
|
||||||
|
|||||||
@ -23,7 +23,6 @@ public class MqttClientService implements MqttCallback {
|
|||||||
|
|
||||||
public MqttClientService(AppState appState) {
|
public MqttClientService(AppState appState) {
|
||||||
this.appState = appState;
|
this.appState = appState;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client = new MqttClient(
|
client = new MqttClient(
|
||||||
BROKER_URL,
|
BROKER_URL,
|
||||||
@ -107,6 +106,7 @@ public class MqttClientService implements MqttCallback {
|
|||||||
Consumer<String> listener = topicListeners.get(topic);
|
Consumer<String> listener = topicListeners.get(topic);
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.accept(payload);
|
listener.accept(payload);
|
||||||
|
Logger.debug("MQTT", "Payload accepted");
|
||||||
} else {
|
} else {
|
||||||
Logger.warn(
|
Logger.warn(
|
||||||
"MQTT",
|
"MQTT",
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
package vassistent.service;
|
|
||||||
|
|
||||||
public class PixelStreamingService {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -12,6 +12,7 @@ public class ProcessManagerService {
|
|||||||
|
|
||||||
private Process pythonProcess;
|
private Process pythonProcess;
|
||||||
private Process unrealProcess;
|
private Process unrealProcess;
|
||||||
|
private Process unrealSignallingProcess;
|
||||||
|
|
||||||
public ProcessManagerService(Properties config) {
|
public ProcessManagerService(Properties config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
@ -54,34 +55,92 @@ public class ProcessManagerService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String exe = config.getProperty("unreal.executable");
|
startSignallingServer();
|
||||||
|
startUnrealEngine();
|
||||||
ProcessBuilder pb = new ProcessBuilder(
|
|
||||||
exe,
|
|
||||||
"-RenderOffScreen",
|
|
||||||
"-NoSound",
|
|
||||||
"-PixelStreamingSignallingURL=ws://127.0.0.1:8888"
|
|
||||||
);
|
|
||||||
|
|
||||||
pb.redirectErrorStream(true);
|
|
||||||
|
|
||||||
unrealProcess = pb.start();
|
|
||||||
|
|
||||||
Logger.info("PROCESS", "Unreal Engine Avatar");
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logger.error("PROCESS", "Unreal Engine Start fehlgeschlagen", e);
|
Logger.error("PROCESS", "Unreal Start fehlgeschlagen", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startSignallingServer() throws IOException {
|
||||||
|
|
||||||
|
String script =
|
||||||
|
config.getProperty("unreal.signalling_server.script");
|
||||||
|
|
||||||
|
if (script == null) return;
|
||||||
|
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
|
"cmd",
|
||||||
|
"/c",
|
||||||
|
script);
|
||||||
|
|
||||||
|
pb.redirectErrorStream(true);
|
||||||
|
|
||||||
|
unrealSignallingProcess = pb.start();
|
||||||
|
|
||||||
|
Logger.info("PROCESS",
|
||||||
|
"Unreal Signalling Server gestartet" + pb.command());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startUnrealEngine() throws IOException {
|
||||||
|
|
||||||
|
String exe =
|
||||||
|
config.getProperty("unreal.executable");
|
||||||
|
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
|
exe,
|
||||||
|
"-PixelStreamingURL=ws://127.0.0.1:8888",
|
||||||
|
"-RenderOffscreen",
|
||||||
|
"-NoSound"
|
||||||
|
);
|
||||||
|
|
||||||
|
pb.directory(new File(exe).getParentFile());
|
||||||
|
|
||||||
|
pb.redirectErrorStream(true);
|
||||||
|
|
||||||
|
unrealProcess = pb.start();
|
||||||
|
|
||||||
|
Logger.info("PROCESS",
|
||||||
|
"Unreal Engine gestartet" + pb.command());
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|
||||||
if (pythonProcess != null)
|
Logger.info("PROCESS", "Shutdown externe Prozesse gestartet");
|
||||||
pythonProcess.destroyForcibly();
|
|
||||||
|
|
||||||
if (unrealProcess != null)
|
terminateProcess(pythonProcess);
|
||||||
unrealProcess.destroyForcibly();
|
terminateProcess(unrealProcess);
|
||||||
|
terminateProcess(unrealSignallingProcess);
|
||||||
|
|
||||||
Logger.info("PROCESS", "Externe Prozesse beendet");
|
Logger.info("PROCESS", "Externe Prozesse beendet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void terminateProcess(Process process) {
|
||||||
|
|
||||||
|
if (process == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
long pid = process.pid();
|
||||||
|
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
|
"taskkill",
|
||||||
|
"/PID",
|
||||||
|
String.valueOf(pid),
|
||||||
|
"/T",
|
||||||
|
"/F"
|
||||||
|
);
|
||||||
|
|
||||||
|
pb.start().waitFor();
|
||||||
|
|
||||||
|
Logger.info("PROCESS",
|
||||||
|
"Process Tree beendet → PID " + pid);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.error("PROCESS",
|
||||||
|
"Fehler beim Prozess Kill", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
package vassistent.service;
|
|
||||||
|
|
||||||
import vassistent.model.AppState;
|
|
||||||
|
|
||||||
public class StateService {
|
|
||||||
private static final AppState STATE = new AppState();
|
|
||||||
|
|
||||||
private StateService() {}
|
|
||||||
|
|
||||||
public static AppState getState() {
|
|
||||||
return STATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
package vassistent.service;
|
|
||||||
|
|
||||||
import vassistent.util.Logger;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import jakarta.websocket.*;
|
|
||||||
|
|
||||||
public class UnrealWebSocketService {
|
|
||||||
|
|
||||||
private Session session;
|
|
||||||
private final URI serverUri;
|
|
||||||
private final AtomicBoolean connected = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
|
|
||||||
public UnrealWebSocketService(String serverUrl) {
|
|
||||||
this.serverUri = URI.create(serverUrl);
|
|
||||||
//connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void connect() {
|
|
||||||
try {
|
|
||||||
WebSocketContainer container =
|
|
||||||
ContainerProvider.getWebSocketContainer();
|
|
||||||
|
|
||||||
Logger.info("UNREAL", "Verbinde zu " + serverUri);
|
|
||||||
container.connectToServer(this, serverUri);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.error("UNREAL", "WebSocket-Verbindung fehlgeschlagen", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConnected() {
|
|
||||||
return connected.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect() {
|
|
||||||
try {
|
|
||||||
if (session != null && session.isOpen()) {
|
|
||||||
session.close();
|
|
||||||
Logger.info("UNREAL", "WebSocket-Verbindung geschlossen");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.error("UNREAL", "Fehler beim Schließen der Verbindung", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnOpen
|
|
||||||
public void onOpen(Session session) {
|
|
||||||
this.session = session;
|
|
||||||
connected.set(true);
|
|
||||||
Logger.info("UNREAL", "WebSocket verbunden");
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClose
|
|
||||||
public void onClose(Session session, CloseReason reason) {
|
|
||||||
connected.set(false);
|
|
||||||
Logger.warn("UNREAL", "WebSocket geschlossen: " + reason.getReasonPhrase());
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnError
|
|
||||||
public void onError(Session session, Throwable throwable) {
|
|
||||||
connected.set(false);
|
|
||||||
Logger.error("UNREAL", "WebSocket-Fehler", throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnMessage
|
|
||||||
public void onMessage(String message) {
|
|
||||||
Logger.debug("UNREAL", "Nachricht empfangen: " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void speak(String text) {
|
|
||||||
if (!connected.get()) {
|
|
||||||
//Logger.warn("UNREAL", "Nicht verbunden! Text wird nicht gesendet!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String json = buildSpeakMessage(text);
|
|
||||||
|
|
||||||
session.getAsyncRemote().sendText(json);
|
|
||||||
Logger.info("UNREAL", "Sende Speak-Command: " + text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String buildSpeakMessage(String text) {
|
|
||||||
return "{"
|
|
||||||
+ "\"type\":\"speak\","
|
|
||||||
+ "\"text\":\"" + escape(text) + "\""
|
|
||||||
+ "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String escape(String text) {
|
|
||||||
return text.replace("\"", "\\\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -10,15 +10,11 @@ public class AppWindow extends JFrame {
|
|||||||
|
|
||||||
private PixelStreamingView streamingView;
|
private PixelStreamingView streamingView;
|
||||||
private DashboardView dashboardView;
|
private DashboardView dashboardView;
|
||||||
|
private JTabbedPane tabs;
|
||||||
|
|
||||||
private JLabel mqttStatusLabel;
|
private JLabel mqttStatusLabel;
|
||||||
private JLabel websocketStatusLabel;
|
|
||||||
private JLabel problemLevelLabel;
|
private JLabel problemLevelLabel;
|
||||||
|
|
||||||
private JButton refreshDashboardButton;
|
|
||||||
private JButton reloadStreamButton;
|
|
||||||
private JButton fullscreenButton;
|
|
||||||
|
|
||||||
public AppWindow() {
|
public AppWindow() {
|
||||||
|
|
||||||
setTitle("Virtueller Gesundheitsassistent");
|
setTitle("Virtueller Gesundheitsassistent");
|
||||||
@ -28,41 +24,27 @@ public class AppWindow extends JFrame {
|
|||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
add(createToolbar(), BorderLayout.NORTH);
|
streamingView = new PixelStreamingView(
|
||||||
add(createTabPane(), BorderLayout.CENTER);
|
"http://localhost:80",
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
dashboardView = new DashboardView();
|
||||||
|
|
||||||
|
tabs = createTabPane();
|
||||||
|
add(tabs, BorderLayout.CENTER);
|
||||||
add(createStatusBar(), BorderLayout.SOUTH);
|
add(createStatusBar(), BorderLayout.SOUTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------- Toolbar ----------------
|
|
||||||
|
|
||||||
private JPanel createToolbar() {
|
|
||||||
|
|
||||||
JPanel toolbar = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
||||||
|
|
||||||
refreshDashboardButton = new JButton("Dashboard Refresh");
|
|
||||||
reloadStreamButton = new JButton("Stream Reload");
|
|
||||||
fullscreenButton = new JButton("Fullscreen Stream");
|
|
||||||
|
|
||||||
toolbar.add(refreshDashboardButton);
|
|
||||||
toolbar.add(reloadStreamButton);
|
|
||||||
toolbar.add(fullscreenButton);
|
|
||||||
|
|
||||||
return toolbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------- Tabs ----------------
|
// ---------------- Tabs ----------------
|
||||||
|
|
||||||
private JTabbedPane createTabPane() {
|
private JTabbedPane createTabPane() {
|
||||||
|
|
||||||
JTabbedPane tabs = new JTabbedPane();
|
JTabbedPane tabs = new JTabbedPane();
|
||||||
|
|
||||||
streamingView = new PixelStreamingView(
|
JPanel streamingPanel = new JPanel(new BorderLayout());
|
||||||
"http://141.75.215.233",
|
streamingPanel.add(streamingView, BorderLayout.CENTER);
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
dashboardView = new DashboardView();
|
|
||||||
|
|
||||||
tabs.addTab("Avatar Streaming", streamingView);
|
tabs.addTab("Avatar Streaming", streamingView);
|
||||||
tabs.addTab("Dashboard", dashboardView);
|
tabs.addTab("Dashboard", dashboardView);
|
||||||
@ -77,13 +59,10 @@ public class AppWindow extends JFrame {
|
|||||||
JPanel statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
JPanel statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||||
|
|
||||||
mqttStatusLabel = new JLabel("MQTT: Disconnected");
|
mqttStatusLabel = new JLabel("MQTT: Disconnected");
|
||||||
websocketStatusLabel = new JLabel();
|
|
||||||
problemLevelLabel = new JLabel("Problem: NONE");
|
problemLevelLabel = new JLabel("Problem: NONE");
|
||||||
|
|
||||||
statusBar.add(mqttStatusLabel);
|
statusBar.add(mqttStatusLabel);
|
||||||
statusBar.add(new JLabel(" | "));
|
statusBar.add(new JLabel(" | "));
|
||||||
statusBar.add(websocketStatusLabel);
|
|
||||||
statusBar.add(new JLabel(" | "));
|
|
||||||
statusBar.add(problemLevelLabel);
|
statusBar.add(problemLevelLabel);
|
||||||
|
|
||||||
return statusBar;
|
return statusBar;
|
||||||
@ -94,11 +73,6 @@ public class AppWindow extends JFrame {
|
|||||||
(connected ? "Connected" : "Disconnected"));
|
(connected ? "Connected" : "Disconnected"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateWebsocketStatus(boolean connected) {
|
|
||||||
websocketStatusLabel.setText("WebSocket: " +
|
|
||||||
(connected ? "Connected" : "Disconnected"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateProblemLevel(String level) {
|
public void updateProblemLevel(String level) {
|
||||||
problemLevelLabel.setText("Problem: " + level);
|
problemLevelLabel.setText("Problem: " + level);
|
||||||
}
|
}
|
||||||
@ -111,15 +85,7 @@ public class AppWindow extends JFrame {
|
|||||||
return streamingView;
|
return streamingView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JButton getRefreshDashboardButton() {
|
public JTabbedPane getTabs() {
|
||||||
return refreshDashboardButton;
|
return tabs;
|
||||||
}
|
|
||||||
|
|
||||||
public JButton getReloadStreamButton() {
|
|
||||||
return reloadStreamButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JButton getFullscreenButton() {
|
|
||||||
return fullscreenButton;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import org.jfree.data.category.DefaultCategoryDataset;
|
|||||||
import org.jfree.data.time.Millisecond;
|
import org.jfree.data.time.Millisecond;
|
||||||
import org.jfree.data.time.TimeSeries;
|
import org.jfree.data.time.TimeSeries;
|
||||||
import org.jfree.data.time.TimeSeriesCollection;
|
import org.jfree.data.time.TimeSeriesCollection;
|
||||||
|
import vassistent.model.ProblemLevel;
|
||||||
import vassistent.model.RatioPoint;
|
import vassistent.model.RatioPoint;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@ -20,14 +21,23 @@ import java.util.List;
|
|||||||
public class DashboardView extends JPanel {
|
public class DashboardView extends JPanel {
|
||||||
|
|
||||||
private TimeSeries series;
|
private TimeSeries series;
|
||||||
|
private ProblemLevelBar levelBar;
|
||||||
|
|
||||||
|
private JButton reloadPixelStreamingViewButton;
|
||||||
|
private JButton openFullscreenButton;
|
||||||
|
|
||||||
public DashboardView() {
|
public DashboardView() {
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
// ---------- TOP: Problem Level ----------
|
||||||
|
levelBar = new ProblemLevelBar();
|
||||||
|
add(levelBar, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
// ---------- CENTER: Chart ----------
|
||||||
|
|
||||||
series = new TimeSeries("Ratio");
|
series = new TimeSeries("Ratio");
|
||||||
|
|
||||||
TimeSeriesCollection dataset =
|
TimeSeriesCollection dataset = new TimeSeriesCollection(series);
|
||||||
new TimeSeriesCollection(series);
|
|
||||||
|
|
||||||
JFreeChart chart = ChartFactory.createTimeSeriesChart(
|
JFreeChart chart = ChartFactory.createTimeSeriesChart(
|
||||||
"Ratio Verlauf",
|
"Ratio Verlauf",
|
||||||
@ -36,9 +46,27 @@ public class DashboardView extends JPanel {
|
|||||||
dataset
|
dataset
|
||||||
);
|
);
|
||||||
|
|
||||||
ChartPanel chartPanel = new ChartPanel(chart);
|
add(new ChartPanel(chart), BorderLayout.CENTER);
|
||||||
|
|
||||||
add(chartPanel, BorderLayout.CENTER);
|
// ---------- SOUTH: Preview + Buttons ----------
|
||||||
|
add(createBottomPanel(), BorderLayout.SOUTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel createBottomPanel() {
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||||
|
|
||||||
|
reloadPixelStreamingViewButton = new JButton("Reload Preview");
|
||||||
|
openFullscreenButton = new JButton("Open Fullscreen");
|
||||||
|
|
||||||
|
buttonPanel.add(reloadPixelStreamingViewButton);
|
||||||
|
buttonPanel.add(openFullscreenButton);
|
||||||
|
|
||||||
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateChart(List<RatioPoint> points) {
|
public void updateChart(List<RatioPoint> points) {
|
||||||
@ -59,5 +87,15 @@ public class DashboardView extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateProblemLevel(double ratio) {
|
||||||
|
levelBar.setRatio(ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JButton getReloadPixelStreamingViewButton() {
|
||||||
|
return reloadPixelStreamingViewButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JButton getOpenFullscreenButton() {
|
||||||
|
return openFullscreenButton;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
89
src/main/java/vassistent/ui/ProblemLevelBar.java
Normal file
89
src/main/java/vassistent/ui/ProblemLevelBar.java
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package vassistent.ui;
|
||||||
|
|
||||||
|
import vassistent.model.ProblemLevel;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class ProblemLevelBar extends JPanel {
|
||||||
|
|
||||||
|
private double ratio = 0.0;
|
||||||
|
private ProblemLevel level = ProblemLevel.NONE;
|
||||||
|
|
||||||
|
public ProblemLevelBar() {
|
||||||
|
setPreferredSize(new Dimension(100, 50));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRatio(double ratio) {
|
||||||
|
this.ratio = Math.max(0.0, Math.min(1.0, ratio));
|
||||||
|
this.level = calculateLevel(this.ratio);
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProblemLevel calculateLevel(Double ratio) {
|
||||||
|
if (ratio >= 0.9) {
|
||||||
|
return ProblemLevel.DISASTER;
|
||||||
|
} else if (ratio >= 0.8) {
|
||||||
|
return ProblemLevel.HIGH;
|
||||||
|
} else if (ratio >= 0.5) {
|
||||||
|
return ProblemLevel.WARNING;
|
||||||
|
} else {
|
||||||
|
return ProblemLevel.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
|
||||||
|
int width = getWidth();
|
||||||
|
int height = getHeight();
|
||||||
|
|
||||||
|
Graphics2D g2 = (Graphics2D) g;
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
// --- Hintergrund ---
|
||||||
|
g2.setColor(Color.LIGHT_GRAY);
|
||||||
|
g2.fillRoundRect(0, 0, width, height, 20, 20);
|
||||||
|
|
||||||
|
// --- Gefüllter Bereich ---
|
||||||
|
int filledWidth = (int) (width * ratio);
|
||||||
|
|
||||||
|
Color baseColor = getColorForLevel(level);
|
||||||
|
Color darkerColor = baseColor.darker();
|
||||||
|
|
||||||
|
GradientPaint gradient = new GradientPaint(
|
||||||
|
0, 0, darkerColor,
|
||||||
|
filledWidth, 0, baseColor
|
||||||
|
);
|
||||||
|
|
||||||
|
g2.setPaint(gradient);
|
||||||
|
g2.fillRoundRect(0, 0, filledWidth, height, 20, 20);
|
||||||
|
|
||||||
|
// --- Text ---
|
||||||
|
String text = level.name() + " (" + (int)(ratio * 100) + "%)";
|
||||||
|
FontMetrics fm = g2.getFontMetrics();
|
||||||
|
int textWidth = fm.stringWidth(text);
|
||||||
|
|
||||||
|
g2.setColor(Color.BLACK);
|
||||||
|
g2.drawString(
|
||||||
|
text,
|
||||||
|
(width - textWidth) / 2,
|
||||||
|
(height + fm.getAscent()) / 2 - 3
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color getColorForLevel(ProblemLevel level) {
|
||||||
|
switch (level) {
|
||||||
|
case DISASTER:
|
||||||
|
return new Color(200, 0, 0);
|
||||||
|
case HIGH:
|
||||||
|
return new Color(255, 140, 0);
|
||||||
|
case WARNING:
|
||||||
|
return new Color(255, 215, 0);
|
||||||
|
default:
|
||||||
|
return new Color(0, 170, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,16 +2,16 @@
|
|||||||
app.mode=test
|
app.mode=test
|
||||||
|
|
||||||
# ===== PYTHON =====
|
# ===== PYTHON =====
|
||||||
python.path="C:\\Program Files\\PyManager\\python.exe"
|
python.path=C:\\Program Files\\PyManager\\python.exe
|
||||||
|
|
||||||
# ===== MQTT CLIENT =====
|
# ===== MQTT CLIENT =====
|
||||||
mqtt.topic=PREDICTION
|
mqtt.topic=PREDICTION
|
||||||
|
|
||||||
# ===== MQTT SIMULATOR =====
|
# ===== MQTT SIMULATOR =====
|
||||||
mqtt_sim.enabled=false
|
mqtt_sim.enabled=true
|
||||||
mqtt_sim.script=src/main/resources/scripts/mqtt_simulator.py
|
mqtt_sim.script=src/main/resources/scripts/mqtt_simulator.py
|
||||||
|
|
||||||
# ===== UNREAL ENGINE =====
|
# ===== UNREAL ENGINE =====
|
||||||
unreal.enabled=false
|
unreal.enabled=true
|
||||||
unreal.executable=external/unreal/avatar.exe
|
unreal.executable=C:\\Privat\\Dokumente\\Niklas_Aumueller\\TH\\MSY\\Semester_2\\Projektarbeit\\Windows\\Prototyp1.exe
|
||||||
unreal.signalling_server.script=external/unreal/start.bat
|
unreal.signalling_server.script=C:\\Privat\\Dokumente\\Niklas_Aumueller\\TH\\MSY\\Semester_2\\Projektarbeit\\Windows\\Prototyp1\\Samples\\PixelStreaming\\WebServers\\SignallingWebServer\\platform_scripts\\cmd\\start_with_stun.bat
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
import sys
|
import sys
|
||||||
import random
|
import random
|
||||||
@ -44,17 +46,26 @@ def main():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
logging.info(f"Verbinde mit Broker {BROKER}:{PORT}")
|
logging.info(f"Verbinde mit Broker {BROKER}:{PORT}")
|
||||||
|
|
||||||
client.connect(BROKER, PORT, 60)
|
client.connect(BROKER, PORT, 60)
|
||||||
client.loop_start()
|
client.loop_start()
|
||||||
|
|
||||||
logging.info("Starte kontinuierliches Senden...")
|
logging.info("Starte kontinuierliches Senden...")
|
||||||
|
|
||||||
while True:
|
current_id = 1
|
||||||
message = random.randint(0, 1)
|
|
||||||
|
|
||||||
client.publish(TOPIC, message, qos=QOS)
|
while True:
|
||||||
logging.info(f"Gesendet an '{TOPIC}': {message}")
|
payload = {
|
||||||
|
"valid": True,
|
||||||
|
"_id": current_id,
|
||||||
|
"prediction": random.randint(0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
json_payload = json.dumps(payload)
|
||||||
|
|
||||||
|
client.publish(TOPIC, json_payload, qos=QOS)
|
||||||
|
logging.info(f"Gesendet an '{TOPIC}': {json_payload}")
|
||||||
|
|
||||||
|
current_id += 1
|
||||||
|
|
||||||
time.sleep(INTERVAL_SECONDS)
|
time.sleep(INTERVAL_SECONDS)
|
||||||
|
|
||||||
|
|||||||
@ -12,14 +12,14 @@ class EvaluationServiceTest {
|
|||||||
|
|
||||||
private StatisticsService statisticsService;
|
private StatisticsService statisticsService;
|
||||||
private AppState appState;
|
private AppState appState;
|
||||||
private UnrealWebSocketService unrealService;
|
private AnimationFileService unrealService;
|
||||||
private EvaluationService evaluationService;
|
private EvaluationService evaluationService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
statisticsService = mock(StatisticsService.class);
|
statisticsService = mock(StatisticsService.class);
|
||||||
appState = new AppState();
|
appState = new AppState();
|
||||||
unrealService = mock(UnrealWebSocketService.class);
|
unrealService = mock(AnimationFileService.class);
|
||||||
evaluationService = new EvaluationService(statisticsService, appState, unrealService);
|
evaluationService = new EvaluationService(statisticsService, appState, unrealService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user