finist but not clean
continuous-integration/drone/push Build is failing Details

pull/10/head
David D'ALMEIDA 1 year ago
parent 13c2959095
commit 1db4be9e0d

@ -1,4 +1,6 @@
using Dto; using Dto;
using Dto.Tiny;
using Entities;
using Model; using Model;
using Shared; using Shared;
@ -7,6 +9,7 @@ namespace APIMappers;
public static class ActivityMapper public static class ActivityMapper
{ {
private static GenericMapper<Activity, ActivityDto> _mapper = new(); private static GenericMapper<Activity, ActivityDto> _mapper = new();
private static GenericMapper<ActivityTinyDto, ActivityEntity> _mapperTiny = new ();
public static Activity ToModel(this ActivityDto activityDto, User user) public static Activity ToModel(this ActivityDto activityDto, User user)
{ {
@ -72,6 +75,28 @@ public static class ActivityMapper
return model.ToU(_mapper, create, link); return model.ToU(_mapper, create, link);
} }
public static ActivityEntity ToEntity(this ActivityTinyDto tinyDto)
{
Func<ActivityTinyDto, ActivityEntity> 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<Activity> ToModels(this IEnumerable<ActivityDto> dtos, User user) public static IEnumerable<Activity> ToModels(this IEnumerable<ActivityDto> dtos, User user)
=> dtos.Select(dto => dto.ToModel(user)); => dtos.Select(dto => dto.ToModel(user));

@ -18,7 +18,6 @@ public static class HeartRateMapper
public static HeartRateDto ToDto(this HeartRate model)//Activity activity public static HeartRateDto ToDto(this HeartRate model)//Activity activity
{ {
// [TODO] [Dave] fix this should be activity but it boucle indefinitly
var activity = new DateTime(); var activity = new DateTime();
Func<HeartRate, HeartRateDto> create = heartRate => Func<HeartRate, HeartRateDto> create = heartRate =>
new HeartRateDto new HeartRateDto

@ -168,16 +168,16 @@ namespace DbContextLib
.ValueGeneratedOnAdd(); .ValueGeneratedOnAdd();
modelBuilder.Entity<FriendshipEntity>() modelBuilder.Entity<FriendshipEntity>()
.HasKey(f => new { f.FollowingId, f.FollowerId }); .HasKey(f => new { f.FollowerId, f.FollowingId });
modelBuilder.Entity<FriendshipEntity>() modelBuilder.Entity<FriendshipEntity>()
.HasOne(fing => fing.Following) .HasOne(fing => fing.Following)
.WithMany(fings => fings.Followings) .WithMany(fings => fings.Followers)
.HasForeignKey(fing => fing.FollowingId); .HasForeignKey(fing => fing.FollowingId);
modelBuilder.Entity<FriendshipEntity>() modelBuilder.Entity<FriendshipEntity>()
.HasOne(fer => fer.Follower) .HasOne(fer => fer.Follower)
.WithMany(fers => fers.Followers) .WithMany(fers => fers.Followings)
.HasForeignKey(fing => fing.FollowerId); .HasForeignKey(fing => fing.FollowerId);
// ! // !

@ -12,11 +12,9 @@ public class DataSourceDto
public float Precision { get; set; } 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] [JsonIgnore]
public IEnumerable<UserDto>? Athletes { get; set; } public IEnumerable<UserDto>? Athletes { get; set; }
// [TODO] [Dave] Add a property to store the athletes and the activities so maybe adapt to have a tiny DTO
[JsonIgnore] [JsonIgnore]
public IEnumerable<ActivityDto>? Activities { get; set; } public IEnumerable<ActivityDto>? Activities { get; set; }
} }

@ -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; }
}

@ -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; }
}

@ -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; }
}

@ -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; }
}

@ -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; }
}

@ -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; }
}

@ -0,0 +1,7 @@
namespace Dto.Tiny;
public class FriendshipDto
{
public int FollowedId { get; set; }
public int FollowerId { get; set; }
}

@ -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; }
}

@ -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; }
}

@ -62,17 +62,6 @@ public static class UserMappeur
entity.Activities = user.Activities.ToEntities().ToList(); entity.Activities = user.Activities.ToEntities().ToList();
entity.IsCoach = user.Role is Coach; entity.IsCoach = user.Role is Coach;
entity.Image = user.Image.ToEntity(); 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); return model.ToU(_mapper, create, link);

@ -105,6 +105,6 @@ namespace Entities
public int AthleteId { get; set; } public int AthleteId { get; set; }
public AthleteEntity Athlete { get; set; } = null!; public AthleteEntity Athlete { get; set; }
} }
} }

@ -87,7 +87,6 @@ namespace Entities
/// </summary> /// </summary>
public bool IsCoach { get; set; } public bool IsCoach { get; set; }
// [TODO] [DAVE] Check Image
public string? ProfilPicture { get; set; } public string? ProfilPicture { get; set; }
public LargeImageEntity? Image { get; set; } public LargeImageEntity? Image { get; set; }

@ -0,0 +1,102 @@
using Dto;
using Dto.Tiny;
using Entities;
using Shared;
namespace Entities2Dto;
public static class ActivityMapper
{
private static GenericMapper<ActivityTinyDto, ActivityEntity> _mapper = new ();
private static GenericMapper<ResponseActivityDto, ActivityEntity> _mapperFull = new ();
public static void Reset()
{
_mapper.Reset();
_mapperFull.Reset();
}
public static ActivityTinyDto ToDto(this ActivityEntity entity)
{
Console.WriteLine("dfghf");
Func<ActivityEntity, ActivityTinyDto> 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<ActivityTinyDto, ActivityEntity> 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<ActivityEntity, ResponseActivityDto> 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<ActivityEntity, ResponseActivityDto> 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<ActivityTinyDto> ToTinyDtos(this IEnumerable<ActivityEntity> entities)
=> entities.Select(a => a.ToDto());
public static IEnumerable<ActivityEntity> ToEntities(this IEnumerable<ActivityTinyDto> dtos)
=> dtos.Select(a => a.ToEntity());
}

@ -0,0 +1,70 @@
using Dto;
using Dto.Tiny;
using Entities;
using Shared;
namespace Entities2Dto;
public static class DataSourceMapper
{
private static GenericMapper<DataSourceTinyDto, DataSourceEntity> _mapper = new();
private static GenericMapper<ResponseDataSourceDto, DataSourceEntity> _mapperFull = new();
public static void Reset()
{
_mapper.Reset();
_mapperFull.Reset();
}
public static DataSourceTinyDto ToTinyDto(this DataSourceEntity entity)
{
Func<DataSourceEntity, DataSourceTinyDto> 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<DataSourceTinyDto, DataSourceEntity> 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<DataSourceEntity, ResponseDataSourceDto> create = dataSourceEntity => new ResponseDataSourceDto
{
Id = dataSourceEntity.IdSource,
Type = dataSourceEntity.Type,
Model = dataSourceEntity.Model,
Precision = dataSourceEntity.Precision,
};
Action<DataSourceEntity, ResponseDataSourceDto> 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<DataSourceTinyDto> ToTinyDtos(this IEnumerable<DataSourceEntity> entities)
=> entities.Select(e => e.ToTinyDto());
public static IEnumerable<DataSourceEntity> ToEntities(this IEnumerable<DataSourceTinyDto> dtos)
=> dtos.Select(d => d.ToEntity());
}

@ -0,0 +1,32 @@
using Dto.Tiny;
using Entities;
using Shared;
namespace Entities2Dto;
public static class FriendshipMapper
{
private static GenericMapper<FriendshipDto, FriendshipEntity> _mapper = new();
public static void Reset()
{
_mapper.Reset();
}
public static FriendshipDto ToTinyDto(this FriendshipEntity entity)
{
Func<FriendshipEntity, FriendshipDto> create = friendshipEntity => new FriendshipDto
{
FollowedId = friendshipEntity.FollowingId,
FollowerId = friendshipEntity.FollowerId,
};
return entity.ToT(_mapper, create, null, false);
}
public static IEnumerable<FriendshipDto> ToTinyDtos(this IEnumerable<FriendshipEntity> entities)
=> entities.Select(e => e.ToTinyDto());
}

@ -0,0 +1,63 @@
using Dto.Tiny;
using Entities;
using Shared;
namespace Entities2Dto;
public static class HeartRateMapper
{
private static GenericMapper<HeartRateTinyDto, HeartRateEntity> _mapper = new();
public static void Reset()
{
_mapper.Reset();
}
public static HeartRateTinyDto ToTinyDto(this HeartRateEntity entity)
{
var activityTmp = new DateTime();
Func<HeartRateEntity, HeartRateTinyDto> 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<HeartRateTinyDto, HeartRateEntity> 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<HeartRateTinyDto> ToTinyDtos(this IEnumerable<HeartRateEntity> entities)
=> entities.Select(e => e.ToTinyDto());
public static IEnumerable<HeartRateEntity> ToEntities(this IEnumerable<HeartRateTinyDto> dtos)
=> dtos.Select(d => d.ToEntity());
}

@ -0,0 +1,32 @@
using Dto;
using Entities;
using Shared;
namespace Entities2Dto;
public static class LargeImageMapper
{
private static GenericMapper<LargeImageDto, LargeImageEntity> _mapper = new();
public static void Reset()
{
_mapper.Reset();
}
public static LargeImageDto ToDto(this LargeImageEntity entity)
{
Func<LargeImageEntity, LargeImageDto> create = largeImageEntity => new() { Base64 = largeImageEntity.Base64 };
return entity.ToT(_mapper, create, null, false);
}
public static LargeImageEntity ToEntity(this LargeImageDto dto)
{
Func<LargeImageDto, LargeImageEntity> create = largeImage => new LargeImageEntity
{
Base64 = largeImage.Base64
};
return dto.ToU(_mapper, create);
}
}

@ -0,0 +1,102 @@
using Dto;
using Dto.Tiny;
using Entities;
using Shared;
namespace Entities2Dto;
public static class UserMappeur
{
private static GenericMapper<UserTinyDto, AthleteEntity> _mapper = new();
private static GenericMapper<ResponseUserDto, AthleteEntity> _mapperFull = new();
public static void Reset()
{
_mapper.Reset();
_mapperFull.Reset();
}
public static UserTinyDto ToTinyDto(this AthleteEntity entity)
{
Func<AthleteEntity, UserTinyDto> 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<UserTinyDto, AthleteEntity> 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<AthleteEntity, ResponseUserDto> 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<AthleteEntity, ResponseUserDto> 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<UserTinyDto> ToTinyDtos(this IEnumerable<AthleteEntity> entities)
=> entities.Select(e => e.ToTinyDto());
public static IEnumerable<AthleteEntity> ToEntities(this IEnumerable<UserTinyDto> models)
=> models.Select(m => m.ToEntity());
}

@ -43,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "APIMappers", "APIMappers\AP
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestsModel", "Tests\UnitTestsModel\UnitTestsModel.csproj", "{508D380F-145C-437E-A7DF-7A17C526B2F3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestsModel", "Tests\UnitTestsModel\UnitTestsModel.csproj", "{508D380F-145C-437E-A7DF-7A17C526B2F3}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entities2Dto", "Entities2Dto\Entities2Dto.csproj", "{1B15D383-1DFA-47E8-86EC-AC631B15FBEB}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{508D380F-145C-437E-A7DF-7A17C526B2F3}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

@ -1,9 +1,9 @@
using APIMappers; using APIMappers;
using Dto; using Dto;
using Dto.Tiny;
using HeartTrackAPI.Request; using HeartTrackAPI.Request;
using HeartTrackAPI.Responce; using HeartTrackAPI.Responce;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Model;
using Shared; using Shared;
using Model.Manager; using Model.Manager;
using Model.Repository; using Model.Repository;
@ -30,7 +30,7 @@ public class ActivityController : Controller
[ProducesResponseType(typeof(PageResponse<ActivityDto>), 200)] [ProducesResponseType(typeof(PageResponse<ActivityDto>), 200)]
[ProducesResponseType(400)] [ProducesResponseType(400)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<ActionResult<PageResponse<ActivityDto>>> GetActivities([FromQuery] PageRequest pageRequest) public async Task<ActionResult<PageResponse<ActivityTinyDto>>> GetActivities([FromQuery] PageRequest pageRequest)
{ {
try try
{ {
@ -46,7 +46,9 @@ public class ActivityController : Controller
{ {
return NotFound("No activities found"); return NotFound("No activities found");
} }
var pageResponse = new PageResponse<ActivityDto>(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
var pageResponse =
new PageResponse<ActivityTinyDto>(pageRequest.Index, pageRequest.Count, totalCount, activities);
return Ok(pageResponse); return Ok(pageResponse);
} }
catch (Exception e) catch (Exception e)
@ -57,82 +59,29 @@ public class ActivityController : Controller
} }
[HttpPost] [HttpPost]
public async Task<IActionResult> PostActivity(ActivityDto activityDto) public async Task<IActionResult> PostActivity(NewActivityDto activityDto)
{ {
var user = await _userRepository.GetItemById(activityDto.AthleteId);
var user = await _userRepository.GetUserById(activityDto.AthleteId);
if (user == null) if (user == null)
{ {
_logger.LogError("Athlete with id {id} not found", activityDto.AthleteId); _logger.LogError("Athlete with id {id} not found", activityDto.AthleteId);
return NotFound($"Athlete with id {activityDto.AthleteId} not found"); return NotFound($"Athlete with id {activityDto.AthleteId} not found");
} }
var tmp = user.DataSources.FirstOrDefault(ds => ds.Id == activityDto.DataSourceId); if (activityDto.DataSourceId != null && user.DataSource.Id != activityDto.DataSourceId)
if (tmp == null)
{ {
_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"); return NotFound($"DataSource with id {activityDto.DataSourceId} not found");
} }
var activity = activityDto.ToModel(user); var result = await _activityService.AddActivity(activityDto);
var result = await _activityService.AddActivity(activity);
if (result == null) if (result == null)
{ {
return BadRequest(); return BadRequest();
} }
return CreatedAtAction(nameof(GetActivity), new { id = result.Id }, result.ToDto()); return CreatedAtAction(nameof(GetActivity), new { id = result.Id }, result);
}
/*
public async Task<IActionResult> 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}")] [HttpGet("{id}")]
public async Task<ActionResult<ActivityDto>> GetActivity(int id) public async Task<ActionResult<ActivityDto>> GetActivity(int id)
@ -158,25 +107,15 @@ public class ActivityController : Controller
} }
[HttpPut("{id}")] [HttpPut("{id}")]
public async Task<IActionResult> PutActivity(int id, ActivityDto activityDto) public async Task<IActionResult> PutActivity(int id, ActivityTinyDto activityDto)
{ {
if (id != activityDto.Id) var result = await _activityService.UpdateActivity(id, activityDto);
{
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);
if (result == null) if (result == null)
{ {
return NotFound(); return NotFound();
} }
return NoContent();
return Ok(result);
} }
/// <summary> /// <summary>

@ -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<HeartRateZone> _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<HeartRateTinyDto> heartRates)
{
var secondsInZone =
heartRates.Count(hr => hr.HeartRate >= zone.MinHeartRate && hr.HeartRate <= zone.MaxHeartRate);
return TimeSpan.FromSeconds(secondsInZone);
}
private 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();
}
}
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; }
}

@ -1,8 +1,11 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using APIMappers; using APIMappers;
using Dto; using Dto;
using Dto.Tiny;
using HeartTrackAPI.Request; using HeartTrackAPI.Request;
using HeartTrackAPI.Responce; using HeartTrackAPI.Responce;
using HeartTrackAPI.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Model.Manager; using Model.Manager;
@ -38,10 +41,10 @@ public class UsersController : Controller
/// <response code="400">La demande de pagination est invalide.</response> /// <response code="400">La demande de pagination est invalide.</response>
/// <response code="500">Erreur interne du serveur.</response> /// <response code="500">Erreur interne du serveur.</response>
[HttpGet] [HttpGet]
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)] [ProducesResponseType(typeof(PageResponse<UserTinyDto>), 200)]
[ProducesResponseType(400)] [ProducesResponseType(400)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<ActionResult<PageResponse<UserDto>>> Get([FromQuery] PageRequest request) public async Task<ActionResult<PageResponse<UserTinyDto>>> Get([FromQuery] PageRequest request)
{ {
try try
{ {
@ -54,8 +57,8 @@ public class UsersController : Controller
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), null); _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 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<UserDto>(request.Index, request.Count, totalCount, athletes!.Select(a => a.ToDto())); var pageResponse = new PageResponse<UserTinyDto>(request.Index, request.Count, totalCount, athletes);
return Ok(pageResponse); return Ok(pageResponse);
} }
catch (Exception e) catch (Exception e)
@ -74,21 +77,21 @@ public class UsersController : Controller
/// <response code="404">Aucun utilisateur trouvé pour l'identifiant spécifié.</response> /// <response code="404">Aucun utilisateur trouvé pour l'identifiant spécifié.</response>
/// <response code="500">Erreur interne du serveur.</response> /// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{id}")] [HttpGet("{id}")]
[ProducesResponseType(typeof(UserDto), 200)] [ProducesResponseType(typeof(ResponseUserDto), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<ActionResult<UserDto>> GetById([Range(0,int.MaxValue)]int id) public async Task<ActionResult<ResponseUserDto>> GetById([Range(0,int.MaxValue)]int id)
{ {
try try
{ {
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(GetById), id); _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) if (athlete == null)
{ {
_logger.LogError("Athlete with id {id} not found", id); _logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found"); return NotFound($"Athlete with id {id} not found");
} }
return Ok(athlete.ToDto()); return Ok(athlete);
} }
catch (Exception e) catch (Exception e)
{ {
@ -110,7 +113,7 @@ public class UsersController : Controller
{ {
try try
{ {
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Count), null); _logger.LogInformation("Executing {Action}", nameof(Count));
var nbUsers = await _userService.GetNbItems(); var nbUsers = await _userService.GetNbItems();
return Ok(nbUsers); return Ok(nbUsers);
} }
@ -131,27 +134,27 @@ public class UsersController : Controller
/// <response code="404">Utilisateur non trouvé.</response> /// <response code="404">Utilisateur non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response> /// <response code="500">Erreur interne du serveur.</response>
[HttpPut("{id}")] [HttpPut("{id}")]
[ProducesResponseType(typeof(UserDto), 200)] [ProducesResponseType(typeof(UserTinyDto), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<ActionResult<UserDto>> Update(int id, [FromBody] UserDto user) public async Task<ActionResult<UserTinyDto>> Update(int id, [FromBody] UserTinyDto user)
{ {
try try
{ {
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Update), user,id); _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) if (athlete == null)
{ {
_logger.LogError("Athlete with id {id} not found", id); _logger.LogError("Athlete with id {id} not found", id);
return NotFound($"Athlete with id {id} not found"); 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) if(updatedAthlete == null)
{ {
_logger.LogError("Error while updating athlete with id {id}", id); _logger.LogError("Error while updating athlete with id {id}", id);
return Problem(); return Problem();
} }
return Ok(updatedAthlete.ToDto()); return Ok(updatedAthlete);
} }
catch (Exception e) catch (Exception e)
@ -179,8 +182,7 @@ public class UsersController : Controller
{ {
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Delete), null,id); _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(Delete), null,id);
var athlete = await _userService.GetUserById(id);
var athlete = await _userService.GetItemById(id);
if (athlete == null) if (athlete == null)
{ {
_logger.LogError("Athlete with id {id} not found", id); _logger.LogError("Athlete with id {id} not found", id);
@ -211,31 +213,30 @@ public class UsersController : Controller
/// <response code="404">Utilisateur non trouvé.</response> /// <response code="404">Utilisateur non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response> /// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{id}/friends")] [HttpGet("{id}/friends")]
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)] [ProducesResponseType(typeof(PageResponse<UserTinyDto>), 200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<ActionResult<PageResponse<UserDto>>> GetFriends(int id, [FromQuery] PageRequest request) public async Task<ActionResult<PageResponse<UserTinyDto>>> GetFriends(int id, [FromQuery] PageRequest request)
{ {
try try
{ {
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(GetFriends), null,id); _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(GetFriends), null,id);
var athlete = await _userService.GetItemById(id); var totalCount = await _userService.GetNbFriends(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);
if (request.Count * request.Index >= totalCount) if (request.Count * request.Index >= totalCount)
{ {
_logger.LogError("To many object is asked the max is {totalCount} but the request is superior of ", 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); 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(); if (friends == null) return NotFound();
var pageResponse = new PageResponse<UserDto>(request.Index, request.Count, totalCount, friends.Select(a => a.ToDto())); var pageResponse = new PageResponse<UserTinyDto>(request.Index, request.Count, totalCount, friends);
return Ok(pageResponse); return Ok(pageResponse);
} }
catch(ModelNotFoundException e)
{
_logger.LogError(e, "Error while adding a friend to an athlete");
return BadRequest(e.Message);
}
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, "Error while getting the number of users"); _logger.LogError(e, "Error while getting the number of users");
@ -256,24 +257,13 @@ public class UsersController : Controller
[ProducesResponseType(200)] [ProducesResponseType(200)]
[ProducesResponseType(404)] [ProducesResponseType(404)]
[ProducesResponseType(500)] [ProducesResponseType(500)]
public async Task<IActionResult> AddFriend(int id, int friendId) public async Task<IActionResult> AddFollowing(int id, int friendId)
{ {
try try
{ {
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(AddFriend), friendId,id); _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(AddFollowing), friendId,id);
var athlete = await _userService.GetItemById(id);
if (athlete == null) var isAdded = await _userService.AddFollowing(id, friendId);
{
_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);
if(!isAdded) if(!isAdded)
{ {
_logger.LogError("Error while adding friend with id {friendId} to athlete with id {id}", friendId, id); _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(); return Ok();
} }
catch(FriendShipException e)
{
_logger.LogError(e, "Error while adding a friend to an athlete");
return BadRequest(e.Message);
}
catch (Exception e) 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(); return Problem();
} }
} }
@ -307,19 +302,8 @@ public class UsersController : Controller
try try
{ {
_logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(RemoveFriend), friendId,id); _logger.LogInformation("Executing {Action} with parameters: {Parameters} for {Id}", nameof(RemoveFriend), friendId,id);
var athlete = await _userService.GetItemById(id);
if (athlete == null) var isRemoved = await _userService.RemoveFollowing(id, friendId);
{
_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);
if(!isRemoved) if(!isRemoved)
{ {
_logger.LogError("Error while removing friend with id {friendId} to athlete with id {id}", friendId, id); _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(); return Ok();
} }
catch (Exception e) catch(FriendShipException e)
{
_logger.LogError(e, "Error while getting the number of users");
return Problem();
}
}
/// <summary>
/// Obtient la liste des athlètes d'un coach spécifique.
/// </summary>
/// <param name="coachId">L'identifiant du coach.</param>
/// <param name="request">Les critères de pagination et de tri.</param>
/// <returns>La liste paginée des athlètes.</returns>
/// <response code="200">Retourne la liste paginée des athlètes du coach.</response>
/// <response code="404">Coach non trouvé.</response>
/// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{coachId}/athletes")]
[ProducesResponseType(typeof(PageResponse<UserDto>), 200)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public async Task<ActionResult<PageResponse<UserDto>>> GetAthletes(int coachId, [FromQuery] PageRequest request)
{
try
{
_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); _logger.LogError(e, "Error while removing a friend to an athlete");
return BadRequest("To many object is asked the max is : " + totalCount); return BadRequest(e.Message);
}
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<UserDto>(request.Index, request.Count, totalCount, athletes.Select(a => a.ToDto()));
return Ok(pageResponse);
} }
catch (Exception e) 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(); return Problem();
} }
} }
/*
/// <summary> /// <summary>
/// Obtient la liste des activités d'un utilisateur spécifique. /// Obtient la liste des activités d'un utilisateur spécifique.
/// </summary> /// </summary>
@ -387,7 +335,7 @@ public class UsersController : Controller
/// <response code="500">Erreur interne du serveur.</response> /// <response code="500">Erreur interne du serveur.</response>
[HttpGet("{userId}/activities")] [HttpGet("{userId}/activities")]
// should be tiny DTOActivity returned with only the necessary information (will be used in the list of activities of a user) // should be tiny DTOActivity returned with only the necessary information (will be used in the list of activities of a user)
public async Task<ActionResult<PageResponse<ActivityDto>>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest) public async Task<ActionResult<PageResponse<ActivityTinyDto>>> GetActivitiesByUser(int userId, [FromQuery] PageRequest pageRequest)
{ {
try try
{ {
@ -403,7 +351,7 @@ public class UsersController : Controller
{ {
return NotFound("No activities found"); return NotFound("No activities found");
} }
var pageResponse = new PageResponse<ActivityDto>(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto())); var pageResponse = new PageResponse<ActivityTinyDto>(pageRequest.Index, pageRequest.Count, totalCount, activities.Select(a => a.ToDto()));
return Ok(pageResponse); return Ok(pageResponse);
} }
catch (Exception e) catch (Exception e)
@ -411,7 +359,7 @@ public class UsersController : Controller
_logger.LogError(e, "Error while getting all activities"); _logger.LogError(e, "Error while getting all activities");
return Problem(); return Problem();
} }
} }*/
/// <summary> /// <summary>
/// Déconnecte l'utilisateur actuel. /// Déconnecte l'utilisateur actuel.

@ -1,13 +1,17 @@
using Dto;
using Dto.Tiny;
using Shared; using Shared;
namespace Model.Repository; namespace Model.Repository;
public interface IActivityRepository public interface IActivityRepository
{ {
public Task<IEnumerable<Activity>?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false); public Task<IEnumerable<ActivityTinyDto>?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false);
public Task<Activity?> GetActivityByIdAsync(int id); public Task<Activity?> GetActivityByIdAsync(int id);
public Task<Activity?> AddActivity(Activity activity); public Task<Activity?> AddActivity(Activity activity);
public Task<Activity?> UpdateActivity(int id, Activity activity); public Task<ResponseActivityDto?> AddActivity(NewActivityDto activity);
public Task<ResponseActivityDto?> UpdateActivity(int id, ActivityTinyDto activity);
public Task<bool> DeleteActivity(int id); public Task<bool> DeleteActivity(int id);
public Task<int> GetNbItems(); public Task<int> GetNbItems();
public Task<IEnumerable<Activity>?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria orderCriteria, bool descending= false); public Task<IEnumerable<Activity>?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria orderCriteria, bool descending= false);

@ -1,14 +1,22 @@
using Shared; using Dto;
using Dto.Tiny;
using Shared;
namespace Model.Repository; namespace Model.Repository;
public interface IUserRepository : IGenericRepository<User> public interface IUserRepository : IGenericRepository<User> // Make it generic
{ {
// [TODO] [Dave] DELETE it use just in the test
public Task<IEnumerable<User>?> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false); public Task<IEnumerable<User>?> GetUsers(int index, int count, AthleteOrderCriteria? criteria , bool descending = false);
public Task<bool> AddFriend(User user, User friend); public Task<IEnumerable<UserTinyDto>?> GetUsersTiny(int index, int count, AthleteOrderCriteria? criteria , bool descending = false);
public Task<bool> RemoveFriend(User user, User friend); public Task<bool> AddFollowing(int fromUser, int toUser);
public Task<IEnumerable<User>?> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false); public Task<bool> RemoveFollowing(int fromUser, int toUser);
public Task<int> GetNbFriends(User user);
// DELETE
public Task<IEnumerable<UserTinyDto>?> GetFriends(int user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false);
public Task<int> GetNbFriends(int user);
public Task<UserTinyDto?> UpdateUser(int old,UserTinyDto user);
public Task<ResponseUserDto> GetUserById(int id);
public Task<IEnumerable<User>?> GetAllAthletes(int index, int count, AthleteOrderCriteria? criteria, bool descending = false); public Task<IEnumerable<User>?> GetAllAthletes(int index, int count, AthleteOrderCriteria? criteria, bool descending = false);
public Task<IEnumerable<User>?> GetAllCoaches(int index, int count, AthleteOrderCriteria? criteria, bool descending = false); public Task<IEnumerable<User>?> GetAllCoaches(int index, int count, AthleteOrderCriteria? criteria, bool descending = false);

@ -1,3 +1,5 @@
using Dto;
using Dto.Tiny;
using Model; using Model;
using Model.Repository; using Model.Repository;
using Shared; using Shared;
@ -5,6 +7,7 @@ using Model.Manager;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Entities; using Entities;
using EFMappers; using EFMappers;
using Entities2Dto;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Model2Entities; namespace Model2Entities;
@ -21,13 +24,13 @@ public partial class DbDataManager : IDataManager
this._logger = logger; this._logger = logger;
} }
public async Task<IEnumerable<Activity>> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false) public async Task<IEnumerable<ActivityTinyDto>?> 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 index {index} and count {count}", index, count);
_logger.LogInformation($"GetActivities with criteria {criteria} and descending {descending}", criteria, descending); _logger.LogInformation($"GetActivities with criteria {criteria} and descending {descending}", criteria, descending);
var activities = _dataManager.DbContext.ActivitiesSet 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"); _logger.LogInformation($"Retrieved {activities.Count()} activities");
return await Task.FromResult(activities); return await Task.FromResult(activities);
@ -67,18 +70,46 @@ public partial class DbDataManager : IDataManager
} }
} }
public async Task<Activity?> UpdateActivity(int id, Activity activity) public async Task<ResponseActivityDto?> AddActivity(NewActivityDto activity)
{ {
try try
{ {
_logger.LogInformation($"Updating activity with ID {id}"); _logger.LogInformation("Adding new activity");
var updatedActivity = await _dataManager.DbContext.UpdateItem<Activity, ActivityEntity>(id, activity, (activity, entity) =>
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<ResponseActivityDto> 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.Type = activity.Type;
entity.Date = DateOnly.FromDateTime(activity.Date); entity.Date = DateOnly.FromDateTime(activity.Date);
entity.StartTime = TimeOnly.FromDateTime(activity.StartTime); entity.StartTime = TimeOnly.FromDateTime(activity.StartTime);
entity.EndTime = TimeOnly.FromDateTime(activity.EndTime); entity.EndTime = TimeOnly.FromDateTime(activity.EndTime);
entity.EffortFelt = activity.Effort; entity.EffortFelt = activity.EffortFelt;
entity.Variability = activity.Variability; entity.Variability = activity.Variability;
entity.Variance = activity.Variance; entity.Variance = activity.Variance;
entity.StandardDeviation = activity.StandardDeviation; entity.StandardDeviation = activity.StandardDeviation;
@ -87,16 +118,15 @@ public partial class DbDataManager : IDataManager
entity.Minimum = activity.Minimum; entity.Minimum = activity.Minimum;
entity.AverageTemperature = activity.AverageTemperature; entity.AverageTemperature = activity.AverageTemperature;
entity.HasAutoPause = activity.HasAutoPause; entity.HasAutoPause = activity.HasAutoPause;
}); _dataManager.DbContext.SaveChanges();
if (updatedActivity != null)
{
_logger.LogInformation($"Updated activity with ID {id}"); _logger.LogInformation($"Updated activity with ID {id}");
return await Task.FromResult(updatedActivity.ToModel()); return await Task.FromResult(entity.ToResponseDto());
} }
else else
{ {
_logger.LogError($"Failed to update activity with ID {id}"); _logger.LogError($"Failed to update activity with ID {id}");
return await Task.FromResult<Activity?>(null); return await Task.FromResult<ResponseActivityDto?>(null);
} }
} }
catch (Exception ex) catch (Exception ex)

