first commit
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/// أنواع المقاطع المكتشفة تلقائياً
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user