YD_SmartSports.Api/VOL.Business/Services/Norm/N_SportsTestResultService.cs
2025-06-06 16:55:14 +08:00

1765 lines
74 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AutoMapper;
using Castle.DynamicProxy.Generators;
using Confluent.Kafka;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ML;
using OfficeOpenXml.ConditionalFormatting;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using SkiaSharp;
using StackExchange.Redis;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VOL.Business.IServices;
using VOL.Business.IServices.Norm;
using VOL.Core.CacheManager;
using VOL.Core.Configuration;
using VOL.Core.Extensions;
using VOL.Core.Extensions.AutofacManager;
using VOL.Core.ManageUser;
using VOL.Core.Utilities;
using VOL.Entity.DomainModels;
using VOL.Entity.DomainModels.Business.People;
using VOL.Entity.Enum;
using VOL.Model;
using VOL.Model.Ai;
using VOL.Model.Norm.Request;
using VOL.Model.Norm.Response;
using VOL.Model.School.Response;
using VOL.System.IRepositories;
using VOL.System.Repositories;
using static Dapper.SqlMapper;
using static System.Formats.Asn1.AsnWriter;
namespace VOL.Business.Services
{
public class N_SportsTestResultService : IN_SportsTestResultService, IDependency
{
#region
private readonly IMapper _mapper;
private readonly ICacheService _cacheService;
private readonly ICacheQueryService _cacheQueryService;
private readonly IN_SportsTestResultRepository _sportsTestResultRepository;
private readonly IS_GradeRepository _gradeRepository;
private readonly IS_ClassRepository _classRepository;
private readonly IS_StudentRepository _studentRepository;
private readonly IN_HealthStandardsRepository _healthStandardsRepository;
private readonly IN_SportsTestCategoryRepository _sportsTestCategoryRepository;
//private readonly IG_ActivitiesRepository _activitiesRepository;
[ActivatorUtilitiesConstructor]
public N_SportsTestResultService(IMapper mapper,
ICacheService cacheService,
ICacheQueryService cacheQueryService,
IN_SportsTestResultRepository sportsTestResultRepository,
IS_GradeRepository gradeRepository,
IS_ClassRepository classRepository,
IS_StudentRepository studentRepository,
IN_HealthStandardsRepository healthStandardsRepository,
IN_SportsTestCategoryRepository sportsTestCategoryRepository
//IG_ActivitiesRepository activitiesRepository
)
{
_mapper = mapper;
_cacheService = cacheService;
_cacheQueryService = cacheQueryService;
_sportsTestResultRepository = sportsTestResultRepository;
_gradeRepository = gradeRepository;
_classRepository = classRepository;
_studentRepository = studentRepository;
_healthStandardsRepository = healthStandardsRepository;
_sportsTestCategoryRepository = sportsTestCategoryRepository;
//_activitiesRepository = activitiesRepository;
}
#endregion
/// <summary>
/// 导入学生体测成绩
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async Task ImportStudentsTestData(IFormFile file)
{
if (file == null || file.Length <= 0)
throw new Exception("操作失败");
List<ImportStudentsTestDataParam> dataObjects;
using (var fileStream = file.OpenReadStream())
{
dataObjects = Tool.ConvertExcelToList<ImportStudentsTestDataParam>(fileStream);
}
var studentNos = dataObjects.Select(x => x.StudentNo).Distinct().ToList();
// 用一个查询一次性获取所有学生信息
var students = await (from s in _studentRepository.DbContext.Set<S_Student>()
join c in _studentRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id
join g in _studentRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
where c.SchoolCode.Equals(UserContext.Current.TenantId)
select new
{
s.Id,
s.Age,
s.ClassId,
c.ClassName,
s.StudentName,
GradeId = g.Id,
g.GradeName,
s.Sex,
s.StudentNo
}).ToListAsync();
// 将学生信息存入字典,快速查找
var studentsDict = students.ToDictionary(x => x.StudentNo);
var entityList = new List<N_SportsTestValue>();
// 将时间变量移到外部,避免重复赋值
var timeNow = DateTime.Now;
foreach (var data in dataObjects)
{
if (!studentsDict.TryGetValue(data.StudentNo, out var student))
{
throw new Exception($"未找到此编号为{data.StudentNo}的学生");
}
// 为每个学生添加多条体测数据
if (data.BMIValue > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.BMI, student, timeNow));
if (data.Sit_And_ReachValue > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.Sit_And_Reach, student, timeNow));
if (data.VitalCapacityValue > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.VitalCapacity, student, timeNow));
if (data.MeterRun_50Value > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.MeterRun_50, student, timeNow));
if (data.OneMinuteJumpRopeValue > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.OneMinuteJumpRope, student, timeNow));
if (data.One_Minute_Sit_UpValue > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.One_Minute_Sit_Up, student, timeNow));
if (data.ShuttleRun_50x8Value > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.ShuttleRun_50x8, student, timeNow));
if (data.StandingLongJumpValue > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.StandingLongJump, student, timeNow));
if (data.MeterRun_800Value > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.MeterRun_800, student, timeNow));
if (data.MeterRun_1000Value > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.MeterRun_1000, student, timeNow));
if (data.Pull_UpValue > 0)
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.Pull_Up, student, timeNow));
}
// 批量添加数据
await _sportsTestResultRepository.AddRangeAsync(entityList);
// 一次性保存所有修改
await _sportsTestResultRepository.SaveChangesAsync();
}
public async Task<N_SportsTestValue> AddEnumStudentsTestData(ImportStudentsTestDataParam data, SportsTestItemType type, dynamic student, DateTime timeNow)
{
int classId = student.ClassId;
var teachers = await (from c in _studentRepository.DbContext.Set<S_ClassAssocTeacher>()
join t in _studentRepository.DbContext.Set<S_Teacher>() on c.TeacherId equals t.Id
where c.ClassId == classId
select new
{
t.Id,
t.TeacherName
}).FirstOrDefaultAsync();
var entity = new N_SportsTestValue
{
TeacherId = teachers?.Id ?? 0,
TeacherName = teachers?.TeacherName ?? string.Empty,
DataSource = DataSource.IOT,
ScoreTime = timeNow,
GradeId = student.GradeId,
ClassId = student.ClassId,
GradeName = student.GradeName,
ClassName = student.ClassName,
SchoolCode = UserContext.Current.TenantId,
Sex = student.Sex,
StudentNo = data.StudentNo,
StudentName = student.StudentName,
Creator = UserContext.Current.UserId,
CreateDate = timeNow,
IsDisplay = true
};
int gradeId = student.GradeId;
SexType sexType = student.Sex;
string sex = sexType == SexType.Male ? "男" : "女";
string typeStr = type.ToString();
// 根据测试项目类型设置对应的值
if (type == SportsTestItemType.BMI)
{
entity.Value = data.BMIValue;
entity.Weight = data.Weight;
entity.Height = data.Height;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.BMIValue >= x.MinValue &&
data.BMIValue < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.Sit_And_Reach)
{
entity.Value = data.Sit_And_ReachValue;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.Sit_And_ReachValue >= x.MinValue &&
data.Sit_And_ReachValue < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.VitalCapacity)
{
entity.Value = data.VitalCapacityValue;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.VitalCapacityValue >= x.MinValue &&
data.VitalCapacityValue < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.MeterRun_50)
{
entity.Value = data.MeterRun_50Value;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.MeterRun_50Value >= x.MinValue &&
data.MeterRun_50Value < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.OneMinuteJumpRope)
{
entity.Value = data.OneMinuteJumpRopeValue;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.OneMinuteJumpRopeValue >= x.MinValue &&
data.OneMinuteJumpRopeValue < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
if (standard.Score >= 100)
{
int count = (int)(data.Value - standard.MinValue);
var additionalScore = GetRopeSkipAdditionalScore(sex, count);
entity.Score = entity.Score + additionalScore;
}
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.One_Minute_Sit_Up)
{
entity.Value = data.One_Minute_Sit_UpValue;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.One_Minute_Sit_UpValue >= x.MinValue &&
data.One_Minute_Sit_UpValue < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
if (standard.Score >= 100)
{
int count = (int)(data.Value - standard.MinValue);
var additionalScore = GetPullUpSitUpsAdditionalScore(sex, count);
entity.Score = entity.Score + additionalScore;
}
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.ShuttleRun_50x8)
{
entity.Value = data.ShuttleRun_50x8Value;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.ShuttleRun_50x8Value >= x.MinValue &&
data.ShuttleRun_50x8Value < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.StandingLongJump)
{
entity.Value = data.StandingLongJumpValue;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.StandingLongJumpValue >= x.MinValue &&
data.StandingLongJumpValue < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.MeterRun_800)
{
entity.Value = data.MeterRun_800Value;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.MeterRun_800Value >= x.MinValue &&
data.MeterRun_800Value < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
if (standard.Score >= 100)
{
int count = (int)(standard.MinValue - data.Value);
var additionalScore = GetRunAdditionalScore(sex, count);
entity.Score = entity.Score + additionalScore;
}
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.MeterRun_1000)
{
entity.Value = data.MeterRun_1000Value;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.MeterRun_1000Value >= x.MinValue &&
data.MeterRun_1000Value < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
if (standard.Score >= 100)
{
int count = (int)(standard.MinValue - data.Value);
var additionalScore = GetRunAdditionalScore(sex, count);
entity.Score = entity.Score + additionalScore;
}
entity.Rank = standard.Rank;
}
}
else if (type == SportsTestItemType.Pull_Up)
{
entity.Value = data.Pull_UpValue;
// 根据测试项目查找标准
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
x.CategoryEnum.Equals(typeStr) &&
x.GradeId == gradeId &&
x.Sex == sexType &&
data.Pull_UpValue >= x.MinValue &&
data.Pull_UpValue < x.MaxValue
);
if (standard != null)
{
entity.Score = standard.Score;
if (standard.Score >= 100)
{
int count = (int)(data.Value - standard.MinValue);
var additionalScore = GetPullUpSitUpsAdditionalScore(sex, count);
entity.Score = entity.Score + additionalScore;
}
entity.Rank = standard.Rank;
}
}
entity.CategoryEnum = type.ToString();
entity.CategoryValue = (int)type;
return entity;
}
/// <summary>
/// 大屏数据统计
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<LargeScreenDataStatModel> LargeScreenDataStat(LargeScreenDataStatParam paramDto)
{
if (paramDto.StartTime == DateTime.MinValue || paramDto.EndTime == DateTime.MinValue)
{
throw new Exception($"请求参数不可为空");
}
var res = new LargeScreenDataStatModel();
//学校信息
res.SchoolInfo = await GetLargeScreenSchoolInfo(paramDto);
//体测情况(体质健康监控)
res.TestSituations = await GetLargeScreenTestSituations(paramDto);
//体质监测排行榜
res.PhysicalMonitoringRanking = await GetLargeScreenPhysicalMonitoringRanking(paramDto);
//赛事活动情况
res.ActivitiesSituation = await GetLargeScreenActivitiesSituation(paramDto);
//肥胖情况
res.ObesitySituation = await GetLargeScreenObesitySituation(paramDto);
//视力情况
res.DicVisionSituation = await GetLargeScreenDicVisionSituation(paramDto);
//年级体测项目成绩监控
res.GradeSportsTestTranscript = await GetLargeScreenGradeSportsTestTranscript(paramDto);
return res;
}
#region
/// <summary>
/// 获取学期
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<List<SemesterModel>> SemesterList()
{
var tenantId = UserContext.Current.TenantId;
var school = await _gradeRepository.DbContext.Set<S_School>().Where(x => x.SchoolCode == tenantId).FirstAsync();
return CalculateSemesters(school.CreateDate, DateTime.Now);
}
/// <summary>
/// 大屏学校信息
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<SchoolInfoModel> GetLargeScreenSchoolInfo(LargeScreenDataStatParam paramDto)
{
var schoolInfo = new SchoolInfoModel();
var tenantId = UserContext.Current.TenantId;
//年级信息
var gradeModels = await (
from g in _gradeRepository.DbContext.Set<S_Grade>()
join a in _gradeRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
join c in _gradeRepository.DbContext.Set<S_Class>() on g.Id equals c.GradeId into classGroup
from c in classGroup.DefaultIfEmpty()
where a.SchoolCode.Equals(tenantId) && c.SchoolCode.Equals(tenantId)
group new { c } by new { g.Id, g.GradeName } into groupedData
select new
{
groupedData.Key.Id,
groupedData.Key.GradeName,
ClassCount = groupedData.Select(x => x.c.Id).Distinct().Count(),
ClassIds = groupedData.Select(x => x.c.Id).Distinct().ToList()
}).ToListAsync();
//老师信息
var teacherCountModels = await (
from t in _gradeRepository.DbContext.Set<S_Teacher>()
join a in _gradeRepository.DbContext.Set<S_ClassAssocTeacher>() on t.Id equals a.TeacherId into assocTeachers
from at in assocTeachers.DefaultIfEmpty()
where t.SchoolCode.Equals(UserContext.Current.TenantId) && t.TeacherStatus != TeacherStatus.Depart
group new { t, at } by new { t.Id } into groupedData
select new TeacherPageListModel()
{
Id = groupedData.Key.Id
}).ToListAsync();
var tCount = teacherCountModels.Count;
//老师信息
var teacherDetailsModels = from a in _gradeRepository.DbContext.Set<S_ClassAssocTeacher>()
join t in _gradeRepository.DbContext.Set<S_Teacher>() on a.TeacherId equals t.Id into teacher
from tea in teacher.DefaultIfEmpty()
where tea.SchoolCode.Equals(UserContext.Current.TenantId) && tea.TeacherStatus != TeacherStatus.Depart
group new { a } by new { a.ClassId } into groupedData
select new
{
ClassId = groupedData.Key.ClassId,
TeacherIds = groupedData
.Where(x => x.a.ClassId == groupedData.Key.ClassId)
.Select(x => x.a.TeacherId)
};
var teacherModels = await teacherDetailsModels.ToListAsync();
///班级信息
gradeModels.ForEach(x =>
{
schoolInfo.ClassData.Add(new ClassModel() { GradeName = x.GradeName, ClassCount = x.ClassCount });
var teachers = teacherModels.Where(t => x.ClassIds.Contains(t.ClassId)).ToList();
schoolInfo.TeacherData.Add(new TeacherModel()
{
GradeName = x.GradeName,
TeacherCount = teachers
.SelectMany(c => c.TeacherIds)
.Distinct()
.Count()
});
});
var classIds = gradeModels.SelectMany(x => x.ClassIds).ToList();
var students = await (from s in _studentRepository.DbContext.Set<S_Student>()
join c in _studentRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id
join g in _studentRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
where s.SchoolCode.Equals(tenantId) && s.StudentStatus == StudentStatus.Normal
select s
).ToListAsync();
schoolInfo.StudentData.MaleCount = students.Where(x => x.Sex == SexType.Male).Count();
schoolInfo.StudentData.FemaleCount = students.Where(x => x.Sex == SexType.Female).Count();
schoolInfo.TotalClassCount = gradeModels.Select(x => x.ClassCount).Sum();
schoolInfo.TotalTeacherCount = tCount;
// 从缓存中获取数据
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
// 运动时长
schoolInfo.AccumulatedTrainDuration = sportsTestResults.Select(x => x.MotionDuration).Sum();
var largeScreenTrainingDataModel = new List<LargeScreenTrainingDataModel>
{
await GeLargeScreenTrainingInfo(1, paramDto),
await GeLargeScreenTrainingInfo(2, paramDto),
await GeLargeScreenTrainingInfo(3, paramDto)
};
schoolInfo.LargeScreenTrainingDataModel = largeScreenTrainingDataModel;
return schoolInfo;
}
/// <summary>
/// 大屏训练数据
/// </summary>
/// <param name="dateType">时间类型1今日2本周3本月</param>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<LargeScreenTrainingDataModel> GeLargeScreenTrainingInfo(int dateType, LargeScreenDataStatParam paramDto)
{
var largeScreenTrainingDataModel = new LargeScreenTrainingDataModel();
var tenantId = UserContext.Current.TenantId;
DateTime startTime;
DateTime endTime;
if (dateType == 1)
{
startTime = DateTime.Today;
endTime = DateTime.Today.AddDays(1).AddSeconds(-1);
largeScreenTrainingDataModel.DataType = "今日";
}
else if (dateType == 2)
{
// 获取本周的开始和结束时间
int diff = (7 + (DateTime.Now.DayOfWeek - DayOfWeek.Monday)) % 7;
startTime = DateTime.Now.AddDays(-1 * diff).Date;
endTime = startTime.AddDays(7).AddSeconds(-1);
largeScreenTrainingDataModel.DataType = "本周";
}
else if (dateType == 3)
{
// 获取本月的开始和结束时间
startTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
endTime = startTime.AddMonths(1).AddSeconds(-1);
largeScreenTrainingDataModel.DataType = "本月";
}
else
{
return largeScreenTrainingDataModel;
}
// 从缓存中获取数据
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= startTime && x.ScoreTime <= endTime);
var testCategorys = sportsTestResults.Select(x => x.CategoryEnum).Distinct().ToList();
#region
// 训练次数
largeScreenTrainingDataModel.TrainingCount = sportsTestResults.Count();
// 上课节数
largeScreenTrainingDataModel.AttendClassCount = sportsTestResults.GroupBy(x => x.ClassRoomRecordId).Count();
// 上课时长
largeScreenTrainingDataModel.AttendClassDuration = sportsTestResults.Select(x => x.MotionDuration).Sum();
// 赛事参与人数
var activitiestDatas = await (from ad in _gradeRepository.DbContext.Set<Ai_ActivitiestData>()
join a in _gradeRepository.DbContext.Set<G_Activities>() on ad.ActivitiesId equals a.Id into activitiesDto
from a in activitiesDto.DefaultIfEmpty()
where a.SchoolCode == tenantId && a.StartDate >= startTime &&
a.EndDate <= endTime && a.ActivitiesStatus == ActivitiesStatus.Completed
select ad).ToListAsync();
largeScreenTrainingDataModel.EventParticipationBodCount = activitiestDatas.GroupBy(x => x.StudentNo).Count();
// 项目测试人数
largeScreenTrainingDataModel.ProjectTestingBodCount = sportsTestResults.GroupBy(x => x.StudentNo).Count();
#endregion
#region (//AI赛事//)
// 运动人数
largeScreenTrainingDataModel.AccumulatedTrainCount = sportsTestResults.GroupBy(x => x.StudentNo).Count();
// 平均跳绳次数跳绳个数少于10个不计算在内
var sportsTestCategorys = await _sportsTestCategoryRepository
.FindAsIQueryable(x => x.StatisticType >= 0 && testCategorys.Contains(x.CategoryEnum))
.Select(x => new SportsTestCategoryModel()
{
Id = x.Id,
CategoryEnum = x.CategoryEnum,
CategoryName = x.CategoryName,
StatisticType = x.StatisticType,
IsRopeSkip = x.IsRopeSkip
}).ToListAsync();
var ropeSkipCategorys = sportsTestCategorys.Where(x => x.IsRopeSkip).Select(x => x.CategoryEnum).ToList();
var avgRopeSkips = sportsTestResults.Where(x => x.CategoryValue.Equals((int)SportsTestItemType.OneMinuteJumpRope) && ropeSkipCategorys.Contains(x.CategoryEnum)).ToList();
largeScreenTrainingDataModel.AvgRopeSkipCount = avgRopeSkips.Count > 0 ? (int)avgRopeSkips.Where(x => x.Value > 10).Average(x => x.Value) : 0;
// 平均运动强度
largeScreenTrainingDataModel.AvgStrength = sportsTestResults.Count > 0 ? (int)sportsTestResults.Average(x => x.Strength) : 0;
// 运动时长
largeScreenTrainingDataModel.MotionDuration = sportsTestResults.Select(x => x.MotionDuration).Sum();
// 平均心率
//var avgHeartRates = sportsTestResults.Where(x => x.CategoryEnum.Equals("HeartRate")).ToList();
largeScreenTrainingDataModel.AvgHeartRate = sportsTestResults.Count > 0 ? (int)sportsTestResults.Average(x => x.Value) : 0;
// 平均消耗
largeScreenTrainingDataModel.AvgConsume = sportsTestResults.Count > 0 ? (int)sportsTestResults.Average(x => x.Consumption) : 0;
#endregion
return largeScreenTrainingDataModel;
}
/// <summary>
/// 大屏体测情况(体质健康监控)
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<TestSituations> GetLargeScreenTestSituations(LargeScreenDataStatParam paramDto)
{
var testSituations = new TestSituations();
var tenantId = UserContext.Current.TenantId;
// 从缓存中获取数据
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(
x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime
);
// 获取年级关联的分类
var categoryList = await (from s in _classRepository.DbContext.Set<S_GradeAssocCategory>()
join n in _classRepository.DbContext.Set<N_SportsTestCategory>()
on s.CategoryValue equals n.CategoryValue
select new
{
s.GradeId,
s.CategoryValue,
n.CategoryName,
s.Weight
}).ToListAsync();
// 将 categoryList 转换为嵌套字典,外层键为 GradeId内层键为 CategoryValue
var gradeCategoryDictionary = categoryList
.GroupBy(c => c.GradeId)
.ToDictionary(
g => g.Key,
g => g.ToDictionary(c => c.CategoryValue, c => c)
);
// 按学生分组,计算每个学生的总分和等级
var studentScores = sportsTestResults
.GroupBy(x => x.StudentNo)
.Select(g =>
{
var gradeId = g.First().GradeId;
// 计算总分
double totalScore = 0;
totalScore = g.Sum(x =>
{
if (gradeCategoryDictionary.TryGetValue(gradeId, out var categoryByGrade) &&
categoryByGrade.TryGetValue(x.CategoryValue, out var category))
{
decimal score = (decimal)(x.Score + x.AdditionalScore);
decimal value = score * (decimal)category.Weight;
return (double)value;
}
return 0;
});
return new
{
StudentNo = g.Key,
Sex = g.First().Sex,
TotalScore = totalScore,
Rank = totalScore.GetRank()
};
})
.ToList();
// 定义等级列表
var rankValues = new List<string> { "优秀", "良好", "及格", "不及格" };
// 计算每个等级的人数(总人数、男生人数、女生人数)
var rankStats = rankValues.ToDictionary(
rank => rank,
rank => new
{
Count = studentScores.Count(x => x.Rank == rank),
MaleCount = studentScores.Count(x => x.Sex == SexType.Male && x.Rank == rank),
FemaleCount = studentScores.Count(x => x.Sex == SexType.Female && x.Rank == rank)
}
);
// 计算总人数
float totalCount = studentScores.Count;
// 计算每个等级的原始百分比(保留小数)
var rawRankPercentages = rankStats.ToDictionary(
rank => rank.Key,
rank => (totalCount == 0) ? 0 : (rank.Value.Count / totalCount) * 100
);
// 对原始百分比进行取整操作
var rankPercentages = rawRankPercentages.ToDictionary(
rank => rank.Key,
rank => (int)Math.Floor(rank.Value)
);
// 计算取整后百分比的总和
int sum = rankPercentages.Values.Sum();
// 计算差值
int adjustment = 100 - sum;
// 如果差值不为 0按原始百分比大小顺序分配调整值
if (adjustment != 0)
{
// 按原始百分比降序排序
var sortedRanks = rawRankPercentages
.OrderByDescending(r => r.Value)
.Select(r => r.Key)
.ToList();
// 依次分配调整值
foreach (var rank in sortedRanks)
{
if (adjustment > 0)
{
rankPercentages[rank]++;
adjustment--;
}
else
{
break;
}
}
}
// 处理不及格率为 0 但有不及格人数的情况
if (rankPercentages["不及格"] == 0 && rankStats["不及格"].Count > 0)
{
rankPercentages["不及格"] = 1;
// 按比例最大的等级依次减 1%
var sortedRanks = rankPercentages
.OrderByDescending(r => r.Value)
.Select(r => r.Key)
.ToList();
foreach (var rank in sortedRanks)
{
if (rankPercentages[rank] > 0)
{
rankPercentages[rank]--;
break;
}
}
}
// 构建 TestSituation 列表
var testSituationList = rankValues.Select(rank => new TestSituation
{
Title = $"{rank}率",
Value = rankPercentages[rank],
MaleCount = rankStats[rank].MaleCount,
FemaleCount = rankStats[rank].FemaleCount
}).ToList();
// 计算优秀率和良好率的总和
var excellentAndGoodRates = testSituationList
.Where(x => x.Title == "优秀率" || x.Title == "良好率")
.ToList();
testSituations.ExcellentRate = excellentAndGoodRates.Sum(x => x.Value);
testSituations.ExcellentCount = excellentAndGoodRates.Sum(x => x.MaleCount + x.FemaleCount);
// 填充 TestSituationsData
testSituations.TestSituationsData = testSituationList;
return testSituations;
}
/// <summary>
/// 获取视力统计数据
/// </summary>
/// <param name="paramDto">查询参数</param>
/// <returns>左右眼统计数据</returns>
public async Task<List<SportsProportionData>> GetLargeScreenDicVisionSituation(LargeScreenDataStatParam paramDto)
{
var sportsProportionDataList = new List<SportsProportionData>();
// 获取指定时间范围内的视力记录
var visionData = await _sportsTestCategoryRepository.DbContext.Set<N_VisionData>()
.Where(v => v.SchoolCode == UserContext.Current.TenantId)
.ToListAsync();
// 定义维度范围
var visionCategories = new List<(string Title, float Min, float Max)>
{
("正常", float.MinValue, 50), // 正常 (<50°)
("轻度", 50, 300), // 轻度 (50-300°)
("中度", 300, 600), // 中度 (300-600°)
("高度", 600, float.MaxValue) // 高度 (>600°)
};
// 左右眼统计
var leftEyeStats = new List<StudentSportsProportionData>();
var rightEyeStats = new List<StudentSportsProportionData>();
foreach (var category in visionCategories)
{
// 左眼统计
var leftCount = visionData
.Count(v => v.VisionLeft >= category.Min && v.VisionLeft < category.Max);
leftEyeStats.Add(new StudentSportsProportionData
{
Title = category.Title,
Value = leftCount
});
// 右眼统计
var rightCount = visionData
.Count(v => v.VisionReight >= category.Min && v.VisionReight < category.Max);
rightEyeStats.Add(new StudentSportsProportionData
{
Title = category.Title,
Value = rightCount
});
}
// 组装结果
sportsProportionDataList.Add(new SportsProportionData
{
Name = "右眼",
Datas = rightEyeStats
});
sportsProportionDataList.Add(new SportsProportionData
{
Name = "左眼",
Datas = leftEyeStats
});
return sportsProportionDataList;
}
/// <summary>
/// 大屏肥胖情况
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<List<SportsProportionData>> GetLargeScreenObesitySituation(LargeScreenDataStatParam paramDto)
{
var sportsProportionDataList = new List<SportsProportionData>();
var tenantId = UserContext.Current.TenantId;
// 从缓存中获取数据
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.CategoryEnum != null && x.Rank != null && x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
var obesityTitles = new List<string>() { "偏瘦", "正常", "超重", "肥胖" };
var m_Obesity = new List<StudentSportsProportionData>();
var f_Obesity = new List<StudentSportsProportionData>();
foreach (var title in obesityTitles)
{
var maleCount = sportsTestResults.Where(x => x.Sex == SexType.Male && x.CategoryEnum.Equals("BMI") && x.Rank.Equals(title)).Count();
var femaleCount = sportsTestResults.Where(x => x.Sex == SexType.Female && x.CategoryEnum.Equals("BMI") && x.Rank.Equals(title)).Count();
if (m_Obesity.Any(c => c.Title == title) || f_Obesity.Any(c => c.Title == title))
{
m_Obesity.First().Value += maleCount;
f_Obesity.First().Value += femaleCount;
}
else
{
m_Obesity.Add(new StudentSportsProportionData()
{
Title = title,
Value = maleCount,
});
f_Obesity.Add(new StudentSportsProportionData()
{
Title = title,
Value = femaleCount,
});
}
}
sportsProportionDataList.Add(new SportsProportionData() { Name = "男", Datas = m_Obesity });
sportsProportionDataList.Add(new SportsProportionData() { Name = "女", Datas = f_Obesity });
return sportsProportionDataList;
}
/// <summary>
/// 大屏赛事活动情况
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<ActivitiesSituation> GetLargeScreenActivitiesSituation(LargeScreenDataStatParam paramDto)
{
var activitiesSituation = new ActivitiesSituation();
var tenantId = UserContext.Current.TenantId;
// 从缓存中获取数据
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
var activities = await _gradeRepository.DbContext.Set<G_Activities>().Where(x => x.SchoolCode == tenantId).ToListAsync();
activitiesSituation.ActivitiesTotalCount = activities.Count();
activitiesSituation.CompletedCount = activities.Where(x => x.ActivitiesStatus == ActivitiesStatus.Completed).Count();
activitiesSituation.AfootCount = activities.Where(x => x.ActivitiesStatus == ActivitiesStatus.Afoot).Count();
activitiesSituation.NotStartedCount = activities.Where(x => x.ActivitiesStatus == ActivitiesStatus.NotStarted).Count();
activitiesSituation.ParticipationRate = activitiesSituation.ActivitiesTotalCount > 0 ? activitiesSituation.CompletedCount / activitiesSituation.ActivitiesTotalCount * 100 : 0;
return activitiesSituation;
}
/// <summary>
/// 大屏体质监测排行榜
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<List<PhysicalMonitoring>> GetLargeScreenPhysicalMonitoringRanking(LargeScreenDataStatParam paramDto)
{
var physicalMonitoringList = new List<PhysicalMonitoring>();
var tenantId = UserContext.Current.TenantId;
// 获取所有班级信息
var classList = await _classRepository.DbContext.Set<S_Class>()
.Where(x => x.SchoolCode == tenantId)
.ToListAsync();
var classIds = classList.Select(c => c.Id).ToList();
// 获取体测成绩
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x =>
x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime &&
classIds.Contains(x.ClassId)
);
// 获取年级关联的分类
var categoryList = await (from s in _classRepository.DbContext.Set<S_GradeAssocCategory>()
join n in _classRepository.DbContext.Set<N_SportsTestCategory>()
on s.CategoryValue equals n.CategoryValue
select new
{
s.CategoryValue,
n.CategoryName,
s.Weight,
s.GradeId
}).ToListAsync();
// 计算每个学生的总分
var studentScores = sportsTestResults
.GroupBy(x => x.StudentNo)
.Select(g => new
{
StudentNo = g.Key,
ClassId = g.First().ClassId,
GradeId = g.First().GradeId,
ClassName = g.First().ClassName,
GradeName = g.First().GradeName,
Sex = g.First().Sex,
TotalScore = g.Sum(x => (x.Score + x.AdditionalScore) *
(categoryList.FirstOrDefault(c => c.GradeId == g.First().GradeId && c.CategoryValue == x.CategoryValue)?.Weight ?? 0))
})
.ToList();
// 计算每个班级的优良率
var classRankings = studentScores
.GroupBy(x => new { x.ClassId, x.GradeId, x.ClassName, x.GradeName })
.Select(g => new
{
GradeAndClassName = $"{g.Key.GradeName}-{g.Key.ClassName}",
MaleValue = (float)g.Count(x => x.Sex == SexType.Male && x.TotalScore >= 80) / g.Count() * 100,
FemaleValue = (float)g.Count(x => x.Sex == SexType.Female && x.TotalScore >= 80) / g.Count() * 100,
OverallValue = (float)g.Count(x => x.TotalScore >= 80) / g.Count() * 100
})
.OrderByDescending(g => g.OverallValue)
.Select((g, index) => new PhysicalMonitoring
{
GradeAndClassName = g.GradeAndClassName,
ExcellentRate = Math.Round(g.OverallValue),
Ranking = index + 1
})
.ToList();
// 处理未参与统计的班级
var allClasses = classList.Select(c => $"{c.GradeName}-{c.ClassName}").ToList();
var rankedClasses = classRankings.Select(c => c.GradeAndClassName).ToList();
var unrankedClasses = allClasses.Except(rankedClasses).ToList();
var ranking = classRankings.Count + 1;
foreach (var className in unrankedClasses)
{
classRankings.Add(new PhysicalMonitoring
{
GradeAndClassName = className,
ExcellentRate = 0,
Ranking = ranking++
});
}
return classRankings;
}
/// <summary>
/// 大屏 年级体测项目成绩监控
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<List<GradeSportsTestTranscript>> GetLargeScreenGradeSportsTestTranscript(LargeScreenDataStatParam paramDto)
{
var gradeSportsTestTranscriptList = new List<GradeSportsTestTranscript>();
var tenantId = UserContext.Current.TenantId;
// 从缓存中获取数据
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
// 年级-班级信息
var gradeClassQuery = from g in _classRepository.DbContext.Set<S_Grade>()
join a in _classRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
where a.SchoolCode == tenantId
select new
{
GradeId = g.Id,
GradeAndClassName = $"{g.GradeName}",
};
var gradeCategory = await (
from g in _gradeRepository.DbContext.Set<S_GradeAssocCategory>()
join s in _gradeRepository.DbContext.Set<N_SportsTestCategory>() on g.CategoryValue equals s.CategoryValue
select new
{
GradeId = g.GradeId,
CategoryId = g.CategoryValue,
CategoryName = s.CategoryName,
}).ToListAsync();
var gradeClassModels = await gradeClassQuery.ToListAsync();
var sportsTestList = sportsTestResults.GroupBy(x => new { x.GradeId, x.GradeName }).OrderBy(g => g.Key.GradeId).ToList();
foreach (var gradeClass in gradeClassModels)
{
var sportsProportionDataList = new List<SportsProportionData>();
var sportsTest = sportsTestList.FirstOrDefault(s => s.Key.GradeId == gradeClass.GradeId);
foreach (var type in gradeCategory.Where(c => c.GradeId == gradeClass.GradeId).OrderBy(c => c.CategoryId))
{
var typeSportsTestResults = sportsTest != null ? sportsTest.Where(x => x.CategoryValue == type.CategoryId).ToList() : new List<SportsTestValueModel>();
// 计算平均值
var maleAverage = typeSportsTestResults.Where(x => x.Sex == SexType.Male).Any()
? typeSportsTestResults.Where(x => x.Sex == SexType.Male).Average(x => x.Score)
: 0;
var femaleAverage = typeSportsTestResults.Where(x => x.Sex == SexType.Female).Any()
? typeSportsTestResults.Where(x => x.Sex == SexType.Female).Average(x => x.Score)
: 0;
var sumAverage = typeSportsTestResults.Any() ? typeSportsTestResults.Average(x => x.Score) : 0;
var studentSportsProportionData = new List<StudentSportsProportionData>
{
new StudentSportsProportionData { Title = "总分数", Value = (int)sumAverage },
new StudentSportsProportionData { Title = "男生", Value = (int)maleAverage },
new StudentSportsProportionData { Title = "女生", Value = (int)femaleAverage }
};
sportsProportionDataList.Add(new SportsProportionData
{
Name = type.CategoryName,
Datas = studentSportsProportionData
});
}
gradeSportsTestTranscriptList.Add(new GradeSportsTestTranscript()
{
GradeAndClassName = gradeClass.GradeAndClassName,
Datas = sportsProportionDataList
});
}
return gradeSportsTestTranscriptList;
}
/// <summary>
/// 大屏 班级平均运动强度监控
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<List<SportsProportionData>> LargeScreenAverageClassExerciseIntensity(LargeScreenAverageClassExerciseIntensityParam paramDto)
{
if (paramDto.GradeId < 0 || paramDto.StartTime == DateTime.MinValue || paramDto.EndTime == DateTime.MinValue)
{
throw new Exception($"请求参数不可为空");
}
var sportsProportionDataList = new List<SportsProportionData>();
var tenantId = UserContext.Current.TenantId;
// 从缓存中获取数据
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.GradeId == paramDto.GradeId && x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
// 班级信息
var classQuery = from c in _classRepository.DbContext.Set<S_Class>()
join g in _classRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
join a in _classRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
where a.SchoolCode == tenantId && c.SchoolCode == tenantId && g.Id == paramDto.GradeId
select c;
var classModels = await classQuery.ToListAsync();
if (classModels == null || classModels.Count == 0)
throw new ArgumentNullException("未找到班级数据");
var totalStrength = sportsTestResults.Any() ? sportsTestResults.Select(x => x.Strength).Average(x => x) : 0;
var classGroups = sportsTestResults.Any() ? sportsTestResults.GroupBy(c => new { c.ClassId, c.ClassName }).ToList() : null;
foreach (var classModel in classModels)
{
var classGroup = classGroups?.FirstOrDefault(c => c.Key.ClassId == classModel.Id && c.Key.ClassName == classModel.ClassName);
if (classGroup != null)
{
// 计算该班级的平均强度
var averageStrength = classGroup.Select(x => x.Strength).Average(x => x);
var percentage = averageStrength == 0 ? 0 : (averageStrength / totalStrength) * 100;
var studentSportsProportionData = new List<StudentSportsProportionData>
{
new StudentSportsProportionData { Title = "平均强度", Value =((int)Math.Round(percentage) > 100 ? 100 : (int)Math.Round(percentage)) }
};
sportsProportionDataList.Add(new SportsProportionData
{
Name = classGroup.Key.ClassName,
Datas = studentSportsProportionData
});
}
else
{
var studentSportsProportionData = new List<StudentSportsProportionData>
{
new StudentSportsProportionData { Title = "平均强度", Value = 0 }
};
sportsProportionDataList.Add(new SportsProportionData
{
Name = classModel.ClassName,
Datas = studentSportsProportionData
});
}
}
return sportsProportionDataList;
}
#endregion
public async Task<PageDataDto<StudentsTestDataModel>> GetSportsTestCategoryPageList(StudentsTestDataListParam paramDto)
{
var res = new PageDataDto<StudentsTestDataModel>();
var query = from r in _healthStandardsRepository.DbContext.Set<N_SportsTestValue>()
join c in _healthStandardsRepository.DbContext.Set<N_SportsTestCategory>() on r.CategoryEnum equals c.CategoryEnum
where r.SchoolCode.Equals(UserContext.Current.TenantId)
select new StudentsTestDataModel()
{
Id = r.Id,
GradeId = r.Id,
GradeName = r.GradeName,
StudentNo = r.StudentNo,
CategoryName = c.CategoryName,
ClassId = r.ClassId,
ClassName = r.ClassName,
ClassRank = r.ClassRank,
Consumption = r.Consumption,
MotionDuration = r.MotionDuration,
Strength = r.Strength,
TeacherId = r.TeacherId,
Remarks = r.Remarks,
Value = r.Value,
Rank = r.Rank,
CategoryId = c.Id,
Score = r.Score,
Sex = r.Sex == SexType.Male ? "男" : "女"
};
if (!string.IsNullOrWhiteSpace(paramDto.StudentNo))
{
query = query.Where(x => x.StudentNo.Equals(paramDto.StudentNo));
}
if (paramDto.TeacherId > 0)
{
query = query.Where(x => x.TeacherId == paramDto.TeacherId);
}
if (paramDto.GradeId > 0)
{
query = query.Where(x => x.GradeId == paramDto.GradeId);
}
if (paramDto.ClassId > 0)
{
query = query.Where(x => x.ClassId == paramDto.ClassId);
}
if (paramDto.CategoryId > 0)
{
query = query.Where(x => x.CategoryId == paramDto.CategoryId);
}
if (paramDto.Sex > 0)
{
query = query.Where(x => x.Sex.Equals(paramDto.Sex == SexType.Male ? "男" : "女"));
}
res.Total = await query.CountAsync();
var list = await query
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
.Take(paramDto.PageSize)
.ToListAsync();
res.Datas = list;
return res;
}
public async Task<List<StudentsTestDataModel>> GetStudentsTestDataList(StudentsTestDataListParam paramDto)
{
var query = from r in _healthStandardsRepository.DbContext.Set<N_SportsTestValue>()
join c in _healthStandardsRepository.DbContext.Set<N_SportsTestCategory>() on r.CategoryEnum equals c.CategoryEnum
where r.SchoolCode.Equals(UserContext.Current.TenantId)
select new StudentsTestDataModel()
{
Id = r.Id,
GradeId = r.Id,
GradeName = r.GradeName,
StudentNo = r.StudentNo,
CategoryName = c.CategoryName,
ClassId = r.ClassId,
ClassName = r.ClassName,
ClassRank = r.ClassRank,
Consumption = r.Consumption,
MotionDuration = r.MotionDuration,
Strength = r.Strength,
TeacherId = r.TeacherId,
Remarks = r.Remarks,
Value = r.Value,
Rank = r.Rank,
CategoryId = c.Id,
Score = r.Score,
Sex = r.Sex == SexType.Male ? "男" : "女"
};
if (!string.IsNullOrWhiteSpace(paramDto.StudentNo))
{
query = query.Where(x => x.StudentNo.Equals(paramDto.StudentNo));
}
if (paramDto.TeacherId > 0)
{
query = query.Where(x => x.TeacherId == paramDto.TeacherId);
}
if (paramDto.GradeId > 0)
{
query = query.Where(x => x.GradeId == paramDto.GradeId);
}
if (paramDto.ClassId > 0)
{
query = query.Where(x => x.ClassId == paramDto.ClassId);
}
if (paramDto.CategoryId > 0)
{
query = query.Where(x => x.CategoryId == paramDto.CategoryId);
}
if (paramDto.Sex > 0)
{
query = query.Where(x => x.Sex.Equals(paramDto.Sex == SexType.Male ? "男" : "女"));
}
var list = await query.ToListAsync();
return list;
}
public async Task AddStudentsTestData(List<AddStudentsTestDataParam> paramDto)
{
var studentNos = paramDto.Select(x => x.StudentNo).Distinct().ToList();
var students = await (from s in _studentRepository.DbContext.Set<S_Student>()
join c in _studentRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id
join g in _studentRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
where g.SchoolCode.Equals(UserContext.Current.TenantId)
select new
{
Id = s.Id,
Age = s.Age,
ClassId = s.ClassId,
ClassName = c.ClassName,
GradeId = g.Id,
GradeName = g.GradeName,
Sex = s.Sex,
StudentNo = s.StudentNo,
}).ToListAsync();
var distinctCategoryTypes = paramDto.Select(c => c.CategoryEnum).Distinct().ToList();
var healthStandards = await _healthStandardsRepository.FindAsync(x => distinctCategoryTypes.Contains(x.CategoryEnum));
var entityList = new List<N_SportsTestValue>();
var timeNow = DateTime.Now;
foreach (var data in paramDto)
{
var entity = _mapper.Map<N_SportsTestValue>(data);
var student = students.FirstOrDefault(x => x.StudentNo.Equals(data.StudentNo));
if (student == null)
throw new Exception($"未找到此编号为{data.StudentNo}的学生");
var standard = healthStandards.Where(x =>
x.CategoryEnum.Equals(data.CategoryEnum) &&
x.GradeId == student.GradeId &&
x.Sex == student.Sex &&
data.Value >= x.MinValue &&
data.Value < x.MaxValue
).FirstOrDefault();
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
entity.GradeId = student.GradeId;
entity.ClassId = student.ClassId;
entity.GradeName = student.GradeName;
entity.ClassName = student.ClassName;
entity.Sex = student.Sex;
entity.Creator = UserContext.Current.UserId;
entity.CreateDate = timeNow;
entityList.Add(entity);
}
await _sportsTestResultRepository.AddRangeAsync(entityList);
await _sportsTestResultRepository.SaveChangesAsync();
var ranks = await _sportsTestResultRepository.FindAsIQueryable(x => distinctCategoryTypes.Contains(x.CategoryEnum))
.Select(x => x.Score)
.Distinct()
.OrderByDescending(value => value)
.ToListAsync();
foreach (var entity in entityList)
{
if (entity.Score > 0)
{
entity.ClassRank = ranks.IndexOf(entity.Score) + 1;
}
}
_sportsTestResultRepository.UpdateRange(entityList);
await _sportsTestResultRepository.SaveChangesAsync();
}
public async Task ModifyStudentsTestData(List<AddStudentsTestDataParam> paramDto)
{
var studentNos = paramDto.Select(x => x.StudentNo).Distinct().ToList();
var entityList = await _sportsTestResultRepository.FindAsync(x => studentNos.Contains(x.StudentNo));
var distinctCategoryTypes = paramDto.Select(c => c.CategoryEnum).Distinct().ToList();
var healthStandards = await _healthStandardsRepository.FindAsync(x => distinctCategoryTypes.Contains(x.CategoryEnum));
var timeNow = DateTime.Now;
foreach (var data in paramDto)
{
var entity = entityList.FirstOrDefault(x => x.StudentNo.Equals(data.StudentNo));
if (entity == null)
throw new Exception($"未找到要更新的数据");
entity = _mapper.Map<N_SportsTestValue>(data);
var standard = healthStandards.Where(x =>
x.CategoryEnum.Equals(data.CategoryEnum) &&
x.GradeId == entity.GradeId &&
x.Sex == entity.Sex &&
data.Value >= x.MinValue &&
data.Value < x.MaxValue
).FirstOrDefault();
if (standard != null)
{
entity.Score = standard.Score;
entity.Rank = standard.Rank;
}
entity.Modifier = UserContext.Current.UserId;
entity.ModifyDate = timeNow;
entityList.Add(entity);
}
_sportsTestResultRepository.UpdateRange(entityList);
await _sportsTestResultRepository.SaveChangesAsync();
var ranks = await _sportsTestResultRepository.FindAsIQueryable(x => distinctCategoryTypes.Contains(x.CategoryEnum))
.Select(x => x.Score)
.Distinct()
.OrderByDescending(value => value)
.ToListAsync();
foreach (var entity in entityList)
{
if (entity.Score > 0)
{
entity.ClassRank = ranks.IndexOf(entity.Score) + 1;
}
}
_sportsTestResultRepository.UpdateRange(entityList);
await _sportsTestResultRepository.SaveChangesAsync();
}
public async Task DeleteStudentsTestData(List<int> Ids)
{
var model = await _sportsTestResultRepository.FindAsync(x => Ids.Contains(x.Id));
if (model == null)
throw new ArgumentNullException($"未找到删除的数据");
_sportsTestResultRepository.DbContext.RemoveRange(model);
await _sportsTestResultRepository.SaveChangesAsync();
}
/// <summary>
/// 获取学期
/// </summary>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <returns></returns>
public List<SemesterModel> CalculateSemesters(DateTime startDate, DateTime endDate)
{
List<SemesterModel> semesters = new List<SemesterModel>();
// 每年分为上学期和下学期
for (int year = startDate.Year; year <= endDate.Year; year++)
{
// 计算每个学期的开始和结束时间
DateTime springStart = new DateTime(year, 1, 1); // 上学期开始时间(春季学期)
DateTime springEnd = new DateTime(year, 6, 30); // 上学期结束时间(春季学期)
DateTime autumnStart = new DateTime(year, 9, 1); // 下学期开始时间(秋季学期)
DateTime autumnEnd = new DateTime(year, 12, 31); // 下学期结束时间(秋季学期)
// 对于每个学期,如果它部分或完全在范围内,都算作一个完整学期
if (startDate <= springEnd && endDate >= springStart)
{
semesters.Add(new SemesterModel
{
Semester = $"{year - 1}~{year}下学期",
StartTime = springStart.ToString("yyyy-MM-dd"),
EndTime = springEnd.ToString("yyyy-MM-dd")
});
}
if (startDate <= autumnEnd && endDate >= autumnStart)
{
semesters.Add(new SemesterModel
{
Semester = $"{year - 1}~{year}上学期",
StartTime = autumnStart.ToString("yyyy-MM-dd"),
EndTime = autumnEnd.ToString("yyyy-MM-dd")
});
}
}
return semesters;
}
//获取跳绳附加分
public int GetRopeSkipAdditionalScore(string gender, int score)
{
Dictionary<string, Dictionary<int, int>> genderScoreToAdditionalPoints = new Dictionary<string, Dictionary<int, int>>()
{
{ "男", new Dictionary<int, int>()
{
{ 20, 40 },
{ 19, 38 },
{ 18, 36 },
{ 17, 34 },
{ 16, 32 },
{ 15, 30 },
{ 14, 28 },
{ 13, 26 },
{ 12, 24 },
{ 11, 22 },
{ 10, 20 },
{ 9, 18 },
{ 8, 16 },
{ 7, 14 },
{ 6, 12 },
{ 5, 10 },
{ 4, 8 },
{ 3, 6 },
{ 2, 4 },
{ 1, 2 }
}
},
{ "女", new Dictionary<int, int>()
{
{ 20, 40 },
{ 19, 38 },
{ 18, 36 },
{ 17, 34 },
{ 16, 32 },
{ 15, 30 },
{ 14, 28 },
{ 13, 26 },
{ 12, 24 },
{ 11, 22 },
{ 10, 20 },
{ 9, 18 },
{ 8, 16 },
{ 7, 14 },
{ 6, 12 },
{ 5, 10 },
{ 4, 8 },
{ 3, 6 },
{ 2, 4 },
{ 1, 2 }
}
}
};
var scoreToAdditionalPoints = genderScoreToAdditionalPoints[gender];
return scoreToAdditionalPoints[score];
}
//获取引体向上和仰卧起坐附加分
public int GetPullUpSitUpsAdditionalScore(string gender, int score)
{
Dictionary<string, Dictionary<int, int>> genderScoreToAdditionalPoints = new Dictionary<string, Dictionary<int, int>>()
{
{ "男", new Dictionary<int, int>()
{
{ 10, 10 },
{ 9, 9 },
{ 8, 8 },
{ 7, 7 },
{ 6, 6 },
{ 5, 5 },
{ 4, 4 },
{ 3, 3 },
{ 2, 2 },
{ 1, 1 }
}
},
{ "女", new Dictionary<int, int>()
{
{ 10, 13 },
{ 9, 12 },
{ 8, 11 },
{ 7, 10 },
{ 6, 9 },
{ 5, 8 },
{ 4, 7 },
{ 3, 6 },
{ 2, 4 },
{ 1, 2 }
}
}
};
var scoreToAdditionalPoints = genderScoreToAdditionalPoints[gender];
return scoreToAdditionalPoints[score];
}
//获取跑步附加分
public int GetRunAdditionalScore(string gender, int score)
{
Dictionary<string, Dictionary<int, int>> genderScoreToAdditionalPoints = new Dictionary<string, Dictionary<int, int>>()
{
{ "男", new Dictionary<int, int>()
{
{ 10, 35 },
{ 9, 32 },
{ 8, 29 },
{ 7, 26 },
{ 6, 23 },
{ 5, 20 },
{ 4, 16 },
{ 3, 12 },
{ 2, 8 },
{ 1, 4 }
}
},
{ "女", new Dictionary<int, int>()
{
{ 10, 50 },
{ 9, 45 },
{ 8, 40 },
{ 7, 35 },
{ 6, 30 },
{ 5, 25 },
{ 4, 20 },
{ 3, 15 },
{ 2, 10 },
{ 1, 5 }
}
}
};
var scoreToAdditionalPoints = genderScoreToAdditionalPoints[gender];
return scoreToAdditionalPoints[score];
}
}
}