@ -40,13 +40,10 @@ public static class Extensions
var existingT = await context.Set<U>().FindAsync(id); var existingT = await context.Set<U>().FindAsync(id);
if (existingT != null && newItem != null) 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); updateAction(newItem, existingT);
// Marquer l'objet comme modifié dans le contexte
context.Update(existingT); context.Update(existingT);
// Enregistrer les modifications dans la base de données
await context.SaveChangesAsync(); await context.SaveChangesAsync();
return existingT; return existingT;
} }
@ -84,7 +81,7 @@ public static class Extensions
return descending ? list.OrderByDescending(x => propertyInfo.GetValue(x)) : list.OrderBy(x => propertyInfo.GetValue(x)); return descending ? list.OrderByDescending(x => propertyInfo.GetValue(x)) : list.OrderBy(x => propertyInfo.GetValue(x));
} }
public static IQueryable<TEntity> IncludeAll<TEntity>(this HeartTrackContext dbContext, IQueryable<TEntity> query) where TEntity : class public static IQueryable<TEntity> IncludeAll<TEntity>(this IQueryable<TEntity> query, HeartTrackContext dbContext) where TEntity : class
{ {
var entityType = dbContext.Model.FindEntityType(typeof(TEntity)); var entityType = dbContext.Model.FindEntityType(typeof(TEntity));
foreach (var navigation in entityType.GetNavigations()) foreach (var navigation in entityType.GetNavigations())

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DbContextLib\DbContextLib.csproj" /> <ProjectReference Include="..\DbContextLib\DbContextLib.csproj" />
<ProjectReference Include="..\Entities2Dto\Entities2Dto.csproj" />
<ProjectReference Include="..\Model\Model.csproj" /> <ProjectReference Include="..\Model\Model.csproj" />
<ProjectReference Include="..\EFMappers\EFMappers.csproj" /> <ProjectReference Include="..\EFMappers\EFMappers.csproj" />
<ProjectReference Include="..\StubbedContextLib\StubbedContextLib.csproj" /> <ProjectReference Include="..\StubbedContextLib\StubbedContextLib.csproj" />

@ -1,9 +1,12 @@
using Dto;
using Dto.Tiny;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Model; using Model;
using Model.Repository; using Model.Repository;
using Shared; using Shared;
using EFMappers; using EFMappers;
using Entities; using Entities;
using Entities2Dto;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Model2Entities; namespace Model2Entities;
@ -39,6 +42,16 @@ public partial class DbDataManager
} }
public async Task<IEnumerable<UserTinyDto>?> 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<User?> GetItemById(int id) public async Task<User?> GetItemById(int id)
{ {
@ -54,6 +67,43 @@ public partial class DbDataManager
} }
public async Task<UserTinyDto?> 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<UserTinyDto?>(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<ResponseUserDto> 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<User?> UpdateItem(int oldItem, User newItem) public async Task<User?> UpdateItem(int oldItem, User newItem)
{ {
_logger.LogInformation($"UpdateItem with id {oldItem}", oldItem); _logger.LogInformation($"UpdateItem with id {oldItem}", oldItem);
@ -107,7 +157,6 @@ public partial class DbDataManager
public async Task<int> GetNbItems() public async Task<int> GetNbItems()
{ {
_logger.LogInformation("GetNbItems"); _logger.LogInformation("GetNbItems");
var nbItems = await _dataManager.DbContext.AthletesSet.CountAsync(); var nbItems = await _dataManager.DbContext.AthletesSet.CountAsync();
_logger.LogInformation($"Retrieved {nbItems} users"); _logger.LogInformation($"Retrieved {nbItems} users");
@ -143,84 +192,135 @@ public partial class DbDataManager
} }
public async Task<bool> AddFriend(User user, User friend)
public async Task<bool> AddFollowing(int fromUser, int toUser)
{ {
_logger.LogInformation($"Attempting to add friend: User {user.Id} adding Friend {friend.Id}"); _logger.LogInformation($"Attempting to add following: User {fromUser} adding Following {toUser}");
var userEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == user.Id);
var friendEntity = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().FirstOrDefault(a => a.IdAthlete == friend.Id); var userEntity = _dataManager.DbContext.AthletesSet
if (userEntity == null || friendEntity == null) .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}"); _logger.LogWarning($"User not found: User {fromUser}");
return false; 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))
{ {
_logger.LogInformation($"Following already exists: User {fromUser} and Following {toUser}");
throw new FriendShipException("Following already exists");
}
await _dataManager.DbContext.SaveChangesAsync();
userEntity.Followings.Add(new FriendshipEntity userEntity.Followings.Add(new FriendshipEntity
{ FollowingId = friend.Id, FollowerId = user.Id, StartDate = DateTime.Now }); {
FollowingId = toUser,
FollowerId = fromUser,
StartDate = DateTime.Now
});
await _dataManager.DbContext.SaveChangesAsync(); await _dataManager.DbContext.SaveChangesAsync();
_logger.LogInformation($"Successfully added friend: User {user.Id} added Friend {friend.Id}");
_logger.LogInformation($"Successfully following: from User {fromUser} to Following {toUser}");
return true; return true;
} }
_logger.LogInformation($"Friendship already exists: User {user.Id} and Friend {friend.Id}"); public async Task<bool> RemoveFollowing(int fromUser, int toUser){
return false; _logger.LogInformation($"Attempting to remove following: User {fromUser} removing Following {toUser}");
}
public async Task<bool> RemoveFriend(User user, User friend) var userEntity = _dataManager.DbContext.AthletesSet
{ .Include(a => a.Followings)
_logger.LogInformation($"Attempting to remove friend: User {user.Id} removing Friend {friend.Id}"); .FirstOrDefault(a => a.IdAthlete == fromUser);
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)
if (userEntity == null || friendEntity == null)
{ {
_logger.LogWarning($"User or friend not found: User {user.Id}, Friend {friend.Id}"); _logger.LogWarning($"User not found: User {fromUser}");
return false; throw new FriendShipException("User with id " + fromUser + " not found");
} }
var friendship = userEntity.Followings.FirstOrDefault(f => f.FollowingId == friend.Id); var friendship = userEntity.Followings.FirstOrDefault(f => f.FollowingId == toUser);
if (friendship != null) if (friendship == null)
{ {
_logger.LogInformation($"Following not found: User {fromUser} and Following {toUser}");
throw new FriendShipException("Following not found");
}
await _dataManager.DbContext.SaveChangesAsync();
userEntity.Followings.Remove(friendship); userEntity.Followings.Remove(friendship);
await _dataManager.DbContext.SaveChangesAsync(); await _dataManager.DbContext.SaveChangesAsync();
_logger.LogInformation($"Successfully removed friend: User {user.Id} removed Friend {friend.Id}");
return true;
}
_logger.LogInformation($"Friendship does not exist: User {user.Id} and Friend {friend.Id}"); _logger.LogInformation($"Successfully removed following: from User {fromUser} to Following {toUser}");
return false; return await Task.FromResult(true);
} }
public async Task<IEnumerable<UserTinyDto>?> GetFriends(int userId, int index, int count, AthleteOrderCriteria? criteria,
public Task<IEnumerable<User>> GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria,
bool descending = false) bool descending = false)
{ {
try try
{ {
_logger.LogInformation($"GetFriends with index {index} and count {count}", index, count); _logger.LogInformation($"GetFriends called with index {index}, count {count}, criteria {criteria}, and descending {descending}");
_logger.LogInformation($"GetFriends with criteria {criteria} and descending {descending}", criteria,
descending); var athlete = await _dataManager.DbContext.AthletesSet
var friends = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().Include(a => a.Followers).Include(a => a.Followings) .Include(a => a.Followers).ThenInclude(f => f.Follower)
.GetItemsWithFilterAndOrdering(a => a.Followers.Any(f => f.FollowingId == user.Id), index, count, .Include(a => a.Followings).ThenInclude(f => f.Following)
criteria, descending).ToModels(); .FirstOrDefaultAsync(a => a.IdAthlete == userId); // Use async version for better performance
_logger.LogInformation($"Retrieved {friends.Count()} friends");
return Task.FromResult(friends); 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) catch (Exception ex)
{ {
_logger.LogError(ex.Message, ex.InnerException, ex.StackTrace); _logger.LogError(ex.Message, ex.InnerException, ex.StackTrace);
return Task.FromResult<IEnumerable<User>>(new List<User>()); return null;
} }
} }
public Task<int> GetNbFriends(User user) public async Task<int> GetNbFriends(int userId)
{ {
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);
_logger.LogInformation($"GetNbFriends with user {user}", user); if (athlete == null)
var nbFriends = _dataManager.DbContext.AthletesSet {
.GetItemsWithFilterAndOrdering(a => a.IdAthlete == user.Id, 0, int.MaxValue, _logger.LogError("Athlete with id {id} not found", userId);
AthleteOrderCriteria.None, false).First().Followings.Count(); throw new ModelNotFoundException($"Athlete with id {userId} not found");
_logger.LogInformation($"Retrieved {nbFriends} friends");
return Task.FromResult(nbFriends);
} }
// 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.
}
}
} }
} }

@ -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;
}
}*/

@ -2,25 +2,25 @@ namespace Shared;
public static class Extensions public static class Extensions
{ {
public static U ToU<T, U>(this T t, GenericMapper<T, U> mapper, Func<T, U> func,Action<T, U>? action = null) where U :class where T :class public static U ToU<T, U>(this T t, GenericMapper<T, U> mapper, Func<T, U> func,Action<T, U>? action = null,bool useMapper = true) where U :class where T :class
{ {
var res = mapper.GetU(t); var res = mapper.GetU(t);
if (res != null) return res; if (res != null) return res;
U u = func(t); U u = func(t);
mapper.Add(t, u); if(useMapper) mapper.Add(t, u);
if(action != null) action(t, u); if(action != null) action(t, u);
return u; return u;
} }
// , Action<T, U> action // , Action<T, U> action
public static T ToT<T,U>(this U u, GenericMapper<T, U> mapper, Func<U, T> func,Action<U, T>? action = null) where U :class where T :class public static T ToT<T,U>(this U u, GenericMapper<T, U> mapper, Func<U, T> func,Action<U, T>? action = null,bool useMapper = true) where U :class where T :class
{ {
var result = mapper.GetT(u); var result = mapper.GetT(u);
if(result != null) return result; if(result != null) return result;
T t = func(u); T t = func(u);
mapper.Add(t, u); if(useMapper) mapper.Add(t, u);
if(action != null) action(u, t); if(action != null) action(u, t);
return t; return t;

@ -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)
{
}
}

@ -1,3 +1,5 @@
using Dto;
using Dto.Tiny;
using Model; using Model;
using Model.Repository; using Model.Repository;
using Shared; using Shared;
@ -6,17 +8,17 @@ namespace StubAPI;
public class ActivityService: IActivityRepository public class ActivityService: IActivityRepository
{ {
private List<Activity> _activities = new List<Activity>( private List<ActivityTinyDto> _activities = new List<ActivityTinyDto>(
new Activity[] new ActivityTinyDto[]
{ {
new Activity new ActivityTinyDto
{ {
Id = 1, Id = 1,
Type = "Running", Type = "Running",
Date = new DateTime(2021, 10, 10), Date = new DateTime(2021, 10, 10),
StartTime = new DateTime(2021, 10, 10, 10, 0, 0), StartTime = new DateTime(2021, 10, 10, 10, 0, 0),
EndTime = new DateTime(2021, 10, 10, 11, 0, 0), EndTime = new DateTime(2021, 10, 10, 11, 0, 0),
Effort = 3, EffortFelt = 3,
Variability = 0.5f, Variability = 0.5f,
Variance = 0.5f, Variance = 0.5f,
StandardDeviation = 0.5f, StandardDeviation = 0.5f,
@ -25,33 +27,41 @@ public class ActivityService: IActivityRepository
Minimum = 0, Minimum = 0,
AverageTemperature = 20.0f, AverageTemperature = 20.0f,
HasAutoPause = false, 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<IEnumerable<Activity>?> GetActivities(int index, int count, ActivityOrderCriteria criteria, bool descending = false) public async Task<IEnumerable<ActivityTinyDto>?> 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)); => await Task.FromResult(_activities.GetItemsWithFilterAndOrdering(a => true, index, count, criteria, descending));
public Task<Activity?> GetActivityByIdAsync(int id) public Task<Activity?> 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<Activity?> AddActivity(Activity activity) public Task<Activity?> AddActivity(Activity activity)
=> _activities.AddItem(activity); => throw new NotImplementedException();
public async Task<ResponseActivityDto?> AddActivity(NewActivityDto activity)
{
throw new NotImplementedException();
}
public async Task<ResponseActivityDto?> UpdateActivity(int id, ActivityTinyDto activity)
{
throw new NotImplementedException();
}
public async Task<Activity?> UpdateActivity(int id, Activity activity) public async Task<Activity?> 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; if (oldActivity == null) return null;
return await _activities.UpdateItem(oldActivity, activity); return await _activities.UpdateItem(oldActivity, activity);*/
} }
public Task<bool> DeleteActivity(int id) public Task<bool> DeleteActivity(int id)
@ -66,13 +76,16 @@ public class ActivityService: IActivityRepository
public async Task<IEnumerable<Activity>?> GetActivitiesByUser(int userId, int index, int count, ActivityOrderCriteria criteria, bool descending = false) public async Task<IEnumerable<Activity>?> 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); criteria != ActivityOrderCriteria.None ? criteria : null, descending);
return await Task.FromResult(activities); return await Task.FromResult(activities);*/
} }
public Task<int> GetNbActivitiesByUser(int userId) public Task<int> 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));
} }
} }

