Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66

This commit is contained in:
Niels Gras
2024-06-05 15:08:20 +02:00
2 changed files with 17 additions and 54 deletions

View File

@@ -2,9 +2,7 @@ package com.example.fitbot.ui.activities;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
@@ -59,8 +57,6 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
private VideoView videoView; private VideoView videoView;
private QiContext qiContext; private QiContext qiContext;
private ObjectAnimator shimmerAnimator;
private final Object lock = new Object(); private final Object lock = new Object();
// Some nice little messages for the user // Some nice little messages for the user
@@ -101,14 +97,6 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
ProgressBar loadingCircle = findViewById(R.id.loadingCircle); ProgressBar loadingCircle = findViewById(R.id.loadingCircle);
loadingCircle.setIndeterminateTintList(ColorStateList.valueOf(Color.RED)); loadingCircle.setIndeterminateTintList(ColorStateList.valueOf(Color.RED));
// Start shimmer animation for loading elements
View shimmerProgressCircle = findViewById(R.id.progressCircle);
View shimmerFitnessTitle = findViewById(R.id.textViewFitnessTitle);
View shimmerFitnessText = findViewById(R.id.textViewFitnessShortDescription);
shimmerAnimation(shimmerProgressCircle);
shimmerAnimation(shimmerFitnessTitle);
shimmerAnimation(shimmerFitnessText);
// Navigation Buttons // Navigation Buttons
NavigationManager.setupButtonNavigation(this, R.id.homeButtonFitness, MainActivity.class); NavigationManager.setupButtonNavigation(this, R.id.homeButtonFitness, MainActivity.class);
NavigationManager.setupButtonNavigation(this, R.id.skipButtonFitness, MainActivity.class); //Needs to skip exercises once those are implemented NavigationManager.setupButtonNavigation(this, R.id.skipButtonFitness, MainActivity.class); //Needs to skip exercises once those are implemented
@@ -140,16 +128,13 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
// Acquire paths from the exercise and provide them to the motion processor // Acquire paths from the exercise and provide them to the motion processor
motionProcessor = new InputProcessor(this); motionProcessor = new InputProcessor(this);
motionProcessor.useExercise(exercise); motionProcessor.useExercise(exercise);
/* TODO: Remove if not needed */
motionProcessor.setRecording(true, 10);
motionProcessor.startListening();
}, (n) -> { }, (n) -> {
int randomMessageIndex = (int) Math.floor(Math.random() * EXERCISE_NOT_FOUND_MESSAGES.length); int randomMessageIndex = (int) Math.floor(Math.random() * EXERCISE_NOT_FOUND_MESSAGES.length);
Pepper.say(EXERCISE_NOT_FOUND_MESSAGES[randomMessageIndex]); Pepper.say(EXERCISE_NOT_FOUND_MESSAGES[randomMessageIndex]);
Pepper.say(EXERCISE_NOT_FOUND_SEEK_HELP_MESSAGE); Pepper.say(EXERCISE_NOT_FOUND_SEEK_HELP_MESSAGE);
NavigationManager.navigateToActivity(this, EndScreenActivity.class); // Run on main thread to prevent crashes (wack)
this.runOnUiThread(() -> NavigationManager.navigateToActivity(this, EndScreenActivity.class));
}); });
} }
@@ -164,7 +149,10 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
new Thread(() -> { new Thread(() -> {
Exercise exercise = ExerciseManager.fetchExerciseFromDatabase(); Exercise exercise = ExerciseManager.fetchExerciseFromDatabase();
if (exercise == null) { if (exercise == null) {
runOnUiThread(() -> onFailedFetch.handle(null)); onFailedFetch.handle(null);
// Main thread stuff
runOnUiThread(() -> NavigationManager.navigateToActivity(this, MainActivity.class));
} else { } else {
onSuccessfulFetch.handle(exercise); onSuccessfulFetch.handle(exercise);
runOnUiThread(() -> { runOnUiThread(() -> {
@@ -183,12 +171,11 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
ProgressBar loadingCircle = findViewById(R.id.loadingCircle); ProgressBar loadingCircle = findViewById(R.id.loadingCircle);
loadingCircle.setVisibility(View.GONE); loadingCircle.setVisibility(View.GONE);
// Stop shimmer animation
stopShimmerAnimation();
Pepper.animate("armraise"); Pepper.animate("armraise");
// Start checking for user movement once the video has loaded // Start checking for user movement once the video has loaded
this.motionProcessor.startListening();
this.motionProcessor.startCheckingUserMovement(); this.motionProcessor.startCheckingUserMovement();
return true; return true;
@@ -301,24 +288,4 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
}); });
animator.start(); animator.start();
} }
public void shimmerAnimation(View view) {
ObjectAnimator animator = ObjectAnimator.ofObject(
view,
"backgroundColor",
new ArgbEvaluator(),
ContextCompat.getColor(view.getContext(), R.color.shimmerStartColor),
ContextCompat.getColor(view.getContext(), R.color.shimmerEndColor)
);
animator.setDuration(1200);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.start();
}
public void stopShimmerAnimation() {
if (shimmerAnimator != null && shimmerAnimator.isRunning()) {
shimmerAnimator.cancel();
}
}
} }

View File

@@ -101,21 +101,19 @@ public class InputProcessor {
* This function will start a thread that will check for user movement * This function will start a thread that will check for user movement
* and compare the last rotation vectors to the target rotation vectors. * and compare the last rotation vectors to the target rotation vectors.
*/ */
public void startCheckingUserMovement() public void startCheckingUserMovement() {
{
// Error checking thread. // Error checking thread.
(new Thread(() -> { (new Thread(() -> {
while (this.exercisesRemaining > 0) while (this.exercisesRemaining > 0) {
{
boolean isFaulty = this.isFaultyMovement(); boolean isFaulty = this.isFaultyMovement();
if ( isFaulty ) { if (isFaulty) {
this.onInadequateRepetition(); this.onInadequateRepetition();
} else this.onAdequateRepetition(); } else this.onAdequateRepetition();
this.checksPerformed++; this.checksPerformed++;
if ( this.checksPerformed >= this.totalChecks ) if (this.checksPerformed >= this.totalChecks)
acquireExercise(); acquireExercise();
try { try {
@@ -134,7 +132,9 @@ public class InputProcessor {
*/ */
private void nextExercise(Exercise exercise) { private void nextExercise(Exercise exercise) {
if (this.exercisesRemaining-- <= 0) { if (this.exercisesRemaining-- <= 0) {
NavigationManager.navigateToActivity(this.parentActivity, EndScreenActivity.class);
// Move to end screen on main activity
this.parentActivity.runOnUiThread(() -> NavigationManager.navigateToActivity(this.parentActivity, EndScreenActivity.class));
return; return;
} }
@@ -230,14 +230,12 @@ public class InputProcessor {
* Function for acquiring the next exercise from the database. * Function for acquiring the next exercise from the database.
* Upon successful retrieval, it will call the nextExercise method. * Upon successful retrieval, it will call the nextExercise method.
*/ */
private void acquireExercise() private void acquireExercise() {
{
this.exercisesRemaining--; this.exercisesRemaining--;
this.parentActivity.fetchExerciseAsync(this::nextExercise, (nil) -> { this.parentActivity.fetchExerciseAsync(this::nextExercise, (nil) -> {
Log.i("MotionProcessor", "Failed to fetch exercise data."); Log.i("MotionProcessor", "Failed to fetch exercise data.");
NavigationManager.navigateToActivity(this.parentActivity, MainActivity.class);
}); });
} }
@@ -397,8 +395,7 @@ public class InputProcessor {
int i, referenceIndex; int i, referenceIndex;
float distance; float distance;
for ( i = 0; i < selfRotationVectorPaths.length; i++) for (i = 0; i < selfRotationVectorPaths.length; i++) {
{
referenceIndex = (int) (Math.round( referenceIndex = (int) (Math.round(
((this.secondsPassed % this.exerciseRepetitionDurationInSeconds) / ((this.secondsPassed % this.exerciseRepetitionDurationInSeconds) /
(this.exerciseRepetitionDurationInSeconds)) * this.targetRotationVectorPaths[i].length)) (this.exerciseRepetitionDurationInSeconds)) * this.targetRotationVectorPaths[i].length))
@@ -407,8 +404,7 @@ public class InputProcessor {
distance = this.selfRotationVectorPaths[i].get(this.selfRotationVectorPaths[i].size() - 1).distance( distance = this.selfRotationVectorPaths[i].get(this.selfRotationVectorPaths[i].size() - 1).distance(
this.targetRotationVectorPaths[i][referenceIndex]); this.targetRotationVectorPaths[i][referenceIndex]);
if (distance > ExerciseManager.EXERCISE_ERROR_MARGIN) if (distance > ExerciseManager.EXERCISE_ERROR_MARGIN) {
{
Log.i("MotionProcessor", "Faulty movement detected: " + distance + " > " + ExerciseManager.EXERCISE_ERROR_MARGIN); Log.i("MotionProcessor", "Faulty movement detected: " + distance + " > " + ExerciseManager.EXERCISE_ERROR_MARGIN);
return true; return true;
} }