diff --git a/src/APIMappers/ActivityMapper.cs b/src/APIMappers/ActivityMapper.cs index 2442a40..21af46d 100644 --- a/src/APIMappers/ActivityMapper.cs +++ b/src/APIMappers/ActivityMapper.cs @@ -1,4 +1,6 @@ using Dto; +using Dto.Tiny; +using Entities; using Model; using Shared; @@ -7,7 +9,8 @@ namespace APIMappers; public static class ActivityMapper { private static GenericMapper _mapper = new(); - + private static GenericMapper _mapperTiny = new (); + public static Activity ToModel(this ActivityDto activityDto, User user) { Func create = activity => new Activity @@ -72,6 +75,28 @@ public static class ActivityMapper return model.ToU(_mapper, create, link); } + public static ActivityEntity ToEntity(this ActivityTinyDto tinyDto) + { + Func create = dto => new ActivityEntity + { + Type = dto.Type, + Date = DateOnly.FromDateTime(dto.Date), + StartTime = TimeOnly.FromDateTime(dto.StartTime), + EndTime = TimeOnly.FromDateTime(dto.EndTime), + EffortFelt = dto.EffortFelt, + Variability = dto.Variability, + Variance = dto.Variance, + StandardDeviation = dto.StandardDeviation, + Average = dto.Average, + Maximum = dto.Maximum, + Minimum = dto.Minimum, + AverageTemperature = dto.AverageTemperature, + HasAutoPause = dto.HasAutoPause + }; + + return tinyDto.ToU(_mapperTiny, create); + } + public static IEnumerable ToModels(this IEnumerable dtos, User user) => dtos.Select(dto => dto.ToModel(user)); diff --git a/src/APIMappers/HeartRateMapper.cs b/src/APIMappers/HeartRateMapper.cs index c5f81a6..bfcaf9f 100644 --- a/src/APIMappers/HeartRateMapper.cs +++ b/src/APIMappers/HeartRateMapper.cs @@ -18,7 +18,6 @@ public static class HeartRateMapper public static HeartRateDto ToDto(this HeartRate model)//Activity activity { - // [TODO] [Dave] fix this should be activity but it boucle indefinitly var activity = new DateTime(); Func create = heartRate => new HeartRateDto diff --git a/src/DbContextLib/HeartTrackContext.cs b/src/DbContextLib/HeartTrackContext.cs index 3e94ae9..2dfb977 100644 --- a/src/DbContextLib/HeartTrackContext.cs +++ b/src/DbContextLib/HeartTrackContext.cs @@ -168,16 +168,16 @@ namespace DbContextLib .ValueGeneratedOnAdd(); modelBuilder.Entity() - .HasKey(f => new { f.FollowingId, f.FollowerId }); + .HasKey(f => new { f.FollowerId, f.FollowingId }); modelBuilder.Entity() .HasOne(fing => fing.Following) - .WithMany(fings => fings.Followings) + .WithMany(fings => fings.Followers) .HasForeignKey(fing => fing.FollowingId); modelBuilder.Entity() .HasOne(fer => fer.Follower) - .WithMany(fers => fers.Followers) + .WithMany(fers => fers.Followings) .HasForeignKey(fing => fing.FollowerId); // ! diff --git a/src/Dto/DataSourceDto.cs b/src/Dto/DataSourceDto.cs index 74705a1..21eb46b 100644 --- a/src/Dto/DataSourceDto.cs +++ b/src/Dto/DataSourceDto.cs @@ -12,11 +12,9 @@ public class DataSourceDto public float Precision { get; set; } - // [TODO] [Dave] Add a property to store the athletes and the activities so maybe adapt to have a tiny DTO [JsonIgnore] public IEnumerable? Athletes { get; set; } - // [TODO] [Dave] Add a property to store the athletes and the activities so maybe adapt to have a tiny DTO [JsonIgnore] public IEnumerable? Activities { get; set; } } \ No newline at end of file diff --git a/src/Dto/NewActivityDto.cs b/src/Dto/NewActivityDto.cs new file mode 100644 index 0000000..e3bd0f1 --- /dev/null +++ b/src/Dto/NewActivityDto.cs @@ -0,0 +1,12 @@ +using Dto.Tiny; + +namespace Dto; + +public class NewActivityDto +{ + public ActivityTinyDto Activity { get; set; } + public HeartRateTinyDto[]? HeartRates { get; set; } + public int? DataSourceId { get; set; } + public int AthleteId { get; set; } + +} \ No newline at end of file diff --git a/src/Dto/ResponseActivityDto.cs b/src/Dto/ResponseActivityDto.cs new file mode 100644 index 0000000..dd92956 --- /dev/null +++ b/src/Dto/ResponseActivityDto.cs @@ -0,0 +1,25 @@ +using Dto.Tiny; + +namespace Dto; + +public class ResponseActivityDto +{ + public int Id { get; set; } + public string Type { get; set; } = ""; + public DateTime Date { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public int EffortFelt { get; set; } + public float Variability { get; set; } + public float Variance { get; set; } + public float StandardDeviation { get; set; } + public float Average { get; set; } + public int Maximum { get; set; } + public int Minimum { get; set; } + public float AverageTemperature { get; set; } + public bool HasAutoPause { get; set; } + public HeartRateTinyDto[]? HeartRates { get; set; } + public DataSourceTinyDto? DataSource { get; set; } + public UserTinyDto? Athlete { get; set; } + +} \ No newline at end of file diff --git a/src/Dto/ResponseDataSourceDto.cs b/src/Dto/ResponseDataSourceDto.cs new file mode 100644 index 0000000..ae260f6 --- /dev/null +++ b/src/Dto/ResponseDataSourceDto.cs @@ -0,0 +1,18 @@ +using Dto.Tiny; + +namespace Dto; + +public class ResponseDataSourceDto +{ + public int Id { get; set; } + + public string Type { get; set; } = "Unknown"; + + public string Model { get; set; } + + public float Precision { get; set; } + + public ActivityTinyDto[]? Activities { get; set; } + + public UserTinyDto[]? Users { get; set; } +} \ No newline at end of file diff --git a/src/Dto/ResponseUserDto.cs b/src/Dto/ResponseUserDto.cs new file mode 100644 index 0000000..673d00f --- /dev/null +++ b/src/Dto/ResponseUserDto.cs @@ -0,0 +1,28 @@ +using System.ComponentModel.DataAnnotations; +using Dto.Tiny; + +namespace Dto; + +public class ResponseUserDto +{ + public int Id { get; set; } + [MaxLength(100)] + public required string Username { get; set; } + [MaxLength(150)] + public required string LastName { get; set; } + [MaxLength(100)] + public required string FirstName { get; set; } + public required string Email { get; set; } + public required string Sexe { get; set; } + public float Lenght { get; set; } + public float Weight { get; set; } + public string? Password { get; set; } + public DateTime DateOfBirth { get; set; } + public string ProfilePicture { get; set; } = "https://davidalmeida.site/assets/me_avatar.f77af006.png"; + public bool IsCoach { get; set; } + public LargeImageDto? Image { get; set; } + public ActivityTinyDto[] Activities { get; set; } + public DataSourceTinyDto DataSource { get; set; } + public FriendshipDto?[] Followers { get; set; } + public FriendshipDto?[] Followings { get; set; } +} \ No newline at end of file diff --git a/src/Dto/Tiny/ActivityTinyDto.cs b/src/Dto/Tiny/ActivityTinyDto.cs new file mode 100644 index 0000000..2865be0 --- /dev/null +++ b/src/Dto/Tiny/ActivityTinyDto.cs @@ -0,0 +1,19 @@ +namespace Dto.Tiny; + +public class ActivityTinyDto +{ + public int? Id { get; set; } + public string Type { get; set; } = ""; + public DateTime Date { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public int EffortFelt { get; set; } + public float Variability { get; set; } + public float Variance { get; set; } + public float StandardDeviation { get; set; } + public float Average { get; set; } + public int Maximum { get; set; } + public int Minimum { get; set; } + public float AverageTemperature { get; set; } + public bool HasAutoPause { get; set; } +} \ No newline at end of file diff --git a/src/Dto/Tiny/DataSourceTinyDto.cs b/src/Dto/Tiny/DataSourceTinyDto.cs new file mode 100644 index 0000000..0cbf471 --- /dev/null +++ b/src/Dto/Tiny/DataSourceTinyDto.cs @@ -0,0 +1,12 @@ +namespace Dto.Tiny; + +public class DataSourceTinyDto +{ + public int Id { get; set; } + + public string Type { get; set; } = "Unknown"; + + public string Model { get; set; } + + public float Precision { get; set; } +} \ No newline at end of file diff --git a/src/Dto/Tiny/FriendshipDto.cs b/src/Dto/Tiny/FriendshipDto.cs new file mode 100644 index 0000000..76deabd --- /dev/null +++ b/src/Dto/Tiny/FriendshipDto.cs @@ -0,0 +1,7 @@ +namespace Dto.Tiny; + +public class FriendshipDto +{ + public int FollowedId { get; set; } + public int FollowerId { get; set; } +} \ No newline at end of file diff --git a/src/Dto/Tiny/HeartRateTinyDto.cs b/src/Dto/Tiny/HeartRateTinyDto.cs new file mode 100644 index 0000000..a80472b --- /dev/null +++ b/src/Dto/Tiny/HeartRateTinyDto.cs @@ -0,0 +1,16 @@ +namespace Dto.Tiny; + +public class HeartRateTinyDto +{ + public int Id { get; set; } + public DateTime Timestamp { get; set; } + public double? Latitude { get; set; } + public double? Longitude { get; set; } + public double? Altitude { get; set; } + public int HeartRate { get; set; } + public int? Cadence { get; set; } + public double? Distance { get; set; } + public double? Speed { get; set; } + public int? Power { get; set; } + public double? Temperature { get; set; } +} \ No newline at end of file diff --git a/src/Dto/Tiny/UserTinyDto.cs b/src/Dto/Tiny/UserTinyDto.cs new file mode 100644 index 0000000..7f5df8f --- /dev/null +++ b/src/Dto/Tiny/UserTinyDto.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Dto.Tiny; + +public class UserTinyDto +{ + public int Id { get; set; } + [MaxLength(100)] + public required string Username { get; set; } + [MaxLength(150)] + public required string LastName { get; set; } + [MaxLength(100)] + public required string FirstName { get; set; } + public required string Email { get; set; } + public required string Sexe { get; set; } + public float Lenght { get; set; } + public float Weight { get; set; } + public string? Password { get; set; } + public DateTime DateOfBirth { get; set; } + public string ProfilePicture { get; set; } = "https://davidalmeida.site/assets/me_avatar.f77af006.png"; + public bool IsCoach { get; set; } +} \ No newline at end of file diff --git a/src/EFMappers/AthleteMappeur.cs b/src/EFMappers/AthleteMappeur.cs index ef779f1..1cd39a8 100644 --- a/src/EFMappers/AthleteMappeur.cs +++ b/src/EFMappers/AthleteMappeur.cs @@ -62,17 +62,6 @@ public static class UserMappeur entity.Activities = user.Activities.ToEntities().ToList(); entity.IsCoach = user.Role is Coach; entity.Image = user.Image.ToEntity(); - /*if (user.Role is Coach) - entity.TrainingsCoach = user.Traning.ToEntities().ToList(); - else - entity.TrainingsAthlete = user.Traning.ToEntities().ToList(); - */ - // entity.NotificationsReceived = user.Notifications.ToEntities().ToList(); - - // entity.DataSource = user.DataSources.ToEntities().ToList(); - - // [TODO] [DAVE] : Add the link to the friendship - }; return model.ToU(_mapper, create, link); diff --git a/src/Entities/ActivityEntity.cs b/src/Entities/ActivityEntity.cs index d1af116..9776074 100644 --- a/src/Entities/ActivityEntity.cs +++ b/src/Entities/ActivityEntity.cs @@ -105,6 +105,6 @@ namespace Entities public int AthleteId { get; set; } - public AthleteEntity Athlete { get; set; } = null!; + public AthleteEntity Athlete { get; set; } } } \ No newline at end of file diff --git a/src/Entities/AthleteEntity.cs b/src/Entities/AthleteEntity.cs index 199d635..3b89fbe 100644 --- a/src/Entities/AthleteEntity.cs +++ b/src/Entities/AthleteEntity.cs @@ -87,7 +87,6 @@ namespace Entities /// public bool IsCoach { get; set; } - // [TODO] [DAVE] Check Image public string? ProfilPicture { get; set; } public LargeImageEntity? Image { get; set; } diff --git a/src/Entities2Dto/ActivityMapper.cs b/src/Entities2Dto/ActivityMapper.cs new file mode 100644 index 0000000..116f63a --- /dev/null +++ b/src/Entities2Dto/ActivityMapper.cs @@ -0,0 +1,102 @@ +using Dto; +using Dto.Tiny; +using Entities; +using Shared; + +namespace Entities2Dto; + +public static class ActivityMapper +{ + private static GenericMapper _mapper = new (); + + private static GenericMapper _mapperFull = new (); + + public static void Reset() + { + _mapper.Reset(); + _mapperFull.Reset(); + } + + public static ActivityTinyDto ToDto(this ActivityEntity entity) + { + Console.WriteLine("dfghf"); + Func create = activityEntity => new ActivityTinyDto + { + Id = activityEntity.IdActivity, + Type = activityEntity.Type, + Date = activityEntity.Date.ToDateTime(TimeOnly.MinValue), + StartTime = activityEntity.Date.ToDateTime(activityEntity.StartTime), + EndTime = activityEntity.Date.ToDateTime(activityEntity.EndTime), + EffortFelt = activityEntity.EffortFelt, + Variability = activityEntity.Variability, + Variance = activityEntity.Variance, + StandardDeviation = activityEntity.StandardDeviation, + Average = activityEntity.Average, + Maximum = activityEntity.Maximum, + Minimum = activityEntity.Minimum, + AverageTemperature = activityEntity.AverageTemperature, + HasAutoPause = activityEntity.HasAutoPause + }; + return entity.ToT(_mapper, create, null, false); + } + + public static ActivityEntity ToEntity(this ActivityTinyDto dto) + { + Func create = activity => new ActivityEntity + { + Type = activity.Type, + Date = DateOnly.FromDateTime(activity.Date), + StartTime = TimeOnly.FromDateTime(activity.StartTime), + EndTime = TimeOnly.FromDateTime(activity.EndTime), + EffortFelt = activity.EffortFelt, + Variability = activity.Variability, + Variance = activity.Variance, + StandardDeviation = activity.StandardDeviation, + Average = activity.Average, + Maximum = activity.Maximum, + Minimum = activity.Minimum, + AverageTemperature = activity.AverageTemperature, + HasAutoPause = activity.HasAutoPause + }; + return dto.ToU(_mapper, create); + } + + public static ResponseActivityDto ToResponseDto(this ActivityEntity entity) + { + Func create = activityEntity => new ResponseActivityDto + { + Id = activityEntity.IdActivity, + Type = activityEntity.Type, + Date = activityEntity.Date.ToDateTime(TimeOnly.MinValue), + StartTime = activityEntity.Date.ToDateTime(activityEntity.StartTime), + EndTime = activityEntity.Date.ToDateTime(activityEntity.EndTime), + EffortFelt = activityEntity.EffortFelt, + Variability = activityEntity.Variability, + Variance = activityEntity.Variance, + StandardDeviation = activityEntity.StandardDeviation, + Average = activityEntity.Average, + Maximum = activityEntity.Maximum, + Minimum = activityEntity.Minimum, + AverageTemperature = activityEntity.AverageTemperature, + HasAutoPause = activityEntity.HasAutoPause + }; + + Action linker = (activityEntity, activity) => + { + if (activityEntity.HeartRates != null) activity.HeartRates = activityEntity.HeartRates.ToTinyDtos().ToArray(); + activity.DataSource = activityEntity.DataSource != null ? activityEntity.DataSource.ToTinyDto() : null; + activity.Athlete = activityEntity.Athlete.ToTinyDto(); + }; + + return entity.ToT(_mapperFull, create, linker, false); + } + + public static IEnumerable ToTinyDtos(this IEnumerable entities) + => entities.Select(a => a.ToDto()); + + public static IEnumerable ToEntities(this IEnumerable dtos) + => dtos.Select(a => a.ToEntity()); + + + +} \ No newline at end of file diff --git a/src/Entities2Dto/DataSourceMapper.cs b/src/Entities2Dto/DataSourceMapper.cs new file mode 100644 index 0000000..2aa5a50 --- /dev/null +++ b/src/Entities2Dto/DataSourceMapper.cs @@ -0,0 +1,70 @@ +using Dto; +using Dto.Tiny; +using Entities; +using Shared; + +namespace Entities2Dto; + +public static class DataSourceMapper +{ + private static GenericMapper _mapper = new(); + + private static GenericMapper _mapperFull = new(); + + public static void Reset() + { + _mapper.Reset(); + _mapperFull.Reset(); + } + + public static DataSourceTinyDto ToTinyDto(this DataSourceEntity entity) + { + Func create = dataSourceEntity => new DataSourceTinyDto + { + Id = dataSourceEntity.IdSource, + Type = dataSourceEntity.Type, + Model = dataSourceEntity.Model, + Precision = dataSourceEntity.Precision + }; + return entity.ToT(_mapper, create, null,false); + } + + public static DataSourceEntity ToEntity(this DataSourceTinyDto dto) + { + Func create = dataSource => new DataSourceEntity + { + IdSource = dataSource.Id, + Type = dataSource.Type, + Model = dataSource.Model, + Precision = dataSource.Precision + }; + return dto.ToU(_mapper, create); + } + + public static ResponseDataSourceDto ToResponseDto(this DataSourceEntity entity) + { + Func create = dataSourceEntity => new ResponseDataSourceDto + { + Id = dataSourceEntity.IdSource, + Type = dataSourceEntity.Type, + Model = dataSourceEntity.Model, + Precision = dataSourceEntity.Precision, + }; + + Action linker = (dataSourceEntity, dto) => + { + dto.Activities = dataSourceEntity.Activities.ToTinyDtos().ToArray(); + dto.Users = dataSourceEntity.Athletes.ToTinyDtos().ToArray(); + }; + + return entity.ToT(_mapperFull, create, linker, false); + } + + public static IEnumerable ToTinyDtos(this IEnumerable entities) + => entities.Select(e => e.ToTinyDto()); + + public static IEnumerable ToEntities(this IEnumerable dtos) + => dtos.Select(d => d.ToEntity()); + + +} \ No newline at end of file diff --git a/src/Entities2Dto/FriendshipMapper.cs b/src/Entities2Dto/FriendshipMapper.cs new file mode 100644 index 0000000..ccc9707 --- /dev/null +++ b/src/Entities2Dto/FriendshipMapper.cs @@ -0,0 +1,32 @@ +using Dto.Tiny; +using Entities; +using Shared; + +namespace Entities2Dto; + +public static class FriendshipMapper +{ + private static GenericMapper _mapper = new(); + + public static void Reset() + { + _mapper.Reset(); + } + + public static FriendshipDto ToTinyDto(this FriendshipEntity entity) + { + Func create = friendshipEntity => new FriendshipDto + { + FollowedId = friendshipEntity.FollowingId, + FollowerId = friendshipEntity.FollowerId, + }; + + return entity.ToT(_mapper, create, null, false); + } + + public static IEnumerable ToTinyDtos(this IEnumerable entities) + => entities.Select(e => e.ToTinyDto()); + + + +} \ No newline at end of file diff --git a/src/Entities2Dto/HeartRateMapper.cs b/src/Entities2Dto/HeartRateMapper.cs new file mode 100644 index 0000000..5ef863c --- /dev/null +++ b/src/Entities2Dto/HeartRateMapper.cs @@ -0,0 +1,63 @@ +using Dto.Tiny; +using Entities; +using Shared; + +namespace Entities2Dto; + +public static class HeartRateMapper +{ + + private static GenericMapper _mapper = new(); + + public static void Reset() + { + _mapper.Reset(); + } + + public static HeartRateTinyDto ToTinyDto(this HeartRateEntity entity) + { + var activityTmp = new DateTime(); + Func create = heartRateEntity => new HeartRateTinyDto + { + Id = heartRateEntity.IdHeartRate, + HeartRate = heartRateEntity.Bpm, + Timestamp = activityTmp, + Latitude = heartRateEntity.Latitude, + Longitude = heartRateEntity.Longitude, + Altitude = heartRateEntity.Altitude, + Cadence = heartRateEntity.Cadence, + Distance = heartRateEntity.Distance, + Speed = heartRateEntity.Speed, + Power = heartRateEntity.Power, + Temperature = heartRateEntity.Temperature + }; + + return entity.ToT(_mapper, create, null, false); + } + + public static HeartRateEntity ToEntity(this HeartRateTinyDto dto) + { + Func create = heartRate => new HeartRateEntity + { + IdHeartRate = heartRate.Id, + Bpm = heartRate.HeartRate, + Time = TimeOnly.FromDateTime(heartRate.Timestamp), + Latitude = heartRate.Latitude, + Longitude = heartRate.Longitude, + Altitude = heartRate.Altitude, + Cadence = heartRate.Cadence, + Distance = heartRate.Distance, + Speed = heartRate.Speed, + Power = heartRate.Power, + Temperature = heartRate.Temperature + }; + return dto.ToU(_mapper, create); + } + + public static IEnumerable ToTinyDtos(this IEnumerable entities) + => entities.Select(e => e.ToTinyDto()); + + public static IEnumerable ToEntities(this IEnumerable dtos) + => dtos.Select(d => d.ToEntity()); + +} \ No newline at end of file diff --git a/src/Entities2Dto/LargeImageMapper.cs b/src/Entities2Dto/LargeImageMapper.cs new file mode 100644 index 0000000..8a225d5 --- /dev/null +++ b/src/Entities2Dto/LargeImageMapper.cs @@ -0,0 +1,32 @@ +using Dto; +using Entities; +using Shared; + +namespace Entities2Dto; + +public static class LargeImageMapper +{ + private static GenericMapper _mapper = new(); + + public static void Reset() + { + _mapper.Reset(); + } + + public static LargeImageDto ToDto(this LargeImageEntity entity) + { + Func create = largeImageEntity => new() { Base64 = largeImageEntity.Base64 }; + + return entity.ToT(_mapper, create, null, false); + } + + public static LargeImageEntity ToEntity(this LargeImageDto dto) + { + Func create = largeImage => new LargeImageEntity + { + Base64 = largeImage.Base64 + }; + + return dto.ToU(_mapper, create); + } +} \ No newline at end of file diff --git a/src/Entities2Dto/UserMappeur.cs b/src/Entities2Dto/UserMappeur.cs new file mode 100644 index 0000000..71b2dcf --- /dev/null +++ b/src/Entities2Dto/UserMappeur.cs @@ -0,0 +1,102 @@ +using Dto; +using Dto.Tiny; +using Entities; +using Shared; + +namespace Entities2Dto; + +public static class UserMappeur +{ + private static GenericMapper _mapper = new(); + private static GenericMapper _mapperFull = new(); + + + public static void Reset() + { + _mapper.Reset(); + _mapperFull.Reset(); + } + + public static UserTinyDto ToTinyDto(this AthleteEntity entity) + { + Func create = athleteEntity => new UserTinyDto + { + Id = athleteEntity.IdAthlete, + FirstName = athleteEntity.FirstName, + LastName = athleteEntity.LastName, + Email = athleteEntity.Email, + Password = athleteEntity.Password, + DateOfBirth = athleteEntity.DateOfBirth.ToDateTime(TimeOnly.MinValue), + Sexe = athleteEntity.Sexe, + Username = athleteEntity.Username, + Weight = athleteEntity.Weight, + Lenght = (float)athleteEntity.Length, + ProfilePicture = athleteEntity.ProfilPicture ?? "", + IsCoach = athleteEntity.IsCoach + }; + + return entity.ToT(_mapper, create, null, false); + } + + public static AthleteEntity ToEntity(this UserTinyDto model) + { + Func create = user => new AthleteEntity + { + IdAthlete = user.Id, + Username = user.Username, + Sexe = user.Sexe, + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password ?? "", + DateOfBirth = DateOnly.FromDateTime(user.DateOfBirth), + IsCoach = user.IsCoach, + Weight = user.Weight, + Length = user.Lenght, + ProfilPicture = user.ProfilePicture + }; + + return model.ToU(_mapper, create); + } + + public static ResponseUserDto ToResponseDto(this AthleteEntity entity) + { + Func creator = athleteEntity => new ResponseUserDto + { + Id = athleteEntity.IdAthlete, + FirstName = athleteEntity.FirstName, + LastName = athleteEntity.LastName, + Email = athleteEntity.Email, + Password = athleteEntity.Password, + DateOfBirth = athleteEntity.DateOfBirth.ToDateTime(TimeOnly.MinValue), + Sexe = athleteEntity.Sexe, + Username = athleteEntity.Username, + Weight = athleteEntity.Weight, + Lenght = (float)athleteEntity.Length, + ProfilePicture = athleteEntity.ProfilPicture ?? "", + IsCoach = athleteEntity.IsCoach, + }; + + Action linker = (athleteEntity, userDto) => + { + userDto.Activities = athleteEntity.Activities.ToTinyDtos().ToArray(); + userDto.Image = athleteEntity.Image?.ToDto(); + userDto.DataSource = athleteEntity.DataSource.ToTinyDto(); + userDto.Followers = athleteEntity.Followers.ToTinyDtos().ToArray(); + userDto.Followings = athleteEntity.Followings.ToTinyDtos().ToArray(); + }; + + return entity.ToT(_mapperFull, creator, linker, false); + } + + public static IEnumerable ToTinyDtos(this IEnumerable entities) + => entities.Select(e => e.ToTinyDto()); + + public static IEnumerable ToEntities(this IEnumerable models) + => models.Select(m => m.ToEntity()); + + + + + +} \ No newline at end of file diff --git a/src/HeartTrack.sln b/src/HeartTrack.sln index 8bd8954..a20b9ff 100644 --- a/src/HeartTrack.sln +++ b/src/HeartTrack.sln @@ -43,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "APIMappers", "APIMappers\AP EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestsModel", "Tests\UnitTestsModel\UnitTestsModel.csproj", "{508D380F-145C-437E-A7DF-7A17C526B2F3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entities2Dto", "Entities2Dto\Entities2Dto.csproj", "{1B15D383-1DFA-47E8-86EC-AC631B15FBEB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -121,6 +123,10 @@ Global {508D380F-145C-437E-A7DF-7A17C526B2F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {508D380F-145C-437E-A7DF-7A17C526B2F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {508D380F-145C-437E-A7DF-7A17C526B2F3}.Release|Any CPU.Build.0 = Release|Any CPU + {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B15D383-1DFA-47E8-86EC-AC631B15FBEB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/HeartTrackAPI/Controllers/ActivityController.cs b/src/HeartTrackAPI/Controllers/ActivityController.cs index b6e160b..79f8654 100644 --- a/src/HeartTrackAPI/Controllers/ActivityController.cs +++ b/src/HeartTrackAPI/Controllers/ActivityController.cs @@ -1,9 +1,9 @@ using APIMappers; using Dto; +using Dto.Tiny; using HeartTrackAPI.Request; using HeartTrackAPI.Responce; using Microsoft.AspNetCore.Mvc; -using Model; using Shared; using Model.Manager; using Model.Repository; @@ -30,7 +30,7 @@ public class ActivityController : Controller [ProducesResponseType(typeof(PageResponse), 200)] [ProducesResponseType(400)] [ProducesResponseType(500)] - public async Task>> GetActivities([FromQuery] PageRequest pageRequest) + public async Task>> GetActivities([FromQuery] PageRequest pageRequest) { try { @@ -46,7 +46,9 @@ public class ActivityController : Controller { return NotFound("No activities found"); } - var pageResponse = new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto())); + + var pageResponse = + new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities); return Ok(pageResponse); } catch (Exception e) @@ -57,83 +59,30 @@ public class ActivityController : Controller } [HttpPost] - public async Task PostActivity(ActivityDto activityDto) + public async Task PostActivity(NewActivityDto activityDto) { - var user = await _userRepository.GetItemById(activityDto.AthleteId); + + var user = await _userRepository.GetUserById(activityDto.AthleteId); if (user == null) { _logger.LogError("Athlete with id {id} not found", activityDto.AthleteId); return NotFound($"Athlete with id {activityDto.AthleteId} not found"); } - var tmp = user.DataSources.FirstOrDefault(ds => ds.Id == activityDto.DataSourceId); - if (tmp == null) + if (activityDto.DataSourceId != null && user.DataSource.Id != activityDto.DataSourceId) { - _logger.LogError("DataSource with id {id} not found", activityDto.DataSourceId); + _logger.LogError("DataSource with id {id} not found for this user", activityDto.DataSourceId); return NotFound($"DataSource with id {activityDto.DataSourceId} not found"); } - var activity = activityDto.ToModel(user); - var result = await _activityService.AddActivity(activity); + var result = await _activityService.AddActivity(activityDto); + if (result == null) { return BadRequest(); } - return CreatedAtAction(nameof(GetActivity), new { id = result.Id }, result.ToDto()); + return CreatedAtAction(nameof(GetActivity), new { id = result.Id }, result); } - /* - public async Task PostFitFile( Stream file, string contentType) // [FromForm] - { - if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) - { - ModelState.AddModelError("File", - $"The request couldn't be processed (Error 1)."); - // Log error - - return BadRequest(ModelState); - } - if (file == null) - { - return BadRequest("No file was provided"); - } - //var fileUploadSummary = await _fileService.UploadFileAsync(HttpContext.Request.Body, Request.ContentType); -// var activity = await _activityManager.AddActivityFromFitFile(file); - var activity = new Activity - { - Id = 1, - Type = "Running", - Date = new DateTime(2021, 10, 10), - StartTime = new DateTime(2021, 10, 10, 10, 0, 0), - EndTime = new DateTime(2021, 10, 10, 11, 0, 0), - Effort = 3, - Variability = 0.5f, - Variance = 0.5f, - StandardDeviation = 0.5f, - Average = 5.0f, - Maximum = 10, - Minimum = 0, - AverageTemperature = 20.0f, - HasAutoPause = false, - Users = - { - new User - { - Id = 3, Username = "Athlete3", - ProfilePicture = - "https://plus.unsplash.com/premium_photo-1705091981693-6006f8a20479?q=80&w=1974&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", - FirstName = "First3", LastName = "Last3", - Sexe = "M", Lenght = 190, Weight = 80, DateOfBirth = new DateTime(1994, 3, 3), Email = "ath@ex.fr", - Role = new Athlete() - } - } - }; - if (activity == null) - { - return BadRequest("The file provided is not a valid fit file"); - } - return CreatedAtAction(nameof(GetActivity), new { id = activity.Id }, activity.ToDto()); - }*/ - [HttpGet("{id}")] public async Task> GetActivity(int id) { @@ -158,25 +107,15 @@ public class ActivityController : Controller } [HttpPut("{id}")] - public async Task PutActivity(int id, ActivityDto activityDto) + public async Task PutActivity(int id, ActivityTinyDto activityDto) { - if (id != activityDto.Id) - { - return BadRequest(); - } - var user = await _userRepository.GetItemById(activityDto.AthleteId); - if (user == null) - { - _logger.LogError("Athlete with id {id} not found", activityDto.AthleteId); - return NotFound($"Athlete with id {activityDto.AthleteId} not found"); - } - var activity = activityDto.ToModel(user); - var result = await _activityService.UpdateActivity(id, activity); + var result = await _activityService.UpdateActivity(id, activityDto); if (result == null) { return NotFound(); } - return NoContent(); + + return Ok(result); } /// diff --git a/src/HeartTrackAPI/Controllers/AnalysisController.cs b/src/HeartTrackAPI/Controllers/AnalysisController.cs new file mode 100644 index 0000000..e4f9fcb --- /dev/null +++ b/src/HeartTrackAPI/Controllers/AnalysisController.cs @@ -0,0 +1,70 @@ +using Dto.Tiny; +using Microsoft.AspNetCore.Mvc; + +namespace HeartTrackAPI.Controllers; + +[ApiController] +[ApiVersion("1.0")] +[Route("api/[controller]")] +public class AnalysisController : ControllerBase +{ + 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")] + public IActionResult GetHeartRateZones() + { + var heartRates = GetMockHeartRateData(); + var results = _heartRateZones.Select(zone => new HeartRateZoneResult + { + Zone = zone.Name, + TimeSpent = CalculateTimeInZone(zone, heartRates) + }).ToList(); + return Ok(results); + } + + private TimeSpan CalculateTimeInZone(HeartRateZone zone, List heartRates) + { + var secondsInZone = + heartRates.Count(hr => hr.HeartRate >= zone.MinHeartRate && hr.HeartRate <= zone.MaxHeartRate); + return TimeSpan.FromSeconds(secondsInZone); + } + + 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 diff --git a/src/HeartTrackAPI/Controllers/UsersController.cs b/src/HeartTrackAPI/Controllers/UsersController.cs index cd9f0b6..c7daf65 100644 --- a/src/HeartTrackAPI/Controllers/UsersController.cs +++ b/src/HeartTrackAPI/Controllers/UsersController.cs @@ -1,8 +1,11 @@ using System.ComponentModel.DataAnnotations; using APIMappers; using Dto; +using Dto.Tiny; using HeartTrackAPI.Request; using HeartTrackAPI.Responce; +using HeartTrackAPI.Utils; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Model.Manager; @@ -38,10 +41,10 @@ public class UsersController : Controller /// La demande de pagination est invalide. /// Erreur interne du serveur. [HttpGet] - [ProducesResponseType(typeof(PageResponse), 200)] + [ProducesResponseType(typeof(PageResponse), 200)] [ProducesResponseType(400)] [ProducesResponseType(500)] - public async Task>> Get([FromQuery] PageRequest request) + public async Task>> Get([FromQuery] PageRequest request) { try { @@ -54,8 +57,8 @@ public class UsersController : Controller _logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), null); - var athletes = await _userService.GetUsers(request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false); - var pageResponse = new PageResponse(request.Index, request.Count, totalCount, athletes!.Select(a => a.ToDto())); + var athletes = await _userService.GetUsersTiny(request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false); + var pageResponse = new PageResponse(request.Index, request.Count, totalCount, athletes); return Ok(pageResponse); } catch (Exception e) @@ -74,21 +77,21 @@ public class UsersController : Controller /// Aucun utilisateur trouvé pour l'identifiant spécifié. /// Erreur interne du serveur. [HttpGet("{id}")] - [ProducesResponseType(typeof(UserDto), 200)] + [ProducesResponseType(typeof(ResponseUserDto), 200)] [ProducesResponseType(404)] [ProducesResponseType(500)] - public async Task> GetById([Range(0,int.MaxValue)]int id) + public async Task> GetById([Range(0,int.MaxValue)]int id) { try { _logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetById), id); - var athlete = await _userService.GetItemById(id); + var athlete = await _userService.GetUserById(id); if (athlete == null) { _logger.LogError("Athlete with id {id} not found", id); return NotFound($"Athlete with id {id} not found"); } - return Ok(athlete.ToDto()); + return Ok(athlete); } catch (Exception e) { @@ -110,7 +113,7 @@ public class UsersController : Controller { try { - _logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Count), null); + _logger.LogInformation("Executing {Action}", nameof(Count)); var nbUsers = await _userService.GetNbItems(); return Ok(nbUsers); } @@ -131,27 +134,27 @@ public class UsersController : Controller /// Utilisateur non trouvé. /// Erreur interne du serveur. [HttpPut("{id}")] - [ProducesResponseType(typeof(UserDto), 200)] + [ProducesResponseType(typeof(UserTinyDto), 200)] [ProducesResponseType(404)] [ProducesResponseType(500)] - public async Task> Update(int id, [FromBody] UserDto user) + public async Task> Update(int id, [FromBody] UserTinyDto user) { try { _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Update), user,id); - var athlete = await _userService.GetItemById(id); + var athlete = await _userService.GetUserById(id); if (athlete == null) { _logger.LogError("Athlete with id {id} not found", id); return NotFound($"Athlete with id {id} not found"); } - var updatedAthlete = await _userService.UpdateItem(id, user.ToModel()); + var updatedAthlete = await _userService.UpdateUser(id, user); if(updatedAthlete == null) { _logger.LogError("Error while updating athlete with id {id}", id); return Problem(); } - return Ok(updatedAthlete.ToDto()); + return Ok(updatedAthlete); } catch (Exception e) @@ -178,9 +181,8 @@ public class UsersController : Controller try { _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Delete), null,id); - - - var athlete = await _userService.GetItemById(id); + + var athlete = await _userService.GetUserById(id); if (athlete == null) { _logger.LogError("Athlete with id {id} not found", id); @@ -211,31 +213,30 @@ public class UsersController : Controller /// Utilisateur non trouvé. /// Erreur interne du serveur. [HttpGet("{id}/friends")] - [ProducesResponseType(typeof(PageResponse), 200)] + [ProducesResponseType(typeof(PageResponse), 200)] [ProducesResponseType(404)] [ProducesResponseType(500)] - public async Task>> GetFriends(int id, [FromQuery] PageRequest request) + public async Task>> GetFriends(int id, [FromQuery] PageRequest request) { try { _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(GetFriends), null,id); - var athlete = await _userService.GetItemById(id); - if (athlete == null) - { - _logger.LogError("Athlete with id {id} not found", id); - return NotFound($"Athlete with id {id} not found"); - } - var totalCount = await _userService.GetNbFriends(athlete); + var totalCount = await _userService.GetNbFriends(id); if (request.Count * request.Index >= totalCount) { _logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount); return BadRequest("To many object is asked the max is : " + totalCount); } - var friends = await _userService.GetFriends(athlete, request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false); + var friends = await _userService.GetFriends(id, request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false); if (friends == null) return NotFound(); - var pageResponse = new PageResponse(request.Index, request.Count, totalCount, friends.Select(a => a.ToDto())); + var pageResponse = new PageResponse(request.Index, request.Count, totalCount, friends); return Ok(pageResponse); } + catch(ModelNotFoundException e) + { + _logger.LogError(e, "Error while adding a friend to an athlete"); + return BadRequest(e.Message); + } catch (Exception e) { _logger.LogError(e, "Error while getting the number of users"); @@ -256,24 +257,13 @@ public class UsersController : Controller [ProducesResponseType(200)] [ProducesResponseType(404)] [ProducesResponseType(500)] - public async Task AddFriend(int id, int friendId) + public async Task AddFollowing(int id, int friendId) { try { - _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(AddFriend), friendId,id); - var athlete = await _userService.GetItemById(id); - if (athlete == null) - { - _logger.LogError("Athlete with id {id} not found", id); - return NotFound($"Athlete with id {id} not found"); - } - var friend = await _userService.GetItemById(friendId); - if (friend == null) - { - _logger.LogError("Athlete with id {id} not found", friendId); - return NotFound($"Athlete with id {friendId} not found"); - } - var isAdded = await _userService.AddFriend(athlete, friend); + _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(AddFollowing), friendId,id); + + var isAdded = await _userService.AddFollowing(id, friendId); if(!isAdded) { _logger.LogError("Error while adding friend with id {friendId} to athlete with id {id}", friendId, id); @@ -281,9 +271,14 @@ public class UsersController : Controller } return Ok(); } + catch(FriendShipException e) + { + _logger.LogError(e, "Error while adding a friend to an athlete"); + return BadRequest(e.Message); + } catch (Exception e) { - _logger.LogError(e, "Error while getting the number of users"); + _logger.LogError(e, "Error while attempting to follow a user"); return Problem(); } } @@ -307,19 +302,8 @@ public class UsersController : Controller try { _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(RemoveFriend), friendId,id); - var athlete = await _userService.GetItemById(id); - if (athlete == null) - { - _logger.LogError("Athlete with id {id} not found", id); - return NotFound($"Athlete with id {id} not found"); - } - var friend = await _userService.GetItemById(friendId); - if (friend == null) - { - _logger.LogError("Athlete with id {id} not found", friendId); - return NotFound($"Athlete with id {friendId} not found"); - } - var isRemoved = await _userService.RemoveFriend(athlete, friend); + + var isRemoved = await _userService.RemoveFollowing(id, friendId); if(!isRemoved) { _logger.LogError("Error while removing friend with id {friendId} to athlete with id {id}", friendId, id); @@ -327,55 +311,19 @@ public class UsersController : Controller } return Ok(); } - catch (Exception e) - { - _logger.LogError(e, "Error while getting the number of users"); - return Problem(); - } - } - - /// - /// Obtient la liste des athlètes d'un coach spécifique. - /// - /// L'identifiant du coach. - /// Les critères de pagination et de tri. - /// La liste paginée des athlètes. - /// Retourne la liste paginée des athlètes du coach. - /// Coach non trouvé. - /// Erreur interne du serveur. - [HttpGet("{coachId}/athletes")] - [ProducesResponseType(typeof(PageResponse), 200)] - [ProducesResponseType(404)] - [ProducesResponseType(500)] - public async Task>> GetAthletes(int coachId, [FromQuery] PageRequest request) - { - try + catch(FriendShipException e) { - _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(GetAthletes), null,coachId); - var coach = await _userService.GetItemById(coachId); - if (coach == null) - { - _logger.LogError("Athlete with id {id} not found", coachId); - return NotFound($"Athlete with id {coachId} not found"); - } - var totalCount = await _userService.GetNbFriends(coach); - if (request.Count * request.Index >= totalCount) - { - _logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", totalCount); - return BadRequest("To many object is asked the max is : " + totalCount); - } - var athletes = await _userService.GetFriends(coach, request.Index, request.Count, Enum.TryParse(request.OrderingPropertyName, out AthleteOrderCriteria result) ? result : AthleteOrderCriteria.None, request.Descending ?? false); - if (athletes == null) return NotFound(); - var pageResponse = new PageResponse(request.Index, request.Count, totalCount, athletes.Select(a => a.ToDto())); - return Ok(pageResponse); + _logger.LogError(e, "Error while removing a friend to an athlete"); + return BadRequest(e.Message); } catch (Exception e) { - _logger.LogError(e, "Error while getting the number of users"); + _logger.LogError(e, "Error while attempting to unfollow a user"); return Problem(); } } - + + /* /// /// Obtient la liste des activités d'un utilisateur spécifique. /// @@ -387,7 +335,7 @@ public class UsersController : Controller /// Erreur interne du serveur. [HttpGet("{userId}/activities")] // should be tiny DTOActivity returned with only the necessary information (will be used in the list of activities of a user) - public async Task>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest) + public async Task>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest) { try { @@ -403,7 +351,7 @@ public class UsersController : Controller { return NotFound("No activities found"); } - var pageResponse = new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto())); + var pageResponse = new PageResponse(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto())); return Ok(pageResponse); } catch (Exception e) @@ -411,7 +359,7 @@ public class UsersController : Controller _logger.LogError(e, "Error while getting all activities"); return Problem(); } - } + }*/ /// /// Déconnecte l'utilisateur actuel. diff --git a/src/Model/Repository/IActivityRepository.cs b/src/Model/Repository/IActivityRepository.cs index eab97da..84c2225 100644 --- a/src/Model/Repository/IActivityRepository.cs +++ b/src/Model/Repository/IActivityRepository.cs @@ -1,13 +1,17 @@ +using Dto; +using Dto.Tiny; using Shared; namespace Model.Repository; public interface IActivityRepository { - public Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false); + public Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false); public Task GetActivityByIdAsync(int id); public Task AddActivity(Activity activity); - public Task UpdateActivity(int id, Activity activity); + public Task AddActivity(NewActivityDto activity); + + public Task UpdateActivity(int id, ActivityTinyDto activity); public Task DeleteActivity(int id); public Task GetNbItems(); public Task?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria orderCriteria, bool descending= false); diff --git a/src/Model/Repository/IUserRepository.cs b/src/Model/Repository/IUserRepository.cs index dddc19d..a4d3c1a 100644 --- a/src/Model/Repository/IUserRepository.cs +++ b/src/Model/Repository/IUserRepository.cs @@ -1,14 +1,22 @@ -using Shared; +using Dto; +using Dto.Tiny; +using Shared; namespace Model.Repository; -public interface IUserRepository : IGenericRepository +public interface IUserRepository : IGenericRepository // Make it generic { + // [TODO] [Dave] DELETE it use just in the test public Task?> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false); - public Task AddFriend(User user, User friend); - public Task RemoveFriend(User user, User friend); - public Task?> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false); - public Task GetNbFriends(User user); + public Task?> GetUsersTiny(int index, int count, AthleteOrderCriteria? criteria , bool descending = false); + public Task AddFollowing(int fromUser, int toUser); + public Task RemoveFollowing(int fromUser, int toUser); + + // DELETE + public Task?> GetFriends(int user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false); + public Task GetNbFriends(int user); + public Task UpdateUser(int old,UserTinyDto user); + public Task GetUserById(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/Model2Entities/ActivityRepository.cs b/src/Model2Entities/ActivityRepository.cs index d3ba2da..468e334 100644 --- a/src/Model2Entities/ActivityRepository.cs +++ b/src/Model2Entities/ActivityRepository.cs @@ -1,3 +1,5 @@ +using Dto; +using Dto.Tiny; using Model; using Model.Repository; using Shared; @@ -5,6 +7,7 @@ using Model.Manager; using Microsoft.Extensions.Logging; using Entities; using EFMappers; +using Entities2Dto; using Microsoft.EntityFrameworkCore; namespace Model2Entities; @@ -21,13 +24,13 @@ public partial class DbDataManager : IDataManager this._logger = logger; } - public async Task> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false) + public async Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false) { _logger.LogInformation($"GetActivities with index {index} and count {count}", index, count); _logger.LogInformation($"GetActivities with criteria {criteria} and descending {descending}", criteria, descending); var activities = _dataManager.DbContext.ActivitiesSet - .IncludeStandardProperties().GetItemsWithFilterAndOrdering(b => true, index, count, criteria, descending).ToModels(); + .GetItemsWithFilterAndOrdering(b => true, index, count, criteria, descending).ToTinyDtos(); _logger.LogInformation($"Retrieved {activities.Count()} activities"); return await Task.FromResult(activities); @@ -67,18 +70,46 @@ public partial class DbDataManager : IDataManager } } - public async Task UpdateActivity(int id, Activity activity) + public async Task AddActivity(NewActivityDto activity) { try { - _logger.LogInformation($"Updating activity with ID {id}"); - var updatedActivity = await _dataManager.DbContext.UpdateItem(id, activity, (activity, entity) => + _logger.LogInformation("Adding new activity"); + + var addedActivity = activity.Activity.ToEntity(); + addedActivity.DataSourceId = activity.DataSourceId; + addedActivity.AthleteId = activity.AthleteId; + addedActivity.HeartRates = activity.HeartRates.ToEntities().ToList(); + + await _dataManager.DbContext.AddItem(addedActivity); + _logger.LogInformation($"Added activity with ID {addedActivity.IdActivity}"); + _dataManager.DbContext.SaveChanges(); + + return await Task.FromResult(addedActivity.ToResponseDto()); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurred while adding activity"); + throw; + } + } + + public async Task UpdateActivity(int id, ActivityTinyDto activity) + { + try + { + var entity =await _dataManager.DbContext.ActivitiesSet.IncludeAll(_dataManager.DbContext) + .FirstOrDefaultAsync(a => a.IdActivity == id); + + if (entity != null) { + + _logger.LogInformation($"Updating activity with ID {id}"); entity.Type = activity.Type; entity.Date = DateOnly.FromDateTime(activity.Date); entity.StartTime = TimeOnly.FromDateTime(activity.StartTime); entity.EndTime = TimeOnly.FromDateTime(activity.EndTime); - entity.EffortFelt = activity.Effort; + entity.EffortFelt = activity.EffortFelt; entity.Variability = activity.Variability; entity.Variance = activity.Variance; entity.StandardDeviation = activity.StandardDeviation; @@ -87,16 +118,15 @@ public partial class DbDataManager : IDataManager entity.Minimum = activity.Minimum; entity.AverageTemperature = activity.AverageTemperature; entity.HasAutoPause = activity.HasAutoPause; - }); - if (updatedActivity != null) - { + _dataManager.DbContext.SaveChanges(); + _logger.LogInformation($"Updated activity with ID {id}"); - return await Task.FromResult(updatedActivity.ToModel()); + return await Task.FromResult(entity.ToResponseDto()); } else { _logger.LogError($"Failed to update activity with ID {id}"); - return await Task.FromResult(null); + return await Task.FromResult(null); } } catch (Exception ex) diff --git a/src/Model2Entities/Extension.cs b/src/Model2Entities/Extension.cs index d7341ec..9d2bcf4 100644 --- a/src/Model2Entities/Extension.cs +++ b/src/Model2Entities/Extension.cs @@ -40,13 +40,10 @@ public static class Extensions var existingT = await context.Set().FindAsync(id); if (existingT != null && newItem != null) { - // Appliquer les mises à jour sur l'objet existant en utilisant l'action passée en paramètre updateAction(newItem, existingT); - // Marquer l'objet comme modifié dans le contexte context.Update(existingT); - - // Enregistrer les modifications dans la base de données + await context.SaveChangesAsync(); return existingT; } @@ -84,7 +81,7 @@ public static class Extensions return descending ? list.OrderByDescending(x => propertyInfo.GetValue(x)) : list.OrderBy(x => propertyInfo.GetValue(x)); } - public static IQueryable IncludeAll(this HeartTrackContext dbContext, IQueryable query) where TEntity : class + public static IQueryable IncludeAll(this IQueryable query, HeartTrackContext dbContext) where TEntity : class { var entityType = dbContext.Model.FindEntityType(typeof(TEntity)); foreach (var navigation in entityType.GetNavigations()) diff --git a/src/Model2Entities/Model2Entities.csproj b/src/Model2Entities/Model2Entities.csproj index d1f7751..24879a9 100644 --- a/src/Model2Entities/Model2Entities.csproj +++ b/src/Model2Entities/Model2Entities.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Model2Entities/UserRepository.cs b/src/Model2Entities/UserRepository.cs index 09d2cf2..264da22 100644 --- a/src/Model2Entities/UserRepository.cs +++ b/src/Model2Entities/UserRepository.cs @@ -1,9 +1,12 @@ +using Dto; +using Dto.Tiny; using Microsoft.Extensions.Logging; using Model; using Model.Repository; using Shared; using EFMappers; using Entities; +using Entities2Dto; using Microsoft.EntityFrameworkCore; namespace Model2Entities; @@ -39,6 +42,16 @@ public partial class DbDataManager } + public async Task?> GetUsersTiny(int index, int count, AthleteOrderCriteria? criteria, bool descending = false) + { + + var users = _dataManager.DbContext.AthletesSet.GetItemsWithFilterAndOrdering(b => true, + index, count, + criteria != AthleteOrderCriteria.None ? criteria : null, descending); + _logger.LogInformation($"Retrieved {users.Count()} users"); + return await Task.FromResult(users.ToTinyDtos()); + } + public async Task GetItemById(int id) { @@ -54,6 +67,43 @@ public partial class DbDataManager } + public async Task UpdateUser(int old, UserTinyDto user) + { + _logger.LogInformation($"UpdateUser with id {old}", old); + var originalEntity = _dataManager.DbContext.AthletesSet.Find(old); + if (originalEntity == null) + { + _logger.LogWarning($"No user found with ID {old}"); + return await Task.FromResult(null); + } + var originalEntry = _dataManager.DbContext.Entry(originalEntity); + var values = typeof(AthleteEntity).GetProperties().Where(ppty => ppty.Name != "IdAthlete") + .ToDictionary(ppty => ppty.Name, ppty => ppty.GetValue(user.ToEntity())); + originalEntry.CurrentValues.SetValues(values); + _dataManager.DbContext.AthletesSet.Attach(originalEntity); + _dataManager.DbContext.Entry(originalEntity).State = EntityState.Modified; + _dataManager.DbContext.SaveChanges(); + var updatedUser = originalEntity.ToTinyDto(); + if (updatedUser != null) + _logger.LogInformation($"Updated user with ID {old}"); + else + _logger.LogWarning($"No user found with ID {old}"); + return await Task.FromResult(updatedUser); + } + + public async Task GetUserById(int id) + { + _logger.LogInformation($"GetTinyItemById with id {id}", id); + var userEntity = await _dataManager.DbContext.AthletesSet.IncludeStandardProperties().Include(a => a.Followers).Include(a => a.Followings) + .SingleOrDefaultAsync(a => a.IdAthlete == id); + var user = userEntity != null ? userEntity.ToResponseDto() : null; + if (user != null) + _logger.LogInformation($"Retrieved user with ID {id}"); + else + _logger.LogWarning($"No user found with ID {id}"); + return user; + } + public async Task UpdateItem(int oldItem, User newItem) { _logger.LogInformation($"UpdateItem with id {oldItem}", oldItem); @@ -107,7 +157,6 @@ public partial class DbDataManager public async Task GetNbItems() { - _logger.LogInformation("GetNbItems"); var nbItems = await _dataManager.DbContext.AthletesSet.CountAsync(); _logger.LogInformation($"Retrieved {nbItems} users"); @@ -142,85 +191,136 @@ public partial class DbDataManager return await Task.FromResult(coaches); } + - public async Task AddFriend(User user, User friend) + public async Task AddFollowing(int fromUser, int toUser) { - _logger.LogInformation($"Attempting to add friend: User {user.Id} adding Friend {friend.Id}"); - var userEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == user.Id); - var friendEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == friend.Id); - if (userEntity == null || friendEntity == null) + _logger.LogInformation($"Attempting to add following: User {fromUser} adding Following {toUser}"); + + var userEntity = _dataManager.DbContext.AthletesSet + .Include(a => a.Followings) + .FirstOrDefault(a => a.IdAthlete == fromUser); + + if (userEntity == null) { - _logger.LogWarning($"User or friend not found: User {user.Id}, Friend {friend.Id}"); - return false; + _logger.LogWarning($"User not found: User {fromUser}"); + throw new FriendShipException("User with id " + fromUser + " not found"); } - if (userEntity.Followings.All(f => f.FollowingId != friend.Id)) + if (userEntity.Followings.Any(f => f.FollowingId == toUser)) { - userEntity.Followings.Add(new FriendshipEntity - { FollowingId = friend.Id, FollowerId = user.Id, StartDate = DateTime.Now }); - await _dataManager.DbContext.SaveChangesAsync(); - _logger.LogInformation($"Successfully added friend: User {user.Id} added Friend {friend.Id}"); - return true; + _logger.LogInformation($"Following already exists: User {fromUser} and Following {toUser}"); + throw new FriendShipException("Following already exists"); } + await _dataManager.DbContext.SaveChangesAsync(); - _logger.LogInformation($"Friendship already exists: User {user.Id} and Friend {friend.Id}"); - return false; + userEntity.Followings.Add(new FriendshipEntity + { + FollowingId = toUser, + FollowerId = fromUser, + StartDate = DateTime.Now + }); + + await _dataManager.DbContext.SaveChangesAsync(); + + _logger.LogInformation($"Successfully following: from User {fromUser} to Following {toUser}"); + return true; } + + public async Task RemoveFollowing(int fromUser, int toUser){ + _logger.LogInformation($"Attempting to remove following: User {fromUser} removing Following {toUser}"); - public async Task RemoveFriend(User user, User friend) - { - _logger.LogInformation($"Attempting to remove friend: User {user.Id} removing Friend {friend.Id}"); - var userEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == user.Id); - var friendEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == friend.Id); - if (userEntity == null || friendEntity == null) + var userEntity = _dataManager.DbContext.AthletesSet + .Include(a => a.Followings) + .FirstOrDefault(a => a.IdAthlete == fromUser); + + if (userEntity == null) { - _logger.LogWarning($"User or friend not found: User {user.Id}, Friend {friend.Id}"); - return false; + _logger.LogWarning($"User not found: User {fromUser}"); + throw new FriendShipException("User with id " + fromUser + " not found"); } - var friendship = userEntity.Followings.FirstOrDefault(f => f.FollowingId == friend.Id); - if (friendship != null) + var friendship = userEntity.Followings.FirstOrDefault(f => f.FollowingId == toUser); + if (friendship == null) { - userEntity.Followings.Remove(friendship); - await _dataManager.DbContext.SaveChangesAsync(); - _logger.LogInformation($"Successfully removed friend: User {user.Id} removed Friend {friend.Id}"); - return true; + _logger.LogInformation($"Following not found: User {fromUser} and Following {toUser}"); + throw new FriendShipException("Following not found"); } + await _dataManager.DbContext.SaveChangesAsync(); - _logger.LogInformation($"Friendship does not exist: User {user.Id} and Friend {friend.Id}"); - return false; - } + userEntity.Followings.Remove(friendship); - public Task> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, + await _dataManager.DbContext.SaveChangesAsync(); + + _logger.LogInformation($"Successfully removed following: from User {fromUser} to Following {toUser}"); + return await Task.FromResult(true); + } + public async Task?> GetFriends(int userId, int index, int count, AthleteOrderCriteria? criteria, bool descending = false) { try { - _logger.LogInformation($"GetFriends with index {index} and count {count}", index, count); - _logger.LogInformation($"GetFriends with criteria {criteria} and descending {descending}", criteria, - descending); - var friends = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().Include(a => a.Followers).Include(a => a.Followings) - .GetItemsWithFilterAndOrdering(a => a.Followers.Any(f => f.FollowingId == user.Id), index, count, - criteria, descending).ToModels(); - _logger.LogInformation($"Retrieved {friends.Count()} friends"); - return Task.FromResult(friends); + _logger.LogInformation($"GetFriends called with index {index}, count {count}, criteria {criteria}, and descending {descending}"); + + var athlete = await _dataManager.DbContext.AthletesSet + .Include(a => a.Followers).ThenInclude(f => f.Follower) + .Include(a => a.Followings).ThenInclude(f => f.Following) + .FirstOrDefaultAsync(a => a.IdAthlete == userId); // Use async version for better performance + + if (athlete == null) + { + _logger.LogError("Athlete with id {id} not found", userId); + throw new ModelNotFoundException($"Athlete with id {userId} not found"); + } + + var friendsDtos = athlete.Followings + .Where(f => athlete.Followers.Any(ff => ff.FollowerId == f.FollowingId)) + .Select(f => f.Following).GetItemsWithFilterAndOrdering(a => true, index, count, + criteria != AthleteOrderCriteria.None ? criteria : null, descending).ToTinyDtos(); + + var userTinyDtos = friendsDtos.ToArray(); + _logger.LogInformation($"Retrieved {userTinyDtos.Count()} friends for user {userId}"); + + return userTinyDtos; } catch (Exception ex) { _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); - return Task.FromResult>(new List()); + return null; } } - public Task GetNbFriends(User user) + public async Task GetNbFriends(int userId) { - - _logger.LogInformation($"GetNbFriends with user {user}", user); - var nbFriends = _dataManager.DbContext.AthletesSet - .GetItemsWithFilterAndOrdering(a => a.IdAthlete == user.Id, 0, int.MaxValue, - AthleteOrderCriteria.None, false).First().Followings.Count(); - _logger.LogInformation($"Retrieved {nbFriends} friends"); - return Task.FromResult(nbFriends); + try + { + _logger.LogInformation($"GetNbFriends called for user {userId}"); + + var athlete = await _dataManager.DbContext.AthletesSet + .Include(a => a.Followers).ThenInclude(f => f.Follower) + .Include(a => a.Followings).ThenInclude(f => f.Following) + .FirstOrDefaultAsync(a => a.IdAthlete == userId); + + if (athlete == null) + { + _logger.LogError("Athlete with id {id} not found", userId); + throw new ModelNotFoundException($"Athlete with id {userId} not found"); + } + + // Count the number of mutual friendships + var nbFriends = athlete.Followings + .Count(f => athlete.Followers.Any(ff => ff.FollowerId == f.FollowingId)); + + _logger.LogInformation($"User {userId} has {nbFriends} friends"); + + return nbFriends; + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while counting friends for user {UserId}", userId); + throw; // Consider handling the exception outside of this method or logging it accordingly. + } } + } } \ No newline at end of file diff --git a/src/Shared/AthleteOrderCriteria.cs b/src/Shared/AthleteOrderCriteria.cs index 4bc54f0..aad08e4 100644 --- a/src/Shared/AthleteOrderCriteria.cs +++ b/src/Shared/AthleteOrderCriteria.cs @@ -15,31 +15,3 @@ } } - - -/*public AthleteOrderCriteria MapToAthleteOrderCriteria(string orderingPropertyName) - { - switch (orderingPropertyName) - { - case nameof(User.Username): - return AthleteOrderCriteria.ByUsername; - case nameof(User.FirstName): - return AthleteOrderCriteria.ByFirstName; - case nameof(User.LastName): - return AthleteOrderCriteria.ByLastName; - case nameof(User.Sexe): - return AthleteOrderCriteria.BySexe; - case nameof(User.Length): - return AthleteOrderCriteria.ByLength; - case nameof(User.Weight): - return AthleteOrderCriteria.ByWeight; - case nameof(User.DateOfBirth): - return AthleteOrderCriteria.ByDateOfBirth; - case nameof(User.Email): - return AthleteOrderCriteria.ByEmail; - case nameof(User.IsCoach): - return AthleteOrderCriteria.ByIsCoach; - default: - return AthleteOrderCriteria.None; - } - }*/ \ No newline at end of file diff --git a/src/Shared/Extension.cs b/src/Shared/Extension.cs index d86ba4d..35a832c 100644 --- a/src/Shared/Extension.cs +++ b/src/Shared/Extension.cs @@ -2,25 +2,25 @@ namespace Shared; public static class Extensions { - public static U ToU(this T t, GenericMapper mapper, Func func,Action? action = null) where U :class where T :class + public static U ToU(this T t, GenericMapper mapper, Func func,Action? action = null,bool useMapper = true) where U :class where T :class { var res = mapper.GetU(t); if (res != null) return res; U u = func(t); - mapper.Add(t, u); + if(useMapper) mapper.Add(t, u); if(action != null) action(t, u); return u; } // , Action action - public static T ToT(this U u, GenericMapper mapper, Func func,Action? action = null) where U :class where T :class + public static T ToT(this U u, GenericMapper mapper, Func func,Action? action = null,bool useMapper = true) where U :class where T :class { var result = mapper.GetT(u); if(result != null) return result; T t = func(u); - mapper.Add(t, u); + if(useMapper) mapper.Add(t, u); if(action != null) action(u, t); return t; diff --git a/src/Shared/ModelException.cs b/src/Shared/ModelException.cs new file mode 100644 index 0000000..4b074f0 --- /dev/null +++ b/src/Shared/ModelException.cs @@ -0,0 +1,15 @@ +namespace Shared; + +public class FriendShipException : ModelNotFoundException +{ + public FriendShipException(string message) : base(message) + { + } +} + +public class ModelNotFoundException : Exception +{ + public ModelNotFoundException(string message) : base(message) + { + } +} diff --git a/src/StubAPI/ActivityService.cs b/src/StubAPI/ActivityService.cs index fe08608..330a3f1 100644 --- a/src/StubAPI/ActivityService.cs +++ b/src/StubAPI/ActivityService.cs @@ -1,3 +1,5 @@ +using Dto; +using Dto.Tiny; using Model; using Model.Repository; using Shared; @@ -6,17 +8,17 @@ namespace StubAPI; public class ActivityService: IActivityRepository { - private List _activities = new List( - new Activity[] + private List _activities = new List( + new ActivityTinyDto[] { - new Activity + new ActivityTinyDto { Id = 1, Type = "Running", Date = new DateTime(2021, 10, 10), StartTime = new DateTime(2021, 10, 10, 10, 0, 0), EndTime = new DateTime(2021, 10, 10, 11, 0, 0), - Effort = 3, + EffortFelt = 3, Variability = 0.5f, Variance = 0.5f, StandardDeviation = 0.5f, @@ -25,33 +27,41 @@ public class ActivityService: IActivityRepository Minimum = 0, AverageTemperature = 20.0f, HasAutoPause = false, - Athlete = new User - { - Id = 3, Username = "Athlete3", ProfilePicture = "https://plus.unsplash.com/premium_photo-1705091981693-6006f8a20479?q=80&w=1974&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", FirstName = "First3", LastName = "Last3", - Sexe = "M", Lenght = 190, Weight = 80, DateOfBirth = new DateTime(1994, 3, 3), Email = "ath@ex.fr", - Role = new Athlete() - } }, } ); - public async Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false) - => await Task.FromResult(_activities.GetItemsWithFilterAndOrdering(c=>true,index, count,criteria != ActivityOrderCriteria.None ? criteria: null , descending)); + public async Task?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false) + => await Task.FromResult(_activities.GetItemsWithFilterAndOrdering(a => true, index, count, criteria, descending)); public Task GetActivityByIdAsync(int id) { - return Task.FromResult(_activities.FirstOrDefault(s => s.Id == id)); + throw new NotImplementedException(); + // return Task.FromResult(_activities.FirstOrDefault(s => s.Id == id)?.ToModel()); } public Task AddActivity(Activity activity) - => _activities.AddItem(activity); - + => throw new NotImplementedException(); + + + public async Task AddActivity(NewActivityDto activity) + { + throw new NotImplementedException(); + } + + public async Task UpdateActivity(int id, ActivityTinyDto activity) + { + throw new NotImplementedException(); + } + public async Task UpdateActivity(int id, Activity activity) { - var oldActivity = _activities.FirstOrDefault(s => s.Id == id); + throw new NotImplementedException(); + + /*var oldActivity = _activities.FirstOrDefault(s => s.Id == id); if (oldActivity == null) return null; - return await _activities.UpdateItem(oldActivity, activity); + return await _activities.UpdateItem(oldActivity, activity);*/ } public Task DeleteActivity(int id) @@ -66,13 +76,16 @@ public class ActivityService: IActivityRepository public async Task?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria criteria, bool descending = false) { - var activities = _activities.GetItemsWithFilterAndOrdering(a => a.Athlete.Id == userId, index, count, + throw new NotImplementedException(); + + /* var activities = _activities.GetItemsWithFilterAndOrdering(a => a.Athlete.Id == userId, index, count, criteria != ActivityOrderCriteria.None ? criteria : null, descending); - return await Task.FromResult(activities); + return await Task.FromResult(activities);*/ } public Task GetNbActivitiesByUser(int userId) { - return Task.FromResult(_activities.Count(a => a.Athlete.Id == userId)); + throw new NotImplementedException(); + // return Task.FromResult(_activities.Count(a => a.Athlete.Id == userId)); } } \ No newline at end of file diff --git a/src/StubAPI/AthleteService.cs b/src/StubAPI/AthleteService.cs index 4d8bf29..d51a7c7 100644 --- a/src/StubAPI/AthleteService.cs +++ b/src/StubAPI/AthleteService.cs @@ -1,4 +1,6 @@ -using Model; +using Dto; +using Dto.Tiny; +using Model; using Model.Repository; using Shared; @@ -34,6 +36,26 @@ public class UserService : IUserRepository public async Task> GetUsers(int index, int count, AthleteOrderCriteria? orderingProperty = null, bool descending = false) => athletes.GetItemsWithFilterAndOrdering(c=>true,index, count,orderingProperty != AthleteOrderCriteria.None ? orderingProperty: null , descending); + public async Task?> GetUsersTiny(int index, int count, AthleteOrderCriteria? criteria, bool descending = false) + { + throw new NotImplementedException(); + } + + public async Task AddFollowing(int fromUser, int toUser) + { + throw new NotImplementedException(); + } + + public async Task RemoveFollowing(int fromUser, int toUser) + { + throw new NotImplementedException(); + } + + public async Task?> GetFriends(int user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false) + { + throw new NotImplementedException(); + } + public async Task AddFriend(User user, User friend) { if (user == null || friend == null) @@ -71,9 +93,19 @@ public class UserService : IUserRepository public async Task?>? GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false) =>await Task.FromResult(athletes.FirstOrDefault(s => s.Id == user.Id)?.Users.GetItemsWithFilterAndOrdering(c=>true,index, count,criteria, descending)); - public Task GetNbFriends(User user) + public Task GetNbFriends(int user) + { + return Task.FromResult(athletes.FirstOrDefault(s => s.Id == user)?.Users.Count ?? 0); + } + + public async Task UpdateUser(int old, UserTinyDto user) + { + throw new NotImplementedException(); + } + + public async Task GetUserById(int id) { - return Task.FromResult(athletes.FirstOrDefault(s => s.Id == user.Id)?.Users.Count ?? 0); + throw new NotImplementedException(); } public async Task> GetItems(int index, int count, string? orderingProperty = null, diff --git a/src/StubAPI/StubAPI.csproj b/src/StubAPI/StubAPI.csproj index eea9fb7..85860b7 100644 --- a/src/StubAPI/StubAPI.csproj +++ b/src/StubAPI/StubAPI.csproj @@ -7,6 +7,7 @@ + diff --git a/src/StubbedContextLib/AthleteStubbedContext.cs b/src/StubbedContextLib/AthleteStubbedContext.cs index f45140f..3b69133 100644 --- a/src/StubbedContextLib/AthleteStubbedContext.cs +++ b/src/StubbedContextLib/AthleteStubbedContext.cs @@ -43,7 +43,7 @@ namespace StubbedContextLib modelBuilder.Entity().HasData( new AthleteEntity { IdAthlete = 1, Username = "Doe",ProfilPicture = picture2, ImageId = Guid.Parse("{8d121cdc-6787-4738-8edd-9e026ac16b65}") ,LastName = "Doe", FirstName = "John", Email = "john.doe@example.com", Password = "password123", Sexe = "M", Length = 1.80, Weight = 75, DateOfBirth = new DateOnly(1990, 01, 01), IsCoach = true , DataSourceId = 1}, - new AthleteEntity { IdAthlete = 2, Username = "Smith",ProfilPicture = picture2,ImageId = Guid.Parse("{8d121cdc-6787-4738-8edd-9e026ac16b65}") ,LastName = "Smith", FirstName = "Jane", Email = "jane.smith@exemple.com", Password = "secure456", Sexe = "F", Length = 1.65, Weight = 60, DateOfBirth = new DateOnly(1995, 01, 01), IsCoach = false, DataSourceId = 1 }, + new AthleteEntity { IdAthlete = 2, Username = "Smith",ProfilPicture = picture2,LastName = "Smith", FirstName = "Jane", Email = "jane.smith@exemple.com", Password = "secure456", Sexe = "F", Length = 1.65, Weight = 60, DateOfBirth = new DateOnly(1995, 01, 01), IsCoach = false, DataSourceId = 1 }, new AthleteEntity { IdAthlete = 3, Username = "Martin",ProfilPicture = picture2,ImageId = Guid.Parse("{8d121cdc-6787-4738-8edd-9e026ac16b65}") ,LastName = "Martin", FirstName = "Paul", Email = "paul.martin@example.com", Password = "super789", Sexe = "M", Length = 1.75, Weight = 68, DateOfBirth = new DateOnly(1992, 01, 01), IsCoach = true, DataSourceId = 1}, new AthleteEntity { IdAthlete = 4, Username = "Brown",ProfilPicture = picture2, ImageId = Guid.Parse("{8d121cdc-6787-4738-8edd-9e026ac16b65}"),LastName = "Brown", FirstName = "Anna", Email = "anna.brown@example.com", Password = "test000", Sexe = "F", Length = 1.70, Weight = 58, DateOfBirth = new DateOnly(1993, 01, 01), IsCoach = false, DataSourceId = 2 }, new AthleteEntity { IdAthlete = 5, Username = "Lee", ProfilPicture = picture2, ImageId = Guid.Parse("{8d121cdc-6787-4738-8edd-9e026ac16b65}"),LastName = "Lee", FirstName = "Bruce", Email = "bruce.lee@example.com", Password = "hello321", Sexe = "M", Length = 2.0, Weight = 90, DateOfBirth = new DateOnly(1991, 01, 01), IsCoach = false, DataSourceId = 3 } diff --git a/src/StubbedContextLib/FriendshipStubbedContext.cs b/src/StubbedContextLib/FriendshipStubbedContext.cs index 70eb76f..5631ca1 100644 --- a/src/StubbedContextLib/FriendshipStubbedContext.cs +++ b/src/StubbedContextLib/FriendshipStubbedContext.cs @@ -39,10 +39,7 @@ namespace StubbedContextLib modelBuilder.Entity().HasData( new FriendshipEntity { FollowerId = 1, FollowingId = 2 }, new FriendshipEntity { FollowerId = 1, FollowingId = 3 }, - new FriendshipEntity { FollowerId = 1, FollowingId = 4 }, - new FriendshipEntity { FollowerId = 1, FollowingId = 5 }, - new FriendshipEntity { FollowerId = 2, FollowingId = 1 }, - new FriendshipEntity { FollowerId = 2, FollowingId = 3 } + new FriendshipEntity { FollowerId = 3, FollowingId = 1 } ); } } diff --git a/src/Tests/ConsoleTestEFMapper/Program.cs b/src/Tests/ConsoleTestEFMapper/Program.cs index bc71893..5b3ca01 100644 --- a/src/Tests/ConsoleTestEFMapper/Program.cs +++ b/src/Tests/ConsoleTestEFMapper/Program.cs @@ -10,6 +10,7 @@ using static Model2Entities.DbDataManager; namespace Model2Entities { + /* static class Program { static async Task Main(string[] args) @@ -114,5 +115,5 @@ namespace Model2Entities } static void UsersTest() {} - } + }*/ } \ No newline at end of file diff --git a/src/Tests/TestsAPI/UnitTestApi/Controllers/UsersControllerTest.cs b/src/Tests/TestsAPI/UnitTestApi/Controllers/UsersControllerTest.cs index 0a5eb52..bff2e2d 100644 --- a/src/Tests/TestsAPI/UnitTestApi/Controllers/UsersControllerTest.cs +++ b/src/Tests/TestsAPI/UnitTestApi/Controllers/UsersControllerTest.cs @@ -74,14 +74,6 @@ public class UsersControllerTest _usersController = new UsersController(new NullLogger(), _dataManagerMock.Object); } -/* - [TestInitialize] - public void SetUp() - { - _dataManager = new StubData(); - _usersController = new UsersController(new NullLogger(), _dataManager); - }*/ - [TestMethod] public async Task Get_ReturnsPageResponse_WhenRequestIsValid() @@ -103,7 +95,7 @@ public class UsersControllerTest Assert.IsNotNull(okResult); Assert.IsInstanceOfType(okResult.Value, typeof(PageResponse)); var pageResponse = okResult.Value as PageResponse; - Assert.IsNotNull(pageResponse); + Assert.IsNotNull(pageResponse); Assert.AreEqual(3, pageResponse.Items.Count()); Assert.AreEqual(3, pageResponse.Total); Assert.AreEqual(0, pageResponse.Index); diff --git a/src/Tests/UnitTestsEntities/FriendshipEntityTests.cs b/src/Tests/UnitTestsEntities/FriendshipEntityTests.cs index 10cfc00..2a0db78 100644 --- a/src/Tests/UnitTestsEntities/FriendshipEntityTests.cs +++ b/src/Tests/UnitTestsEntities/FriendshipEntityTests.cs @@ -63,7 +63,7 @@ public class FriendshipEntityTests (DatabaseFixture fixture) : IClassFixture a.Followers).Include(a => a.Followings).FirstOrDefault(a => a.Username == "follower_user1").Followers.FirstOrDefault(f => f.FollowerId == follower.IdAthlete && f.FollowingId == following.IdAthlete); + var savedFriendship = context.AthletesSet.Include(a => a.Followers).Include(a => a.Followings).FirstOrDefault(a => a.Username == "follower_user1").Followings.FirstOrDefault(f => f.FollowerId == follower.IdAthlete && f.FollowingId == following.IdAthlete); Assert.NotNull(savedFriendship); if (savedFriendship != null)