Compare commits
2 Commits
f9a8dc18b0
...
6752077f43
Author | SHA1 | Date |
---|---|---|
|
6752077f43 | 1 year ago |
|
578be65f84 | 1 year ago |
@ -0,0 +1,6 @@
|
|||||||
|
namespace Model.Repository;
|
||||||
|
|
||||||
|
public interface IDataSourceRepository<T>
|
||||||
|
{
|
||||||
|
Task<T?> GetItemById(int id);
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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<HeartRateZone> CalculateHeartRateZones(int age)
|
||||||
|
{
|
||||||
|
int fcm = 220 - age; // Estimation de la FCM
|
||||||
|
List<HeartRateZone> zones = new List<HeartRateZone>
|
||||||
|
{
|
||||||
|
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<string, (double Value, string Advice)> 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<string, (double Value, string Advice)> healthMetrics = new Dictionary<string, (double Value, string Advice)>();
|
||||||
|
|
||||||
|
// 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<HeartRateTinyDto> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -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<DataSourceTinyDto>
|
||||||
|
{
|
||||||
|
private readonly DbDataManager _dataManager;
|
||||||
|
private readonly ILogger<DbDataManager> _logger;
|
||||||
|
|
||||||
|
public DataSourceRepository(DbDataManager dbDataManager, ILogger<DbDataManager> logger)
|
||||||
|
{
|
||||||
|
_dataManager = dbDataManager;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<DataSourceTinyDto?> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue