VEU.WathBody/3-app/2-cli/Server.WatchBody.Web/Controllers/Admin/AdminMetricsController.cs

81 lines
3.0 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Server.WatchBody.Core.Dal.Src.Repository;
using Server.WatchBody.Web.Services;
namespace Server.WatchBody.Web.Controllers.Admin;
/// <summary>Метрики (Ф-9.4) и сводка план/факт (Ф-9.5) — только
/// чтение (spec 05 m08).</summary>
public class AdminMetricsController(
AdminAuthService auth,
IWorkoutRepository workouts,
IWorkoutMetricsRepository metrics,
PlanSummaryService plan) : AdminControllerBase(auth)
{
public ActionResult Metrics(int athleteId, string? dateFrom, string? dateTo)
{
if (Denied()) return UnauthorizedJson();
DateOnly? from = dateFrom != null && DateOnly.TryParse(dateFrom, out var f) ? f : null;
DateOnly? to = dateTo != null && DateOnly.TryParse(dateTo, out var t) ? t : null;
var rows = metrics.Select(new WorkoutMetricsFilter
{
AthleteId = athleteId, DateFrom = from, DateTo = to,
}).ToList();
var byDate = new Dictionary<Guid, DateTime>();
foreach (var workout in workouts.Select(new WorkoutFilter
{ AthleteId = athleteId, DateFrom = from, DateTo = to }))
byDate[workout.Id] = workout.StartedAt;
var workoutRows = rows
.OrderByDescending(m => byDate.GetValueOrDefault(m.WorkoutId))
.Select(m => new
{
m.WorkoutId,
date = byDate.TryGetValue(m.WorkoutId, out var started)
? DateOnly.FromDateTime(started).ToString("yyyy-MM-dd") : null,
m.Adherence,
m.Tonnage,
tonnageByGroup = Json(m.TonnageByGroup),
e1pmByExercise = Json(m.E1pmByExercise),
redFlags = Json(m.RedFlags),
}).ToList();
// weekly: ISO-неделя даты тренировки
var weekly = workoutRows
.Where(r => r.date != null)
.GroupBy(r => MondayOf(DateOnly.Parse(r.date!)))
.Select(g => new
{
week = g.Key.ToString("yyyy-MM-dd"),
workouts = g.Count(),
avgAdherence = Math.Round(g.Average(r => r.Adherence), 1, MidpointRounding.AwayFromZero),
tonnage = Math.Round(g.Sum(r => r.Tonnage), 1, MidpointRounding.AwayFromZero),
}).OrderBy(w => w.week).ToList();
return new JsonResult(new { workouts = workoutRows, weekly });
}
public ActionResult Plan(int athleteId)
{
if (Denied()) return UnauthorizedJson();
return new JsonResult(plan.Summarize(athleteId));
}
private static object? Json(string? source)
{
if (string.IsNullOrWhiteSpace(source)) return null;
try
{
return System.Text.Json.JsonSerializer.Deserialize<object>(source);
}
catch (System.Text.Json.JsonException)
{
return source;
}
}
private static DateOnly MondayOf(DateOnly date) =>
date.AddDays(-(((int)date.DayOfWeek + 6) % 7));
}