Files
fitness/mobile/lib/models/workout_segment.dart
T
2026-10-04 00:19:45 +03:00

91 lines
3.0 KiB
Dart

/// أنواع المقاطع المكتشفة تلقائياً
enum SegmentType {
warmup, // إحماء - أول 5-10% من المسافة بسرعة منخفضة
main, // المرحلة الرئيسية
cooldown, // تبريد - آخر 5-10% بسرعة متناقصة
stop, // نقطة توقف - سرعة < 0.3 m/s لأكثر من 10 ثوان
sprint, // تسارع - سرعة > 120% من المتوسط
uphill, // صعود - ارتفاع > 3% grade
downhill, // نزول - انخفاض > 3% grade
}
/// نموذج مقطع من المسار
/// يمثل جزء من التمرين تم تقسيمه بناءً على تغيرات السرعة أو الارتفاع
class WorkoutSegment {
final int segmentIndex;
final SegmentType type;
final double distanceMeters;
final int durationSeconds;
final double avgSpeedMps;
final double maxSpeedMps;
final double elevationChange; // positive = uphill, negative = downhill
final int startCoordIndex; // index in coordinates list
final int endCoordIndex;
WorkoutSegment({
required this.segmentIndex,
required this.type,
required this.distanceMeters,
required this.durationSeconds,
required this.avgSpeedMps,
this.maxSpeedMps = 0,
this.elevationChange = 0,
required this.startCoordIndex,
required this.endCoordIndex,
});
/// Pace in min/km
double get paceMinKm {
if (avgSpeedMps <= 0) return 0;
double kmh = avgSpeedMps * 3.6;
return kmh > 0 ? 60.0 / kmh : 0;
}
/// Gradient percentage (for elevation segments)
double get gradientPercent {
if (distanceMeters <= 0) return 0;
return (elevationChange / distanceMeters) * 100;
}
Map<String, dynamic> toMap() {
return {
'segment_index': segmentIndex,
'segment_type': type.name,
'distance_meters': distanceMeters,
'duration_seconds': durationSeconds,
'avg_speed_mps': avgSpeedMps,
'max_speed_mps': maxSpeedMps,
'elevation_change': elevationChange,
'start_coord_index': startCoordIndex,
'end_coord_index': endCoordIndex,
};
}
factory WorkoutSegment.fromMap(Map<String, dynamic> map) {
return WorkoutSegment(
segmentIndex: map['segment_index'] as int,
type: SegmentType.values.firstWhere(
(e) => e.name == map['segment_type'],
orElse: () => SegmentType.main,
),
distanceMeters: (map['distance_meters'] as num).toDouble(),
durationSeconds: map['duration_seconds'] as int,
avgSpeedMps: (map['avg_speed_mps'] as num).toDouble(),
maxSpeedMps: (map['max_speed_mps'] as num?)?.toDouble() ?? 0,
elevationChange: (map['elevation_change'] as num?)?.toDouble() ?? 0,
startCoordIndex: map['start_coord_index'] as int,
endCoordIndex: map['end_coord_index'] as int,
);
}
/// Convert to API-compatible map
Map<String, dynamic> toApiMap() {
return {
'segment_order': segmentIndex,
'duration_seconds': durationSeconds,
'distance_meters': distanceMeters.toInt(),
'index_in_polyline': startCoordIndex,
};
}
}