diff --git a/src/EFMappers/AthleteMappeur.cs b/src/EFMappers/AthleteMappeur.cs index f6a2198..136c457 100644 --- a/src/EFMappers/AthleteMappeur.cs +++ b/src/EFMappers/AthleteMappeur.cs @@ -9,6 +9,11 @@ public static class UserMappeur { private static GenericMapper _mapper = new (); + public static void Reset() + { + _mapper.Reset(); + } + public static User ToModel(this AthleteEntity entity) { Func create = athleteEntity => new User diff --git a/src/HeartTrackAPI/Controllers/ActivityController.cs b/src/HeartTrackAPI/Controllers/ActivityController.cs index 1a9f7de..41d51af 100644 --- a/src/HeartTrackAPI/Controllers/ActivityController.cs +++ b/src/HeartTrackAPI/Controllers/ActivityController.cs @@ -20,12 +20,14 @@ public class ActivityController : Controller private readonly IActivityRepository _activityService; private readonly ILogger _logger; private readonly IUserRepository _userRepository; + private readonly IDataSourceRepository _dataSourceRepository; public ActivityController(IDataManager dataManager, ILogger logger) { _activityService = dataManager.ActivityRepo; _userRepository = dataManager.UserRepo; + _dataSourceRepository = dataManager.DataSourceRepo; _logger = logger; } @@ -64,17 +66,22 @@ public class ActivityController : Controller [HttpPost] public async Task PostActivity(NewActivityDto activityDto) { - _logger.LogInformation("Executing {Action} with parameters: {Parameters}, {add}", nameof(PostActivity), activityDto.Activity.Average, activityDto.HeartRates[0].HeartRate); - var user = await _userRepository.GetUserById(activityDto.AthleteId); + _logger.LogInformation("Executing {Action} with parameters: {Parameters}, {add}", nameof(PostActivity), activityDto.Activity.Average, activityDto.HeartRates[0].Timestamp); + var user = await _userRepository.GetUserTinyById(activityDto.AthleteId); if (user == null) { _logger.LogError("Athlete with id {id} not found", activityDto.AthleteId); return NotFound($"Athlete with id {activityDto.AthleteId} not found"); } - if (activityDto.DataSourceId != null && user.DataSource?.Id != activityDto.DataSourceId) + if (activityDto.DataSourceId != null) { - _logger.LogError("DataSource with id {id} not found for this user", activityDto.DataSourceId); - return NotFound($"DataSource with id {activityDto.DataSourceId} not found"); + var dataSource = await _dataSourceRepository.GetItemById(activityDto.DataSourceId.Value); + + if (dataSource == null) + { + _logger.LogError("DataSource with id {id} not found", activityDto.DataSourceId); + return NotFound($"DataSource with id {activityDto.DataSourceId} not found"); + } } var result = await _activityService.AddActivity(activityDto); diff --git a/src/HeartTrackAPI/Controllers/AnalysisController.cs b/src/HeartTrackAPI/Controllers/AnalysisController.cs index 11c3be3..96fe0aa 100644 --- a/src/HeartTrackAPI/Controllers/AnalysisController.cs +++ b/src/HeartTrackAPI/Controllers/AnalysisController.cs @@ -1,6 +1,10 @@ +using Dto; using Dto.Tiny; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Model.Manager; +using Model.Repository; +using Model.utils; namespace HeartTrackAPI.Controllers; @@ -10,34 +14,87 @@ namespace HeartTrackAPI.Controllers; [Authorize] public class AnalysisController : Controller { - private readonly List _heartRateZones = new() + + private readonly IActivityRepository _activityService; + private readonly ILogger _logger; + + + public AnalysisController(IDataManager dataManager, ILogger logger) { - new() { Name = "Repos", MinHeartRate = 0, MaxHeartRate = 60 }, - new() { Name = "Aérobie légère", MinHeartRate = 61, MaxHeartRate = 90 }, - new() { Name = "Aérobie", MinHeartRate = 91, MaxHeartRate = 140 }, - new() { Name = "Anaérobie", MinHeartRate = 141, MaxHeartRate = 180 }, - new() { Name = "VO2 Max", MinHeartRate = 181, MaxHeartRate = 220 } - }; + _activityService = dataManager.ActivityRepo; + _logger = logger; + } + + - [HttpGet("heart-rate/zones")] - public IActionResult GetHeartRateZones() + + [HttpGet("activity/{activityId}")] + public async Task AnalyseByActivityId(int activityId) { - var heartRates = GetMockHeartRateData(); - var results = _heartRateZones.Select(zone => new HeartRateZoneResult + var activity = await _activityService.GetActivityById(activityId); + if (activity == null) + { + _logger.LogInformation($"Activity with ID {activityId} not found."); + return NotFound($"Activity with ID {activityId} not found."); + } + // for the moment no need to get the user Entity [Dave] + var user = activity.Athlete; + if (user == null) { - Zone = zone.Name, - TimeSpent = CalculateTimeInZone(zone, heartRates) - }).ToList(); - return Ok(results); + _logger.LogInformation($"User not found for activity ID {activityId}."); + return NotFound($"User not found for activity ID {activityId}."); + } + + var analysis = ActivityAnalysis.FromActivityData(activity); + return Ok(analysis); } + - private TimeSpan CalculateTimeInZone(HeartRateZone zone, List heartRates) - { - var secondsInZone = - heartRates.Count(hr => hr.HeartRate >= zone.MinHeartRate && hr.HeartRate <= zone.MaxHeartRate); - return TimeSpan.FromSeconds(secondsInZone); - } - /* +} + + +/* + /* + public class HeartRateZoneResult + { + public string Zone { get; set; } + public TimeSpan TimeSpent { get; set; } + } + + private readonly List _heartRateZones = new() + { + new() { Name = "Repos", MinHeartRate = 0, MaxHeartRate = 60 }, + new() { Name = "Aérobie légère", MinHeartRate = 61, MaxHeartRate = 90 }, + new() { Name = "Aérobie", MinHeartRate = 91, MaxHeartRate = 140 }, + new() { Name = "Anaérobie", MinHeartRate = 141, MaxHeartRate = 180 }, + new() { Name = "VO2 Max", MinHeartRate = 181, MaxHeartRate = 220 } + }; + [HttpGet("heart-rate/zones/{activityId}")] + public IActionResult GetActivityHeartRateZones(int activityId) + { + var heartRateTinyDtos = _activityService.GetActivityById(activityId).Result?.HeartRates; + if (heartRateTinyDtos != null) + { + var heartRates = heartRateTinyDtos.ToList(); + var results = _heartRateZones.Select(zone => new HeartRateZoneResult + { + Zone = zone.Name, + TimeSpent = CalculateTimeInZone(zone, heartRates) + }).ToList(); + + return Ok(results); + } + + return NotFound("Not heart rates"); + + } + private TimeSpan CalculateTimeInZone(HeartRateZone zone, List heartRates) + { + var secondsInZone = + heartRates.Count(hr => hr.HeartRate >= zone.MinHeartRate && hr.HeartRate <= zone.MaxHeartRate); + return TimeSpan.FromSeconds(secondsInZone); + }* / + [HttpGet("getOptimizedPath")] public IActionResult GetOptimizedPath(int activityId) { @@ -56,36 +113,4 @@ public class AnalysisController : Controller return Ok(path.ToGeoJson()); } -*/ - private List GetMockHeartRateData() - { - var random = new Random(); - return Enumerable.Range(1, 3600) - .Select(_ => new HeartRateTinyDto - { - HeartRate = random.Next(60, 220), - Timestamp = new DateTime(2021, 1, 1).AddSeconds(random.Next(3600)), - Latitude = random.NextDouble() * 180 - 90, - Longitude = random.NextDouble() * 360 - 180, - Altitude = random.NextDouble() * 1000, - Cadence = random.Next(60, 120), - Distance = random.NextDouble() * 100, - Speed = random.NextDouble() * 30, - Power = random.Next(0, 500), - Temperature = random.NextDouble() * 30 - }).ToList(); - } -} - -public class HeartRateZoneResult -{ - public string Zone { get; set; } - public TimeSpan TimeSpent { get; set; } -} - -internal class HeartRateZone -{ - public string Name { get; set; } - public int MinHeartRate { get; set; } - public int MaxHeartRate { get; set; } -} \ No newline at end of file +*/ \ No newline at end of file diff --git a/src/HeartTrackAPI/Controllers/UsersController.cs b/src/HeartTrackAPI/Controllers/UsersController.cs index 6f74657..8f723ac 100644 --- a/src/HeartTrackAPI/Controllers/UsersController.cs +++ b/src/HeartTrackAPI/Controllers/UsersController.cs @@ -143,7 +143,7 @@ public class UsersController : Controller try { _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Update), user,id); - var athlete = await _userService.GetUserById(id); + var athlete = await _userService.GetUserTinyById(id); if (athlete == null) { _logger.LogError("Athlete with id {id} not found", id); @@ -183,7 +183,7 @@ public class UsersController : Controller { _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Delete), null,id); - var athlete = await _userService.GetUserById(id); + var athlete = await _userService.GetUserTinyById(id); if (athlete == null) { _logger.LogError("Athlete with id {id} not found", id); diff --git a/src/Model/Manager/IDataManager.cs b/src/Model/Manager/IDataManager.cs index 6fc8532..9a7b6cc 100644 --- a/src/Model/Manager/IDataManager.cs +++ b/src/Model/Manager/IDataManager.cs @@ -1,3 +1,4 @@ +using Dto.Tiny; using Model.Repository; namespace Model.Manager; @@ -6,4 +7,6 @@ public interface IDataManager { IUserRepository UserRepo { get; } IActivityRepository ActivityRepo { get; } + + IDataSourceRepository DataSourceRepo { get; } } diff --git a/src/Model/Repository/IDataSourceRepository.cs b/src/Model/Repository/IDataSourceRepository.cs new file mode 100644 index 0000000..6a442ae --- /dev/null +++ b/src/Model/Repository/IDataSourceRepository.cs @@ -0,0 +1,6 @@ +namespace Model.Repository; + +public interface IDataSourceRepository +{ + Task GetItemById(int id); +} \ No newline at end of file diff --git a/src/Model/Repository/IUserRepository.cs b/src/Model/Repository/IUserRepository.cs index a4d3c1a..0541afa 100644 --- a/src/Model/Repository/IUserRepository.cs +++ b/src/Model/Repository/IUserRepository.cs @@ -17,6 +17,7 @@ public interface IUserRepository : IGenericRepository // Make it generic public Task GetNbFriends(int user); public Task UpdateUser(int old,UserTinyDto user); public Task GetUserById(int id); + public Task GetUserTinyById(int id); public Task?> GetAllAthletes(int index, int count, AthleteOrderCriteria? criteria, bool descending = false); public Task?> GetAllCoaches(int index, int count, AthleteOrderCriteria? criteria, bool descending = false); diff --git a/src/Model/utils/ActivityAnalysis.cs b/src/Model/utils/ActivityAnalysis.cs new file mode 100644 index 0000000..1634dbb --- /dev/null +++ b/src/Model/utils/ActivityAnalysis.cs @@ -0,0 +1,63 @@ +using Model.utils; + +namespace Dto.Tiny; + +public class ActivityAnalysis +{ + public double AverageHeartRate { get; private set; } + public string AverageHeartRateAdvice { get; private set; } + public double Vo2Max { get; private set; } + public string Vo2MaxAdvice { get; private set; } + public double NormalBpm { get; private set; } + public string NormalBpmAdvice { get; private set; } + public double HeartRateVariability { get; private set; } + public string HeartRateVariabilityAdvice { get; private set; } + public string HeartRateZone { get; private set; } + public string HeartRateZoneAdvice { get; private set; } + public double Duration { get; private set; } + public string DurationAdvice { get; private set; } + public double Effort { get; private set; } + public string EffortAdvice { get; private set; } + public static ActivityAnalysis FromActivityData(ResponseActivityDto activity) + { + double dureeActivity = (activity.EndTime - activity.StartTime).TotalMinutes; + var age = DateTime.Today.Year - activity.Athlete.DateOfBirth.Year; + var gender = activity.Athlete.Sexe; + var poids = activity.Athlete.Weight; + var effortFelt = activity.EffortFelt; + var averageHeartRate = activity.Average; + var heartRateVariability = activity.Variability; + + var heartRateZones = HeartRateAdvise.CalculateHeartRateZones(age); + + var effortScore = HeartRateAdvise.EvaluateEffort(activity); + + var (seuilBPM, vo2Max) = HeartRateAdvise.SeuilBPMavance(gender, age, poids, dureeActivity); + string averageHeartRateAdvice = HeartRateAdvise.GenerateAverageHeartRateAdvice(averageHeartRate, seuilBPM); + string vo2MaxAdvice = HeartRateAdvise.GenerateVo2MaxAdvice(vo2Max); + string normalBpmAdvice = HeartRateAdvise.GenerateNormalBpmAdvice(seuilBPM, averageHeartRate); + string hrvAdvice = HeartRateAdvise.GenerateHrvAdvice(heartRateVariability); + HeartRateAdvise.HeartRateZone currentZone = heartRateZones.Find(zone => averageHeartRate >= zone.MinHeartRate && averageHeartRate <= zone.MaxHeartRate); + string heartRateZoneAdvice = HeartRateAdvise.GenerateHeartRateZoneAdvice(currentZone?.Name); + var effortAccuracy = HeartRateAdvise.CompareEffort(effortFelt, (int)effortScore); + var analysis = new ActivityAnalysis + { + AverageHeartRate = averageHeartRate, + AverageHeartRateAdvice = averageHeartRateAdvice, + Vo2Max = vo2Max, + Vo2MaxAdvice = vo2MaxAdvice, + NormalBpm = seuilBPM, + NormalBpmAdvice = normalBpmAdvice, + HeartRateVariability = heartRateVariability, + HeartRateVariabilityAdvice = hrvAdvice, + HeartRateZone = currentZone != null ? currentZone.Name : "N/A", + HeartRateZoneAdvice = heartRateZoneAdvice, + Duration = dureeActivity, + DurationAdvice =HeartRateAdvise.GenerateDurationAdvice(dureeActivity), + Effort = effortScore, + EffortAdvice = HeartRateAdvise.GenerateEffortAdvice(effortAccuracy) + }; + + return analysis; + } +} \ No newline at end of file diff --git a/src/Model/utils/HeartRateAdvise.cs b/src/Model/utils/HeartRateAdvise.cs new file mode 100644 index 0000000..10d8b61 --- /dev/null +++ b/src/Model/utils/HeartRateAdvise.cs @@ -0,0 +1,278 @@ +using Dto; + +namespace Model.utils; + +public class HeartRateAdvise +{ + public class HeartRateZone + { + public string Name { get; set; } + public int MinHeartRate { get; set; } + public int MaxHeartRate { get; set; } + } + + public string getAdvise(Activity activity) + { + return "You should take a break"; + } + public static List CalculateHeartRateZones(int age) + { + int fcm = 220 - age; // Estimation de la FCM + List zones = new List + { + new HeartRateZone { Name = "Très Légère", MinHeartRate = (int)(fcm * 0.50), MaxHeartRate = (int)(fcm * 0.60) }, + new HeartRateZone { Name = "Aérobie légère", MinHeartRate = (int)(fcm * 0.60), MaxHeartRate = (int)(fcm * 0.70) }, + new HeartRateZone { Name = "Aérobie", MinHeartRate = (int)(fcm * 0.70), MaxHeartRate = (int)(fcm * 0.80) }, + new HeartRateZone { Name = "Anaérobie", MinHeartRate = (int)(fcm * 0.80), MaxHeartRate = (int)(fcm * 0.90) }, + new HeartRateZone { Name = "Maximum", MinHeartRate = (int)(fcm * 0.90), MaxHeartRate = (int)(fcm * 1.00) } + }; + + return zones; + } + public static double EvaluateEffort(ResponseActivityDto stats) + { + double score = 0; + + score += stats.Average * 0.3; // Exemple de poids + score += stats.HeartRates.Average(speed => speed.Speed ?? 0) * 0.25; + score += stats.HeartRates.Sum(dist => dist.Distance ?? 0) * 0.15; + score += stats.HeartRates.Average(hr => hr.Cadence ?? 0) * 0.1; + score += stats.HeartRates.Average(hr => hr.Power ?? 0) * 0.15; + score += stats.StandardDeviation * 0.05; + + return score; + } + + public static string CompareEffort(int perceivedEffort, int objectiveEffort) + { + if (perceivedEffort == objectiveEffort) return "Accurate"; + if (perceivedEffort > objectiveEffort) return "Overestimated"; + if (perceivedEffort < objectiveEffort) return "Underestimated"; + return "Unknown"; + } + + +// Faible intensité : 50-60% de la FCM +// Intensité modérée : 60-70% de la FCM +// Haute intensité : 70-85% de la FCM + public static double CalculerVo2Max(char sexe, int age, double poids) + { + if (sexe == 'M') + { + return (poids * 0.198) + (age * -0.193) + 24.489; + } + + // sexe == "F" + { + return (poids * 0.201) + (age * -0.217) + 20.453; + } + } + + public static (double SeuilBPM, double Vo2Max) SeuilBPMavance(char sexe, int age, double poids, double dureeActivite) + { + double fcm = sexe == 'M' ? 207 - (0.7 * age) : 206 - (0.88 * age); + double vo2Max = CalculerVo2Max(sexe, age, poids); + + double zone = dureeActivite <= 30 ? 0.8 : dureeActivite <= 60 ? 0.7 : 0.6; + double seuilBpm = fcm * zone; + + return (seuilBpm, vo2Max); + } + + public static Dictionary GenerateAdvice(ResponseActivityDto activity) + { + int dureeActivity = (activity.EndTime - activity.StartTime).Minutes; + var age = DateTime.Today.Year - activity.Athlete.DateOfBirth.Year; + var gender = activity.Athlete.Sexe; + var poids = activity.Athlete.Weight; + var effortFelt = activity.EffortFelt; + var averageHeartRate = activity.Average; + var heartRateVariability = activity.Variability; + var heartRateZones = CalculateHeartRateZones(age); + var effortScore = EvaluateEffort(activity); + + + var (seuilBPM, vo2Max) = SeuilBPMavance(gender, age, poids, dureeActivity); + Dictionary healthMetrics = new Dictionary(); + + // Conseil pour AverageHeartRate + string averageHeartRateAdvice = averageHeartRate > seuilBPM + ? "Votre rythme cardiaque moyen est supérieur au seuil recommandé. Envisagez de réduire l'intensité." + : "Votre rythme cardiaque moyen est dans une bonne plage. Continuez à maintenir votre intensité actuelle."; + + // Conseil pour Vo2Max + string vo2MaxAdvice; + if (vo2Max < 30) + vo2MaxAdvice = + "Votre Vo2 max est faible, envisagez d'augmenter progressivement l'intensité de vos entraînements."; + else if (vo2Max < 40) + vo2MaxAdvice = "Votre Vo2 max est dans la moyenne. Continuez de travailler sur votre endurance."; + else vo2MaxAdvice = "Votre Vo2 max est excellente. Vous pourriez bénéficier d'entraînements à haute intensité."; + + // Conseil basé sur la comparaison avec NormalBpm + string normalBpmAdvice = seuilBPM > averageHeartRate + ? "Votre BPM normal est plus élevé que la moyenne, ce qui peut indiquer un bon niveau de forme physique." + : "Votre BPM normal est inférieur à la moyenne, assurez-vous de surveiller votre intensité d'entraînement."; + // Conseil pour HeartRateVariability + string hrvAdvice = heartRateVariability < 40 + ? "Votre HRV est basse, ce qui peut indiquer un stress élevé ou une récupération insuffisante. Envisagez d'améliorer votre récupération." + : heartRateVariability < 60 + ? "Votre HRV est dans une plage moyenne. Continuez de surveiller votre récupération et votre stress." + : "Votre HRV est élevée, indiquant une bonne récupération et une gestion du stress. Continuez vos bonnes pratiques de gestion de la santé."; + + HeartRateZone currentZone = heartRateZones.Find(zone => + averageHeartRate >= zone.MinHeartRate && averageHeartRate <= zone.MaxHeartRate); + string heartRateZoneAdvice; + if (currentZone != null) + { + heartRateZoneAdvice = $"Votre BPM moyen est dans la zone '{currentZone.Name}', qui est idéale pour "; + switch (currentZone.Name) + { + case "Repos": + heartRateZoneAdvice += "favoriser la récupération."; + break; + case "Endurance": + heartRateZoneAdvice += "améliorer l'endurance cardiovasculaire et brûler des graisses."; + break; + case "Aérobie": + heartRateZoneAdvice += "améliorer votre capacité aérobie."; + break; + case "Anaérobie": + heartRateZoneAdvice += "améliorer la performance à haute intensité."; + break; + case "VO2 Max": + heartRateZoneAdvice += "maximiser la performance et la capacité aérobie."; + break; + default: + heartRateZoneAdvice = + "Cette zone est spécifique et peut avoir différents objectifs en fonction de votre plan d'entraînement."; + break; + } + } + else + { + heartRateZoneAdvice = + "Vous n'êtes dans aucune zone spécifique. Assurez-vous que votre BPM moyen est correctement mesuré."; + } + + // Comparaison de l'effort objectif avec l'effort perçu + var effortAccuracy = CompareEffort(effortFelt, (int)effortScore); + + // Remplissage du dictionnaire + healthMetrics.Add("AverageHeartRate", (averageHeartRate, averageHeartRateAdvice)); + healthMetrics.Add("Vo2Max", (vo2Max, vo2MaxAdvice)); + healthMetrics.Add("NormalBpm", (seuilBPM, normalBpmAdvice)); + healthMetrics.Add("HeartRateVariability", (heartRateVariability, hrvAdvice)); + healthMetrics.Add("HeartRateZone", (averageHeartRate, heartRateZoneAdvice)); + healthMetrics.Add("Duration", + (dureeActivity, + dureeActivity < 75 + ? "Vous pourriez augmenter la durée de vos activités pour atteindre les recommandations." + : "Votre durée d'activité est conforme aux recommandations.")); + healthMetrics.Add("Effort", (effortScore, GenerateEffortAdvice(effortAccuracy))); + return healthMetrics; + } + public static string GenerateAverageHeartRateAdvice(float averageHeartRate, double seuilBPM) + { + return averageHeartRate > seuilBPM + ? "Votre rythme cardiaque moyen est supérieur au seuil recommandé. Envisagez de réduire l'intensité." + : "Votre rythme cardiaque moyen est dans une bonne plage. Continuez à maintenir votre intensité actuelle."; + } + public static string GenerateVo2MaxAdvice(double vo2Max) + { + if (vo2Max < 30) + return "Votre Vo2 max est faible, envisagez d'augmenter progressivement l'intensité de vos entraînements."; + if (vo2Max < 40) + return "Votre Vo2 max est dans la moyenne. Continuez de travailler sur votre endurance."; + return "Votre Vo2 max est excellente. Vous pourriez bénéficier d'entraînements à haute intensité."; + } + public static string GenerateNormalBpmAdvice(double normalBpm,double averageHeartRate) + { + return normalBpm > averageHeartRate + ? "Votre BPM normal est plus élevé que la moyenne, ce qui peut indiquer un bon niveau de forme physique." + : "Votre BPM normal est inférieur à la moyenne, assurez-vous de surveiller votre intensité d'entraînement."; + } + + public static string GenerateHrvAdvice(double heartRateVariability) + { + return heartRateVariability < 40 + ? "Votre HRV est basse, ce qui peut indiquer un stress élevé ou une récupération insuffisante. Envisagez d'améliorer votre récupération." + : heartRateVariability < 60 + ? "Votre HRV est dans une plage moyenne. Continuez de surveiller votre récupération et votre stress." + : "Votre HRV est élevée, indiquant une bonne récupération et une gestion du stress. Continuez vos bonnes pratiques de gestion de la santé."; + } + public static string GenerateHeartRateZoneAdvice(string? heartRateZone) + { + return heartRateZone switch + { + "Repos" => "Favoriser la récupération.", + "Endurance" => "Améliorer l'endurance cardiovasculaire et brûler des graisses.", + "Aérobie" => "Améliorer votre capacité aérobie.", + "Anaérobie" => "Améliorer la performance à haute intensité.", + "VO2 Max" => "Maximiser la performance et la capacité aérobie.", + _ => "Cette zone est spécifique et peut avoir différents objectifs en fonction de votre plan d'entraînement." + }; + } + public static string GenerateDurationAdvice(double dureeActivity) + { + return dureeActivity < 75 + ? "Vous pourriez augmenter la durée de vos activités pour atteindre les recommandations." + : "Votre durée d'activité est conforme aux recommandations."; + } + + public static string GenerateEffortAdvice(string effortAccuracy) + { + return effortAccuracy switch + { + "Accurate" => "Votre perception de l'effort est précise. Continuez ainsi!", + "Overestimated" => "Vous surestimez votre effort. Essayez de pousser un peu plus lors de vos prochaines activités.", + "Underestimated" => "Vous sous-estimez votre effort. Vous pourriez être plus proche de vos limites que vous ne le pensez.", + _ => "Continuez à surveiller et ajuster votre effort pour de meilleurs résultats." + }; + } +} + +/* +public class EffortAnalysisResult +{ + public string EffortAccuracy { get; set; } + public string Advice { get; set; } +} + +public EffortAnalysisResult AnalyzeActivityEffort(ResponseActivityDto activity) +{ + + + var effortScore = EvaluateEffort(activity); + + // Comparaison de l'effort objectif avec l'effort perçu + var effortAccuracy = CompareEffort(activity.EffortFelt, (int)effortScore); + var result = new EffortAnalysisResult + { + EffortAccuracy = effortAccuracy, + Advice = GenerateEffortAdvice(effortAccuracy) + }; + + return result; +} +public List GetMockHeartRateData() + { + var random = new Random(); + return Enumerable.Range(1, 3600) + .Select(_ => new HeartRateTinyDto + { + HeartRate = random.Next(60, 220), + Timestamp = new DateTime(2021, 1, 1).AddSeconds(random.Next(3600)), + Latitude = random.NextDouble() * 180 - 90, + Longitude = random.NextDouble() * 360 - 180, + Altitude = random.NextDouble() * 1000, + Cadence = random.Next(60, 120), + Distance = random.NextDouble() * 100, + Speed = random.NextDouble() * 30, + Power = random.Next(0, 500), + Temperature = random.NextDouble() * 30 + }).ToList(); + } + +*/ + diff --git a/src/Model2Entities/DataSourceRepository.cs b/src/Model2Entities/DataSourceRepository.cs new file mode 100644 index 0000000..4630d12 --- /dev/null +++ b/src/Model2Entities/DataSourceRepository.cs @@ -0,0 +1,34 @@ +using Dto.Tiny; +using Entities2Dto; +using Microsoft.Extensions.Logging; +using Model.Repository; + +namespace Model2Entities; + +public partial class DbDataManager +{ + public class DataSourceRepository : IDataSourceRepository + { + private readonly DbDataManager _dataManager; + private readonly ILogger _logger; + + public DataSourceRepository(DbDataManager dbDataManager, ILogger logger) + { + _dataManager = dbDataManager; + _logger = logger; + } + + + public async Task GetItemById(int id) + { + var dataSource = await _dataManager.DbContext.DataSourcesSet.FindAsync(id); + if (dataSource == null) + { + _logger.LogInformation($"DataSource with ID {id} not found."); + return null; + } + + return dataSource.ToTinyDto(); + } + } +} \ No newline at end of file diff --git a/src/Model2Entities/DbDataManager.cs b/src/Model2Entities/DbDataManager.cs index bf1e4fd..3968739 100644 --- a/src/Model2Entities/DbDataManager.cs +++ b/src/Model2Entities/DbDataManager.cs @@ -1,4 +1,5 @@ using DbContextLib; +using Dto.Tiny; using EFMappers; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -11,6 +12,8 @@ public partial class DbDataManager: IDataManager { public IActivityRepository ActivityRepo { get; } public IUserRepository UserRepo { get; } + + public IDataSourceRepository DataSourceRepo { get; } protected HeartTrackContext DbContext { get; } protected readonly ILogger _logger = new Logger(new LoggerFactory()); @@ -21,7 +24,9 @@ public partial class DbDataManager: IDataManager DbContext = dbContext; ActivityRepo = new ActivityRepository(this, _logger); UserRepo = new UserRepository(this, _logger); + DataSourceRepo = new DataSourceRepository(this, _logger); ActivityMapper.Reset(); + UserMappeur.Reset(); // Faire pour les autres reset() des autres mappers } @@ -34,5 +39,6 @@ public partial class DbDataManager: IDataManager DbContext = new HeartTrackContext(); ActivityRepo = new ActivityRepository(this, _logger); UserRepo= new UserRepository(this, _logger); + DataSourceRepo = new DataSourceRepository(this, _logger); } } diff --git a/src/Model2Entities/UserRepository.cs b/src/Model2Entities/UserRepository.cs index 51391c3..e27b9af 100644 --- a/src/Model2Entities/UserRepository.cs +++ b/src/Model2Entities/UserRepository.cs @@ -104,6 +104,18 @@ public partial class DbDataManager return user; } + public Task GetUserTinyById(int id) + { + _logger.LogInformation($"GetTinyItemById with id {id}", id); + var userEntity = _dataManager.DbContext.AthletesSet.FindAsync(id).Result; + var user = userEntity != null ? userEntity.ToTinyDto() : null; + if (user != null) + _logger.LogInformation($"Retrieved user with ID {id}"); + else + _logger.LogWarning($"No user found with ID {id}"); + return Task.FromResult(user); + } + public async Task UpdateItem(int oldItem, User newItem) { _logger.LogInformation($"UpdateItem with id {oldItem}", oldItem); diff --git a/src/StubAPI/AthleteService.cs b/src/StubAPI/AthleteService.cs index 43673e2..2416b66 100644 --- a/src/StubAPI/AthleteService.cs +++ b/src/StubAPI/AthleteService.cs @@ -108,6 +108,11 @@ public class UserService : IUserRepository throw new NotImplementedException(); } + public Task GetUserTinyById(int id) + { + throw new NotImplementedException(); + } + public async Task> GetItems(int index, int count, string? orderingProperty = null, bool descending = false) =>await GetUsers(index, count, this.ToEnum(orderingProperty), descending); diff --git a/src/StubAPI/StubData.cs b/src/StubAPI/StubData.cs index bceb496..f21772c 100644 --- a/src/StubAPI/StubData.cs +++ b/src/StubAPI/StubData.cs @@ -1,3 +1,4 @@ +using Dto.Tiny; using Model.Manager; using Model.Repository; @@ -7,6 +8,7 @@ public class StubData : IDataManager { public IUserRepository UserRepo { get; } public IActivityRepository ActivityRepo { get; } + public IDataSourceRepository DataSourceRepo { get; } public StubData() {