diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/InputProcessor.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/InputProcessor.java index cd81be9..8b0224f 100644 --- a/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/InputProcessor.java +++ b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/InputProcessor.java @@ -31,7 +31,10 @@ public class InputProcessor { private float exerciseRepetitionDurationInSeconds = 0.0f; private int repetitionsRemaining = 0; private int exercisesRemaining = 0; - private float exerciseScore = 0.0F; + + private float errorCheckInterval_s; + private int checksPerformed = 0; + private int totalChecks = 0; private final FitnessActivity parentActivity; @@ -97,6 +100,29 @@ public class InputProcessor { this.exercisesRemaining = 1; this.nextExercise(exercise); Pepper.say(STARTING_PHRASES[(int) Math.floor(Math.random() * STARTING_PHRASES.length)]); + + // Error checking thread. + (new Thread(() -> { + while (this.exercisesRemaining > 0) + { + boolean isFaulty = this.isFaultyMovement(); + + if ( isFaulty ) { + this.onInadequateRepetition(); + } else this.onAdequateRepetition(); + + this.checksPerformed++; + + if ( this.checksPerformed >= this.totalChecks ) + acquireExercise(); + + try { + Thread.sleep((long) (this.errorCheckInterval_s * 1000)); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + })).start(); } /** @@ -107,11 +133,17 @@ public class InputProcessor { private void nextExercise(Exercise exercise) { if (this.exercisesRemaining-- <= 0) { NavigationManager.navigateToActivity(this.parentActivity, EndScreenActivity.class); + return; } ExerciseManager.TOTAL_REPETITIONS_REQUIRED += ExerciseManager.DEFAULT_EXERCISE_REPETITIONS; ExerciseManager.TOTAL_EXERCISES_PREFORMED++; + this.checksPerformed = 0; + this.totalChecks = ExerciseManager.DEFAULT_EXERCISE_REPETITIONS * 6; + + this.errorCheckInterval_s = this.exerciseRepetitionDurationInSeconds * ExerciseManager.DEFAULT_EXERCISE_REPETITIONS / 6.0f; + this.selfRotationVectorPaths = new ArrayList[2]; this.selfRotationVectorPaths[0] = new ArrayList<>(); this.selfRotationVectorPaths[1] = new ArrayList<>(); @@ -194,6 +226,22 @@ public class InputProcessor { } } + /** + * Function for acquiring the next exercise from the database. + * Upon successful retrieval, it will call the nextExercise method. + */ + private void acquireExercise() + { + this.exercisesRemaining--; + + this.parentActivity.fetchExerciseAsync(this::nextExercise, (nil) -> { + + Log.i("MotionProcessor", "Failed to fetch exercise data."); + NavigationManager.navigateToActivity(this.parentActivity, MainActivity.class); + + }); + } + /** * Function for stopping the listening process * of the motion sensor. This function will stop @@ -288,20 +336,13 @@ public class InputProcessor { } // Do something else with the vector - // TODO: Implement !! - Log.i("MotionProcessor", "Rotation vector: " + rotation.toString() + " from device: " + deviceId); // Whenever the exercise has finished and it's not recording, // attempt to move to the next exercise. // If this fails, navigate back to the main activity. - if (this.hasFinished() && !this.recordingMovement) { - this.parentActivity.fetchExerciseAsync(this::nextExercise, (nil) -> { - Log.i("MotionProcessor", "Failed to fetch exercise data."); - NavigationManager.navigateToActivity(this.parentActivity, MainActivity.class); - }); - } - + if (this.hasFinished() && !this.recordingMovement) + acquireExercise(); } } @@ -318,9 +359,7 @@ public class InputProcessor { JsonArray jsonArray = new JsonArray(); /* * Convert to JSON array in the following format: - * [ - * { "deviceId": number, "data": [ [x, y, z], [x, y, z], ... ] }, - * ] + * [ { "deviceId": number, "data": [ [x, y, z], [x, y, z], ... ] }] */ // Iterate over all devices. In the current instance, it's 2. @@ -346,20 +385,9 @@ public class InputProcessor { } /** - * Function for getting the combined (average) error value of both sensors. - public double getCombinedError() - { - - }*/ - - /** - * + * Function for checking whether the last movement was faulty */ - public boolean isFaultyMovement(int sensorId, float time) { - - // Ensure the sensor ID is within the bounds of the array - if (sensorId < 0 || sensorId >= selfRotationVectorPaths.length) - return false; + public boolean isFaultyMovement() { // Calculate the index of the reference rotation vector // This is done by calculating the closest index of the last received vector @@ -367,26 +395,24 @@ public class InputProcessor { // i = | (t % T) / T * N | int i, referenceIndex; + float distance; for ( i = 0; i < selfRotationVectorPaths.length; i++) { referenceIndex = (int) (Math.round( - ((time % this.exerciseRepetitionDurationInSeconds) / + ((this.secondsPassed % this.exerciseRepetitionDurationInSeconds) / (this.exerciseRepetitionDurationInSeconds)) * this.targetRotationVectorPaths[i].length)) % this.targetRotationVectorPaths[i].length; // If distance is greater than the threshold, return true - if (this.selfRotationVectorPaths[i].get(this.selfRotationVectorPaths[i].size() - 1).distance( - this.targetRotationVectorPaths[i][referenceIndex]) > ExerciseManager.EXERCISE_ERROR_MARGIN) + distance = this.selfRotationVectorPaths[i].get(this.selfRotationVectorPaths[i].size() - 1).distance( + this.targetRotationVectorPaths[i][referenceIndex]); + + if (distance > ExerciseManager.EXERCISE_ERROR_MARGIN) + { + Log.i("MotionProcessor", "Faulty movement detected: " + distance + " > " + ExerciseManager.EXERCISE_ERROR_MARGIN); return true; + } } return false; } - - public float secondsPassed() { - return (float) secondsPassed; - } - - public boolean isRecording() { - return this.recordingMovement; - } }