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