@ -1,4 +1,6 @@
using Model; using Dto;
using Dto.Tiny;
using Model;
using Model.Repository; using Model.Repository;
using Shared; using Shared;
@ -34,6 +36,26 @@ public class UserService : IUserRepository
public async Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria? orderingProperty = null, bool descending = false) public async Task<IEnumerable<User>> GetUsers(int index, int count, AthleteOrderCriteria? orderingProperty = null, bool descending = false)
=> athletes.GetItemsWithFilterAndOrdering(c=>true,index, count,orderingProperty != AthleteOrderCriteria.None ? orderingProperty: null , descending); => athletes.GetItemsWithFilterAndOrdering(c=>true,index, count,orderingProperty != AthleteOrderCriteria.None ? orderingProperty: null , descending);
public async Task<IEnumerable<UserTinyDto>?> GetUsersTiny(int index, int count, AthleteOrderCriteria? criteria, bool descending = false)
{
throw new NotImplementedException();
}
public async Task<bool> AddFollowing(int fromUser, int toUser)
{
throw new NotImplementedException();
}
public async Task<bool> RemoveFollowing(int fromUser, int toUser)
{
throw new NotImplementedException();
}
public async Task<IEnumerable<UserTinyDto>?> GetFriends(int user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false)
{
throw new NotImplementedException();
}
public async Task<bool> AddFriend(User user, User friend) public async Task<bool> AddFriend(User user, User friend)
{ {
if (user == null || friend == null) if (user == null || friend == null)
@ -71,9 +93,19 @@ public class UserService : IUserRepository
public async Task<IEnumerable<User>?>? GetFriends(User user, int index, int count, AthleteOrderCriteria? criteria, bool descending = false) public async Task<IEnumerable<User>?>? 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)); =>await Task.FromResult(athletes.FirstOrDefault(s => s.Id == user.Id)?.Users.GetItemsWithFilterAndOrdering(c=>true,index, count,criteria, descending));
public Task<int> GetNbFriends(User user) public Task<int> GetNbFriends(int user)
{
return Task.FromResult(athletes.FirstOrDefault(s => s.Id == user)?.Users.Count ?? 0);
}
public async Task<UserTinyDto?> UpdateUser(int old, UserTinyDto user)
{
throw new NotImplementedException();
}
public async Task<ResponseUserDto> GetUserById(int id)
{ {
return Task.FromResult(athletes.FirstOrDefault(s => s.Id == user.Id)?.Users.Count ?? 0); throw new NotImplementedException();
} }
public async Task<IEnumerable<User>> GetItems(int index, int count, string? orderingProperty = null, public async Task<IEnumerable<User>> GetItems(int index, int count, string? orderingProperty = null,

@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Entities2Dto\Entities2Dto.csproj" />
<ProjectReference Include="..\Model\Model.csproj" /> <ProjectReference Include="..\Model\Model.csproj" />
</ItemGroup> </ItemGroup>

@ -43,7 +43,7 @@ namespace StubbedContextLib
modelBuilder.Entity<AthleteEntity>().HasData( modelBuilder.Entity<AthleteEntity>().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 = 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 = 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 = 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 } 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 }

@ -39,10 +39,7 @@ namespace StubbedContextLib
modelBuilder.Entity<FriendshipEntity>().HasData( modelBuilder.Entity<FriendshipEntity>().HasData(
new FriendshipEntity { FollowerId = 1, FollowingId = 2 }, new FriendshipEntity { FollowerId = 1, FollowingId = 2 },
new FriendshipEntity { FollowerId = 1, FollowingId = 3 }, new FriendshipEntity { FollowerId = 1, FollowingId = 3 },
new FriendshipEntity { FollowerId = 1, FollowingId = 4 }, new FriendshipEntity { FollowerId = 3, FollowingId = 1 }
new FriendshipEntity { FollowerId = 1, FollowingId = 5 },
new FriendshipEntity { FollowerId = 2, FollowingId = 1 },
new FriendshipEntity { FollowerId = 2, FollowingId = 3 }
); );
} }
} }

