2025-07-07 10:41:29 +08:00

222 lines
8.0 KiB
C#

using AutoMapper;
using Microsoft.EntityFrameworkCore;
using System.Drawing;
using System.Reflection.PortableExecutable;
using YD_AllHeartRates.Api.Context;
using YD_AllHeartRates.Api.Entitys;
using YD_AllHeartRates.Api.Services.Interface;
using YD_AllHeartRates.Api.SmartSportsEntitys;
using YD_AllHeartRates.Api.Utilities;
using YD_AllHeartRates.Commons.Dto.LargeScreen;
using YD_AllHeartRates.Commons.MemoryCaches;
namespace YD_AllHeartRates.Api.Services.Impl
{
/// <summary>
/// 服务实现
/// </summary>
public class LargeScreenService : ILargeScreenService
{
public SmartSportsContext _sportsContext;
public UserContext _userContext;
private readonly LoginContext _loginContext;
private string schoolCode;
private readonly ICaching _caching;
/// <summary>
/// 构造
/// </summary>
public LargeScreenService(SmartSportsContext sportsContext, UserContext userContext, LoginContext loginContext, ICaching caching)
{
_sportsContext = sportsContext;
_userContext = userContext;
_loginContext = loginContext;
_caching = caching;
schoolCode = _loginContext.SchoolCode;
}
/// <summary>
/// 获取学校数据
/// </summary>
/// <returns></returns>
public async Task<SchoolDto> SchoolInfo()
{
var res = new SchoolDto();
res.SchoolCode = schoolCode;
res.Name = _loginContext.UserName;
var gIds = await _sportsContext.SchoolAssocGrade.Where(x => x.SchoolCode == schoolCode).Select(x => x.GradeId).ToListAsync();
var grades = await (
from g in _sportsContext.Grade
join c in _sportsContext.Class on g.Id equals c.GradeId into classGroup
from c in classGroup.DefaultIfEmpty()
where gIds.Contains(g.Id) && c.SchoolCode == schoolCode
group c by new { g.Id, g.GradeName } into gradeGroup
select new Grades()
{
Id = gradeGroup.Key.Id,
Name = gradeGroup.Key.GradeName,
Class = gradeGroup.Where(c => c != null).Select(c => new Classes
{
Id = c.Id,
Name = c.ClassName
}).ToList()
}).ToListAsync();
res.Grade = grades;
var devices = await _sportsContext.Device.Where(x => x.SchoolCode == schoolCode).ToListAsync();
var heartRateDevices = devices.Where(x => x.DeviceType == 1).ToList();
var jumpingRopeDevices = devices.Where(x => x.DeviceType == 2).ToList();
res.HeartRateAllCount = heartRateDevices.Count();
res.JumpingRopeAllCount = jumpingRopeDevices.Count();
var tenMinutesAgo = DateTime.Now.AddMinutes(-10);
#region
var heartRateData = _userContext.HeartRateData
.Where(x => x.SchoolCode == schoolCode && x.ScoreTime >= tenMinutesAgo)
.ToList();
var onlineHeartRateDeviceCodes = heartRateData
.Select(x => x.Code)
.Distinct()
.ToHashSet();
// 在线设备
var onlineHeartRateDevices = heartRateDevices
.Where(x => onlineHeartRateDeviceCodes.Contains(x.Code))
.ToList();
// 离线设备 = 所有心率设备 - 在线设备
var offlineHeartRateDevices = heartRateDevices
.Where(x => !onlineHeartRateDeviceCodes.Contains(x.Code))
.ToList();
// 设置返回值或继续处理
res.HeartRateOnlineCount = onlineHeartRateDevices.Count;
res.HeartRateOfflineCount = offlineHeartRateDevices.Count;
#endregion
#region
var jumpRopeData = _userContext.JumpRopeData
.Where(x => x.SchoolCode == schoolCode && x.ScoreTime >= tenMinutesAgo)
.ToList();
var onlineJumpRopeDeviceCodes = jumpRopeData
.Select(x => x.Code)
.Distinct()
.ToHashSet();
// 在线设备
var onlineJumpRopeDevices = jumpingRopeDevices
.Where(x => onlineJumpRopeDeviceCodes.Contains(x.Code))
.ToList();
// 离线设备 = 所有心率设备 - 在线设备
var offlineJumpRopeDevices = jumpingRopeDevices
.Where(x => !onlineJumpRopeDeviceCodes.Contains(x.Code))
.ToList();
// 设置返回值或继续处理
res.JumpingRopeOnLineCount = onlineJumpRopeDevices.Count;
res.JumpingRopeOfflineCount = offlineJumpRopeDevices.Count;
#endregion
return res;
}
/// <summary>
/// 心率数据
/// </summary>
/// <returns></returns>
public async Task<HeartRateDataDto> HeartRateData(int classId)
{
var res = new HeartRateDataDto();
var now = DateTime.Now;
var tenMinutesAgo = now.AddMinutes(-10);
// 班级学生列表
var studentList = await _sportsContext.Student
.Where(x => x.ClassId == classId && x.SchoolCode == schoolCode && x.StudentStatus == 1)
.ToListAsync();
int warmUp = 0, low = 0, medium = 0, high = 0, warning = 0;
foreach (var student in studentList)
{
var heartRateKey = $"heartRate:{student.StudentNo}";
var jumpRopeKey = $"jumpRope:{student.StudentNo}";
// 先从缓存拿
var heartRate = _caching.Get<HeartRateData>(heartRateKey);
var jumpRope = _caching.Get<JumpRopeData>(jumpRopeKey);
// ❗心率缓存未命中 → 单独查数据库
if (heartRate == null)
{
heartRate = await _userContext.HeartRateData
.Where(x => x.StudentNo == student.StudentNo && x.ScoreTime >= tenMinutesAgo)
.OrderByDescending(x => x.ScoreTime)
.FirstOrDefaultAsync();
if (heartRate != null)
_caching.AddObject(heartRateKey, heartRate, 600);
}
// ❗跳绳缓存未命中 → 单独查数据库
if (jumpRope == null)
{
jumpRope = await _userContext.JumpRopeData
.Where(x => x.StudentNo == student.StudentNo && x.ScoreTime.Date == now.Date)
.OrderByDescending(x => x.ScoreTime)
.FirstOrDefaultAsync();
if (jumpRope != null)
_caching.AddObject(jumpRopeKey, jumpRope, 600);
}
// 心率强度判断
int strength = heartRate?.Strength ?? 0;
if (strength < 50) warmUp++;
else if (strength < 60) low++;
else if (strength < 70) medium++;
else if (strength < 85) high++;
else warning++;
res.StudentList.Add(new StudentDto
{
StudentName = student.StudentName,
StudentNo = student.StudentNo,
Photo = student.Photo ?? "",
Sex = student.Sex,
HeartRate = heartRate?.Value ?? 0,
JumpingRope = jumpRope?.JumpValue ?? 0,
Strength = strength
});
}
int total = studentList.Count == 0 ? 1 : studentList.Count;
res.WarmUp = (int)Math.Round(warmUp * 100.0 / total);
res.Low = (int)Math.Round(low * 100.0 / total);
res.Medium = (int)Math.Round(medium * 100.0 / total);
res.High = (int)Math.Round(high * 100.0 / total);
res.Warning = (int)Math.Round(warning * 100.0 / total);
return res;
}
}
}