2024-06-03 14:55:39 +02:00
8 changed files with 55 additions and 44 deletions

View File

@@ -8,6 +8,7 @@ public class Exercise {
public final GesturePath leftPath; public final GesturePath leftPath;
public final GesturePath rightPath; public final GesturePath rightPath;
public final String name; public final String name;
public final String shortDescription;
public final String description; public final String description;
public final String imageUrl; public final String imageUrl;
public final String videoUrl; public final String videoUrl;
@@ -24,9 +25,10 @@ public class Exercise {
* @param imageUrl The URL of the image. * @param imageUrl The URL of the image.
* @param videoUrl The URL of the video. * @param videoUrl The URL of the video.
*/ */
public Exercise(EMuscleGroup muscleGroup, String name, String description, String imageUrl, String videoUrl, GesturePath leftPath, GesturePath rightPath, float exerciseTimeInSeconds) { public Exercise(EMuscleGroup muscleGroup, String name,String shortDescription, String description, String imageUrl, String videoUrl, GesturePath leftPath, GesturePath rightPath, float exerciseTimeInSeconds) {
this.name = name; this.name = name;
this.muscleGroup = muscleGroup; this.muscleGroup = muscleGroup;
this.shortDescription = shortDescription;
this.description = description; this.description = description;
this.leftPath = leftPath; this.leftPath = leftPath;
this.rightPath = rightPath; this.rightPath = rightPath;

View File

@@ -21,10 +21,10 @@ public class ExerciseManager {
private static final String PROPERTY_EXERCISE_DURATION = "duration"; private static final String PROPERTY_EXERCISE_DURATION = "duration";
private static final String PROPERTY_EXERCISE_ID = "exerciseId"; private static final String PROPERTY_EXERCISE_ID = "exerciseId";
private static final String PROPERTY_MUSCLE_GROUP = "muscleGroup"; private static final String PROPERTY_MUSCLE_GROUP = "muscleGroup";
private static final String PROPERTY_SHORT_DESC = "shortDescription";
private static final String PROPERTY_IMAGE_URL = "imageUrl"; private static final String PROPERTY_IMAGE_URL = "imageUrl";
private static final String PROPERTY_VIDEO_URL = "videoUrl"; private static final String PROPERTY_VIDEO_URL = "videoUrl";
private static final String PROPERTY_DESC = "description"; private static final String PROPERTY_DESC = "description";
private static final String PROPERTY_SHORT_DESC = "shortDescription";
private static final String PROPERTY_PATH = "path"; private static final String PROPERTY_PATH = "path";
private static final String PROPERTY_NAME = "name"; private static final String PROPERTY_NAME = "name";
@@ -34,7 +34,7 @@ public class ExerciseManager {
public static final int SENSOR_COUNT = 2; public static final int SENSOR_COUNT = 2;
private static final String[] REQUIRED_PROPERTIES = { private static final String[] REQUIRED_PROPERTIES = {
PROPERTY_MUSCLE_GROUP, PROPERTY_DESC, PROPERTY_IMAGE_URL, PROPERTY_MUSCLE_GROUP, PROPERTY_DESC,PROPERTY_SHORT_DESC, PROPERTY_IMAGE_URL,
PROPERTY_VIDEO_URL, PROPERTY_NAME, PROPERTY_PATH, PROPERTY_VIDEO_URL, PROPERTY_NAME, PROPERTY_PATH,
PROPERTY_EXERCISE_DURATION, PROPERTY_EXERCISE_ID, PROPERTY_EXERCISE_DURATION, PROPERTY_EXERCISE_ID,
PROPERTY_SHORT_DESC PROPERTY_SHORT_DESC
@@ -112,6 +112,7 @@ public class ExerciseManager {
EMuscleGroup.parse(content.get(PROPERTY_MUSCLE_GROUP).getAsString()), EMuscleGroup.parse(content.get(PROPERTY_MUSCLE_GROUP).getAsString()),
content.get(PROPERTY_NAME).getAsString(), content.get(PROPERTY_NAME).getAsString(),
content.get(PROPERTY_DESC).getAsString(), content.get(PROPERTY_DESC).getAsString(),
content.get(PROPERTY_SHORT_DESC).getAsString(),
content.get(PROPERTY_IMAGE_URL).getAsString(), content.get(PROPERTY_IMAGE_URL).getAsString(),
content.get(PROPERTY_VIDEO_URL).getAsString(), content.get(PROPERTY_VIDEO_URL).getAsString(),
GesturePath.fromString(leftRightData[0]), GesturePath.fromString(leftRightData[0]),

View File

@@ -33,7 +33,12 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
private ExerciseStatusElement exerciseStatusElement; private ExerciseStatusElement exerciseStatusElement;
private InputProcessor motionProcessor; private InputProcessor motionProcessor;
private Exercise currentExercise; private Exercise currentExercise;
// Exercise status element data
private TextView exerciseMuscleGroupTextView;
private TextView exerciseNameTextView; private TextView exerciseNameTextView;
private TextView exerciseShortDescriptionTextView;
private TextView exerciseDescriptionTextView;
// Some nice little messages for the user // Some nice little messages for the user
private static final String[] EXERCISE_NOT_FOUND_MESSAGES = new String[]{ private static final String[] EXERCISE_NOT_FOUND_MESSAGES = new String[]{
@@ -58,7 +63,11 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
// Remove the ugly ass bar on top of the view // Remove the ugly ass bar on top of the view
setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE); setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE);
// Fill empty objects with exercise data
this.exerciseNameTextView = findViewById(R.id.textViewFitnessTitle); this.exerciseNameTextView = findViewById(R.id.textViewFitnessTitle);
this.exerciseDescriptionTextView = findViewById(R.id.textViewDialogDescription);
this.exerciseShortDescriptionTextView = findViewById(R.id.textViewFitnessShortDescription);
// Find the VideoView by its ID // Find the VideoView by its ID
VideoView videoView = findViewById(R.id.videoView); VideoView videoView = findViewById(R.id.videoView);
@@ -128,6 +137,8 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
onFailedFetch.handle(null); onFailedFetch.handle(null);
} else { } else {
exerciseNameTextView.setText(exercise.name); exerciseNameTextView.setText(exercise.name);
exerciseShortDescriptionTextView.setText(exercise.shortDescription);
exerciseDescriptionTextView.setText(exercise.description);
onSuccessfulFetch.handle(exercise); onSuccessfulFetch.handle(exercise);
} }
})).start(); })).start();

View File

@@ -18,12 +18,7 @@ import com.example.fitbot.util.NavigationManager;
import com.example.fitbot.util.processing.IInputHandler; import com.example.fitbot.util.processing.IInputHandler;
import com.example.fitbot.util.processing.InputProcessor; import com.example.fitbot.util.processing.InputProcessor;
import org.joml.Matrix4f;
import org.joml.Vector2f;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector4f;
import java.util.concurrent.ConcurrentLinkedQueue;
public class ExerciseStatusElement extends View implements IInputHandler { public class ExerciseStatusElement extends View implements IInputHandler {
@@ -87,8 +82,6 @@ public class ExerciseStatusElement extends View implements IInputHandler {
// Handler that is called every time the motion processor receives new data. // Handler that is called every time the motion processor receives new data.
} }
/** /**
@@ -127,40 +120,40 @@ public class ExerciseStatusElement extends View implements IInputHandler {
@Override @Override
public void accept(Vector3f rotationVector, int sensorId) { public void accept(Vector3f rotationVector, int sensorId) {
Log.i("MotionProcessor", "Rotation vector received: " + rotationVector); Log.i("MotionProcessor", "Rotation vector received: " + rotationVector);
Log.i("MotionProcessor", "Last error offset:" + this.motionProcessor.getError(sensorId, this.motionProcessor.secondsPassed())); Log.i("MotionProcessor", "Last error offset:" + this.motionProcessor.getError(sensorId, this.motionProcessor.secondsPassed()));
// Check whether the current exercise has been completed. // Check whether the current exercise has been completed.
// This is determined by the duration of the exercise, and the amount of time that has passed. // This is determined by the duration of the exercise, and the amount of time that has passed.
// The duration of the exercise originates from the database, and is stored in seconds. // The duration of the exercise originates from the database, and is stored in seconds.
// Whenever 'useExercise' is called, the timer resets and this method will be called again. // Whenever 'useExercise' is called, the timer resets and this method will be called again.
if (this.motionProcessor.hasFinished() && !this.motionProcessor.isRecording()) { if (this.motionProcessor.hasFinished() && !this.motionProcessor.isRecording()) {
// If for some reason the parent activity is not defined, // If for some reason the parent activity is not defined,
// move back to the main screen. // move back to the main screen.
if (this.parentActivity == null) { if (this.parentActivity == null) {
// Move to main screen // Move to main screen
Log.i("MotionProcessor", "Parent activity was null."); Log.i("MotionProcessor", "Parent activity was null.");
NavigationManager.navigateToActivity(getContext(), MainActivity.class); NavigationManager.navigateToActivity(getContext(), MainActivity.class);
return; return;
}
// Move on to the next exercise, or finish.
if (this.exerciseCount > 0) {
this.exerciseCount--;
this.parentActivity.fetchExerciseAsync((newExercise) -> {
this.motionProcessor.useExercise(newExercise);
// Whenever the database retrieval failed, we return to the main screen.
}, (failed) -> {
// Move to main screen
Log.i("MotionProcessor", "Failed to fetch exercise from database");
NavigationManager.navigateToActivity(parentActivity, MainActivity.class);
});
} else {
// Finish the exercise.
Log.i("MotionProcessor", "Exercise has finished");
NavigationManager.navigateToActivity(parentActivity, EndScreenActivity.class);
}
} }
// Move on to the next exercise, or finish.
if (this.exerciseCount > 0) {
this.exerciseCount--;
this.parentActivity.fetchExerciseAsync((newExercise) -> {
this.motionProcessor.useExercise(newExercise);
// Whenever the database retrieval failed, we return to the main screen.
}, (failed) -> {
// Move to main screen
Log.i("MotionProcessor", "Failed to fetch exercise from database");
NavigationManager.navigateToActivity(parentActivity, MainActivity.class);
});
} else {
// Finish the exercise.
Log.i("MotionProcessor", "Exercise has finished");
NavigationManager.navigateToActivity(parentActivity, EndScreenActivity.class);
}
}
} }
} }

View File

@@ -92,6 +92,8 @@ public class GesturePath {
*/ */
public static GesturePath fromString(String input) { public static GesturePath fromString(String input) {
if (input == null)
throw new IllegalArgumentException("Input string cannot be null");
byte[] bytes = input.getBytes(); byte[] bytes = input.getBytes();
// Check if the input string contains a valid amount of bytes (12 bytes per vector) // Check if the input string contains a valid amount of bytes (12 bytes per vector)

View File

@@ -101,6 +101,7 @@ public class InputProcessor {
if (recording) { if (recording) {
this.secondsPassed = 0.0D; this.secondsPassed = 0.0D;
this.lastTime = System.currentTimeMillis(); this.lastTime = System.currentTimeMillis();
this.selfRotationVectorPaths = new Vector3f[2][(int) (duration * this.sampleRate)];
} }
} }
@@ -179,6 +180,7 @@ public class InputProcessor {
int deviceId = object.get("deviceId").getAsInt(); int deviceId = object.get("deviceId").getAsInt();
String type = object.get("type").getAsString(); String type = object.get("type").getAsString();
// Parse the retrieved data
parseRotationVector(rotation, deviceId); parseRotationVector(rotation, deviceId);
} catch (Exception e) { } catch (Exception e) {
Log.i("MotionProcessor", "Failed to parse packet data."); Log.i("MotionProcessor", "Failed to parse packet data.");

View File

@@ -84,7 +84,7 @@
android:layout_gravity="center_horizontal"> android:layout_gravity="center_horizontal">
<TextView <TextView
android:id="@+id/textViewFitnessDescription" android:id="@+id/textViewFitnessShortDescription"
style="@style/TextStyle" style="@style/TextStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@@ -33,7 +33,7 @@
</RelativeLayout> </RelativeLayout>
<TextView <TextView
android:id="@+id/textViewDialog" android:id="@+id/textViewDialogDescription"
style="@style/TextStyle" style="@style/TextStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"