import '../../../navigation/utils/geometry_utils.dart'; import '../widgets/pose_detector.dart'; class Exercise { final int reps; final int series; final Criteria startMovement; final Criteria endMovement; const Exercise({ required this.reps, required this.series, required this.startMovement, required this.endMovement, }); bool isAtStartMovement(MeanFilteredData meanFilteredData) { return startMovement.isAtPosition(meanFilteredData); } bool isAtEndMovement(MeanFilteredData meanFilteredData) { return endMovement.isAtPosition(meanFilteredData); } } abstract class Criteria { bool isAtPosition(MeanFilteredData meanFilteredData); } class CriteriaDistance implements Criteria { final int jointStart; final int jointEnd; final int axis; final int threshold; const CriteriaDistance({ required this.jointStart, required this.jointEnd, required this.axis, required this.threshold, }); @override bool isAtPosition(MeanFilteredData meanFilteredData) { final landmarks = meanFilteredData.toList(); final start = landmarks[jointStart][axis]; final end = landmarks[jointEnd][axis]; final distance = (start - end).abs(); return distance < threshold; } } class CriteriaAngle implements Criteria { final int jointStart; final int jointCenter; final int jointEnd; final int threshold; const CriteriaAngle({ required this.jointStart, required this.jointCenter, required this.jointEnd, required this.threshold, }); @override bool isAtPosition(MeanFilteredData meanFilteredData) { final landmarks = meanFilteredData.toList(); final start = Point3D(x: landmarks[jointStart][0], y: landmarks[jointStart][1], z: landmarks[jointStart][2]); final center = Point3D(x: landmarks[jointCenter][0], y: landmarks[jointCenter][1], z: landmarks[jointCenter][2]); final end = Point3D(x: landmarks[jointEnd][0], y: landmarks[jointEnd][1], z: landmarks[jointEnd][2]); final angle = DistanceUtils.angleBetweenThreePoints(start, center, end).round(); return angle > threshold; } }