242 lines
8.9 KiB
C#
242 lines
8.9 KiB
C#
|
|
using AutoMapper;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
|
|
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;
|
|
res.FlushTime = Convert.ToInt32(AppSettings.FlushTime);
|
|
|
|
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();
|
|
|
|
return res;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据班级Id获取学生列表
|
|
/// </summary>
|
|
/// <param name="classId"></param>
|
|
/// <returns></returns>
|
|
public async Task<List<StudentDto>> StudentList(int classId)
|
|
{
|
|
var res = await _sportsContext.Student.Where(x => x.SchoolCode == schoolCode && x.ClassId == classId && x.StudentStatus == 1).Select(x => new StudentDto
|
|
{
|
|
StudentNo = x.StudentNo,
|
|
StudentName = x.StudentName,
|
|
Photo = x.Photo ?? "",
|
|
Sex = x.Sex
|
|
}).ToListAsync();
|
|
|
|
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(-1);
|
|
|
|
// 在线心率设备
|
|
int onlineHeartRateCount = RedisHelper.Keys("heartRate:*").Length;
|
|
res.HeartRateOnlineCount = onlineHeartRateCount;
|
|
|
|
// 在线跳绳设备
|
|
int onlineJumpRopeCount = RedisHelper.Keys("jumpRope:raw:*").Length;
|
|
res.JumpingRopeOnLineCount = onlineJumpRopeCount;
|
|
|
|
// 1. 构建缓存 key
|
|
string studentListKey = $"students:{schoolCode}:{classId}";
|
|
|
|
// 2. 尝试从缓存获取
|
|
var studentList = _caching.Get<List<StudentDto>>(studentListKey);
|
|
|
|
// 3. 如果缓存没有 → 查询数据库 + 写入缓存
|
|
if (studentList == null || studentList.Count == 0)
|
|
{
|
|
studentList = await _sportsContext.Student
|
|
.Where(x => x.ClassId == classId && x.SchoolCode == schoolCode && x.StudentStatus == 1)
|
|
.Select(x => new StudentDto
|
|
{
|
|
StudentNo = x.StudentNo,
|
|
StudentName = x.StudentName,
|
|
Sex = x.Sex,
|
|
Photo = x.Photo ?? ""
|
|
})
|
|
.ToListAsync();
|
|
|
|
_caching.AddObject(studentListKey, studentList, 60); // 缓存 8 小时
|
|
}
|
|
|
|
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}";
|
|
|
|
//string jumpRopeKey = $"{student.StudentNo}_{DateTime.Now:yyyyMMdd}";
|
|
|
|
var jumpRopeKey = $"jumpRope:active:{student.StudentNo}:{DateTime.Now:yyyyMMdd}";
|
|
|
|
// 先从缓存拿
|
|
var heartRate = _caching.Get<HeartRateData>(heartRateKey);
|
|
|
|
var jumpRope = _caching.Get<JumpRopeData>(jumpRopeKey);
|
|
|
|
if (jumpRope == null)
|
|
{
|
|
jumpRope = await _userContext.JumpRopeData.Where(x => x.StudentNo == student.StudentNo).FirstOrDefaultAsync();
|
|
}
|
|
|
|
// ❗心率缓存未命中 → 单独查数据库
|
|
//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, 60);
|
|
//}
|
|
|
|
// ❗跳绳缓存未命中 → 单独查数据库
|
|
//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, 60);
|
|
//}
|
|
|
|
// 心率强度判断
|
|
int strength = heartRate?.Strength ?? 0;
|
|
|
|
switch (strength)
|
|
{
|
|
case > 0 and < 50:
|
|
warmUp++;
|
|
break;
|
|
case >= 50 and < 60:
|
|
low++;
|
|
break;
|
|
case >= 60 and < 70:
|
|
medium++;
|
|
break;
|
|
case >= 70 and < 85:
|
|
high++;
|
|
break;
|
|
case >= 85:
|
|
warning++;
|
|
break;
|
|
}
|
|
|
|
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,
|
|
HeartRateQuantityOfElectricity = heartRate?.QuantityOfElectricity ?? 0,
|
|
JumpingRopeQuantityOfElectricity = jumpRope?.QuantityOfElectricity ?? 0
|
|
});
|
|
}
|
|
|
|
int total = RedisHelper.Keys("heartRate:*").Length;
|
|
|
|
int CalcPercentage(int count) =>
|
|
total == 0 ? 0 : (int)Math.Round(count * 100.0 / total);
|
|
|
|
res.WarmUp = CalcPercentage(warmUp);
|
|
res.Low = CalcPercentage(low);
|
|
res.Medium = CalcPercentage(medium);
|
|
res.High = CalcPercentage(high);
|
|
res.Warning = CalcPercentage(warning);
|
|
|
|
return res;
|
|
}
|
|
}
|
|
}
|