@ -10,6 +10,7 @@ using static Model2Entities.DbDataManager;
namespace Model2Entities namespace Model2Entities
{ {
/*
static class Program static class Program
{ {
static async Task Main(string[] args) static async Task Main(string[] args)
@ -114,5 +115,5 @@ namespace Model2Entities
} }
static void UsersTest() static void UsersTest()
{} {}
} }*/
} }

@ -74,14 +74,6 @@ public class UsersControllerTest
_usersController = new UsersController(new NullLogger<UsersController>(), _dataManagerMock.Object); _usersController = new UsersController(new NullLogger<UsersController>(), _dataManagerMock.Object);
} }
/*
[TestInitialize]
public void SetUp()
{
_dataManager = new StubData();
_usersController = new UsersController(new NullLogger<UsersController>(), _dataManager);
}*/
[TestMethod] [TestMethod]
public async Task Get_ReturnsPageResponse_WhenRequestIsValid() public async Task Get_ReturnsPageResponse_WhenRequestIsValid()

@ -63,7 +63,7 @@ public class FriendshipEntityTests (DatabaseFixture fixture) : IClassFixture<Dat
using (var context = new TrainingStubbedContext(fixture._options)) using (var context = new TrainingStubbedContext(fixture._options))
{ {
var savedFriendship = context.AthletesSet.Include(a => 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); Assert.NotNull(savedFriendship);
if (savedFriendship != null) if (savedFriendship != null)

Loading…
Cancel
Save