Added sport activity abstraction classes

This commit is contained in:
Luca Warmenhoven
2024-05-17 12:32:54 +02:00
parent a4a01ae9ef
commit 59c374eb02
8 changed files with 268 additions and 8 deletions

View File

@@ -0,0 +1,123 @@
package com.example.fitbot.exercise;
import android.util.Log;
import com.example.fitbot.util.path.GesturePath;
import com.example.fitbot.util.server.IWebSocketHandler;
import com.example.fitbot.util.server.WebSocket;
import java.util.Objects;
public abstract class AbstractExercise implements IWebSocketHandler {
private EMuscleGroup muscleGroup;
private EExerciseType exerciseType;
private GesturePath path;
// Static fields.
private static WebSocket webSocket;
private static AbstractExercise currentExercise = null;
/**
* Constructor for the AbstractExercise class.
*
* @param muscleGroup The muscle group of the exercise.
* @param exerciseType The type of exercise.
* @param path The path of the exercise.
*/
public AbstractExercise(EMuscleGroup muscleGroup, EExerciseType exerciseType, GesturePath path) {
this.muscleGroup = muscleGroup;
this.exerciseType = exerciseType;
this.path = path;
}
/**
* Start the exercise.
* This method starts a WebSocket server
*/
public void startExercise() {
// Ensure no other exercise is active.
if (currentExercise != null && currentExercise != this) {
currentExercise.__stopExercise();
Log.i("Exercises", "Another exercise was started when another was still running.");
}
// If a WebSocket server is already running, change the event handler to be this class.
if (webSocket != null && webSocket.isConnected()) {
webSocket.setEventHandler(this);
}
try {
webSocket = WebSocket.createServer();
Objects.requireNonNull(webSocket, "WebSocket server could not be created.");
webSocket.startListening();
webSocket.setEventHandler(this);
currentExercise = this;
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Method for ending this exercise and returning the grade of the performance
* of this activity.
*/
public final double finishExercise() {
this.__stopExercise();
// TODO: Implement grade calculation
return 0.0;
}
/**
* Stop the exercise.
* This method stops the WebSocket server.
*/
private void __stopExercise() {
if (webSocket != null && webSocket.isConnected()) {
webSocket.stop();
webSocket = null;
}
}
/**
* Method for checking whether the activity is finished.
*/
public abstract boolean isActivityFinished();
/**
* Method for stopping this exercise.
*/
public abstract void stopExercise();
/**
* Check if the current exercise is the current activity.
*/
public final boolean isCurrentActivity() {
return currentExercise == this;
}
/**
* Get the muscle group of the exercise.
*/
public EMuscleGroup getMuscleGroup() {
return muscleGroup;
}
/**
* Get the exercise type.
*/
public EExerciseType getExerciseType() {
return exerciseType;
}
/**
* Get the path of the exercise.
*/
public GesturePath getPath() {
return path;
}
}

View File

@@ -1,13 +1,13 @@
package com.example.fitbot.sports;
package com.example.fitbot.exercise;
public enum ESportType {
public enum EExerciseType {
FITNESS("Fitness"),
POWER("Krachttrening");
private final String name;
ESportType(String name) {
EExerciseType(String name) {
this.name = name;
}

View File

@@ -0,0 +1,5 @@
package com.example.fitbot.exercise;
public enum EMuscleGroup {
// TODO: Implement
}

View File

@@ -0,0 +1,53 @@
package com.example.fitbot.exercise;
/**
* The ExerciseUser class represents a user of the exercise application.
* This contains all necessary information of the current user.
*/
public class ExerciseUser {
public float upperArmLength;
public float lowerArmLength;
public float upperLegLength;
public float lowerLegLength;
public float height;
/**
* Constructor for the ExerciseUser class.
* @param upperArmLength The length of the upper arm.
* @param lowerArmLength The length of the lower arm.
* @param height The height of the user.
* @param upperLegLength The length of the upper leg.
* @param lowerLegLength The length of the lower leg.
*/
public ExerciseUser(float upperArmLength, float lowerArmLength, float height, float upperLegLength, float lowerLegLength) {
this.upperArmLength = upperArmLength;
this.lowerArmLength = lowerArmLength;
this.upperLegLength = upperLegLength;
this.lowerLegLength = lowerLegLength;
this.height = height;
}
/**
* Constructor for the ExerciseUser class.
* @param height The height of the user.
*/
public ExerciseUser(float height) {
this.height = height;
this.upperArmLength = height * 0.2f;
this.lowerArmLength = height * 0.2f;
this.upperLegLength = height * 0.3f;
this.lowerLegLength = height * 0.3f;
}
/**
* Default constructor for the ExerciseUser class.
* This sets the default height to 180.0f. (1.80m)
*/
public ExerciseUser() {
this(180.0f);
}
}

View File

@@ -0,0 +1,48 @@
package com.example.fitbot.exercise;
import com.example.fitbot.util.path.GesturePath;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public class FitnessManager {
private static final String HOST_ADDRESS = "http://145.92.8.132";
private static String sendHTTP(String url, String method, String contentType, String body) {
try {
URLConnection connection = new URL(url).openConnection();
connection.addRequestProperty("Content-Type", contentType);
connection.addRequestProperty("Request-Method", method);
connection.getOutputStream().write(body.getBytes());
connection.connect();
InputStream stream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
return builder.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static GesturePath acquirePath(String uniqueIdentifier) {
String response = sendHTTP(
HOST_ADDRESS + "/acquire", "GET", "application/json", "{\"kind\":\"" + uniqueIdentifier + "\"}"
);
// Validate the response
if ( response != null ) {
}
return null;
}
}

View File

@@ -10,7 +10,6 @@ public class GesturePath {
// The vectors that make up the path.
private final PathSegment[] segments;
private double curvature;
public GesturePath(Vector3f[] vectors) {
this(vectors, 0.0D);
@@ -27,7 +26,6 @@ public class GesturePath {
if ( vectors.length < 2)
throw new IllegalArgumentException("A path must have at least two points.");
this.curvature = curvature;
this.segments = new PathSegment[vectors.length - 1];
for ( int i = 0; i < vectors.length - 1; i++)
segments[i] = new PathSegment(vectors[i], vectors[i + 1]);
@@ -39,7 +37,6 @@ public class GesturePath {
*/
public GesturePath(PathSegment... segments) {
this.segments = segments;
this.curvature = 0.0d;
}
/**

View File

@@ -25,10 +25,9 @@ public class PathSegment {
* depending on the curvature of the curve. If the curvature is unset, or set to 0
* then this method will use linear interpolation. Otherwise, it will use a curve.
*
* @param dst The destination vector to interpolate to.
* @param t The interpolation value between 0 and 1.
*/
public Vector3f interpolate(Vector3f dst, double t) {
public Vector3f interpolate(double t) {
return new Vector3f(this.start)
.lerp(this.end, (float) Math.min(1.0F, Math.max(0.0F, t)));
}

View File

@@ -0,0 +1,35 @@
package com.example.fitbot;
import com.example.fitbot.util.path.GesturePath;
import com.example.fitbot.util.path.PathSegment;
import org.joml.Vector3f;
public class PathSegmentTest {
@Test
public void testPathSegment() {
// Test the PathSegment class
Vector3f[] vectors = new Vector3f[2];
vectors[0] = new Vector3f(0, 0, 0);
vectors[1] = new Vector3f(1, 1, 1);
GesturePath path = new GesturePath(vectors);
PathSegment[] segments = path.getSegments();
assertEquals(1, segments.length);
assertEquals(new Vector3f(0, 0, 0), segments[0].getStart());
assertEquals(new Vector3f(1, 1, 1), segments[0].getEnd());
assertEquals(new Vector3f(0.5f, 0.5f, 0.5f), segments[0].interpolate(0.5));
}
@Test
@DisplayName("Test Path Segment Interpolation")
public void test_pathSegmentInterpolation() {
Vector3f start = new Vector3f(0, 0, 0);
Vector3f end = new Vector3f(1, 1, 1);
PathSegment segment = new PathSegment(start, end);
assertEquals(new Vector3f(0.5f, 0.5f, 0.5f), segment.interpolate(0.5));
}
}