using System; using System.Threading.Tasks; using AutoMapper; using CSRedis; using Microsoft.EntityFrameworkCore; using YD_WeChatApplet.Api.SmartSportsEntitys; using YD_WeChatApplet.Api.Utilities; using YD_WeChatApplet.Commons.Dto; using YD_WeChatApplet.Commons.Dto.ClassRoomRecord; using YD_WeChatApplet.Commons.Dto.HomeWork; using YD_WeChatApplet.Commons.Dto.SportsTest; using YD_WeChatApplet.Commons.Dto.Teacher; using YD_WeChatApplet.Context; namespace YD_WeChatApplet.Services { public class TeacherService : ITeacherService { public UserContext _userContext; public SmartSportsContext _sportsContext; private readonly IMapper _mapper; public TeacherService(UserContext userContext, SmartSportsContext sportsContext, IMapper mapper) { _userContext = userContext; _sportsContext = sportsContext; _mapper = mapper; } /// /// 老师个人信息 /// /// public async Task TeacherProfile() { var userId = UserLoginContext.Current.UserId; var res = await _userContext.Users.Where(x => x.User_Id == userId).Select(x => new TeacherProfileDto() { UserTrueName = x.UserTrueName, BirthDate = x.BirthDate, Gender = x.Gender, HeadImageUrl = x.HeadImageUrl, Height = x.Height, Weight = x.Weight }).FirstOrDefaultAsync(); return res; } /// /// 修改个人信息 /// /// /// public async Task ModifyTeacherProfile(TeacherProfileDto paramDto) { var userId = UserLoginContext.Current.UserId; var model = await _userContext.Users.FirstOrDefaultAsync(x => x.User_Id == userId); if (model == null) throw new Exception("更新数据为空"); model.UserTrueName = !string.IsNullOrWhiteSpace(paramDto.UserTrueName) ? paramDto.UserTrueName : model.UserTrueName; model.HeadImageUrl = !string.IsNullOrWhiteSpace(paramDto.HeadImageUrl) ? paramDto.HeadImageUrl : model.HeadImageUrl; model.BirthDate = paramDto.BirthDate ?? model.BirthDate; model.Gender = paramDto.Gender ?? model.Gender; model.Height = paramDto.Height ?? model.Height; model.Weight = paramDto.Weight ?? model.Weight; if (_userContext.Entry(model).State == EntityState.Modified) { await _userContext.SaveChangesAsync(); } } /// /// 修改密码 /// /// /// public async Task ModifyTeacherPwd(ModifyTeacherPwdDto paramDto) { if (paramDto.NewPwd != paramDto.ConfirmPwd) throw new Exception("确认密码与新密码不一致"); var userId = UserLoginContext.Current.UserId; var model = await _userContext.Users.FirstOrDefaultAsync(x => x.User_Id == userId && x.UserPwd == paramDto.OldPwd); if (model == null) throw new Exception("旧密码输入有误"); model.UserPwd = paramDto.NewPwd; if (_userContext.Entry(model).State == EntityState.Modified) { _userContext.Update(model); await _userContext.SaveChangesAsync(); } } /// /// 项目列表 /// /// public async Task> CategoryList(int gradeId) { var res = await ( from g in _sportsContext.GradeAssocCategory join s in _sportsContext.SportsTestCategory on g.CategoryValue equals s.CategoryValue where g.GradeId == gradeId select new ComboBoxDto { Id = s.CategoryValue, Name = s.CategoryName }).ToListAsync(); return res; } /// /// 数据统计接口 /// /// /// /// public async Task DataStatistics(DataStatisticsFilterDto dto) { var res = new DataStatisticsDto(); var schoolCode = UserLoginContext.Current.SchoolCode; var teacherId = await _sportsContext.Teacher.Where(x => x.TeacherPhoneNo == UserLoginContext.Current.PhoneNo).Select(x => x.Id).FirstOrDefaultAsync(); if (teacherId == 0) return res; var students = await (from a in _sportsContext.ClassAssocTeacher join s in _sportsContext.Student on a.ClassId equals s.ClassId where a.TeacherId == teacherId && s.SchoolCode == schoolCode select new { s.StudentNo, s.Photo }).Distinct().ToListAsync(); res.HeadTotal = students.Count; var currentDate = DateTime.Now; var startOfMonth = new DateTime(currentDate.Year, currentDate.Month, 6); var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1); // 构建基础查询 //IQueryable iotQuery = _sportsContext.SportsTestValue // .Where(x => x.IsDisplay && x.SchoolCode == schoolCode && x.ScoreTime >= startOfMonth && x.ScoreTime <= endOfMonth); //IQueryable aiQuery = _sportsContext.SportsTestData // .Where(x => x.IsDisplay && x.SchoolCode == schoolCode && x.ScoreTime >= startOfMonth && x.ScoreTime <= endOfMonth); IQueryable iotQuery = _sportsContext.SportsTestValue.Where(x => x.IsDisplay && x.SchoolCode == schoolCode); //IQueryable aiQuery = _sportsContext.SportsTestData.Where(x => x.IsDisplay && x.SchoolCode == schoolCode); // 动态追加筛选条件 if (dto.ClassId > 0) { iotQuery = iotQuery.Where(x => x.ClassId == dto.ClassId); //aiQuery = aiQuery.Where(x => x.ClassId == dto.ClassId); } if (dto.CategoryValue > 0) { iotQuery = iotQuery.Where(x => x.CategoryValue == dto.CategoryValue); //aiQuery = aiQuery.Where(x => x.CategoryValue == dto.CategoryValue); } //if (!string.IsNullOrWhiteSpace(dto.Rank)) //{ // iotQuery = iotQuery.Where(x => x.Rank == dto.Rank); // aiQuery = aiQuery.Where(x => x.Rank == dto.Rank); //} // 并行执行查询 var iotTask = await iotQuery.ToListAsync(); //var aiTask = await aiQuery.ToListAsync(); // 映射并合并结果 //var sportsTestResults = _mapper.Map>(iotTask) // .Concat(_mapper.Map>(aiTask)) // .ToList(); var sportsTestResults = _mapper.Map>(iotTask); sportsTestResults = sportsTestResults .GroupBy(x => new { x.StudentNo }) .Select(g => { var latestRecord = g.OrderByDescending(x => x.Score).First(); //var latestRecord = g.Where(x => x.ScoreTime >= startOfMonth && x.ScoreTime <= endOfMonth).OrderByDescending(x => x.Score).First(); //latestRecord.Score = g.Max(x => x.Score); //latestRecord.Value = g.Max(x => x.Value); return latestRecord; }).ToList(); if (!string.IsNullOrWhiteSpace(dto.Rank)) { sportsTestResults = sportsTestResults.Where(x => x.Rank == dto.Rank).ToList(); } res.RankDic.Add("优秀", sportsTestResults.Count(x => x.Rank == "优秀")); res.RankDic.Add("良好", sportsTestResults.Count(x => x.Rank == "良好")); res.RankDic.Add("及格", sportsTestResults.Count(x => x.Rank == "及格")); res.RankDic.Add("不及格", sportsTestResults.Count(x => x.Rank == "不及格")); res.Studentlist = new Commons.Dto.PageDataDto() { Total = sportsTestResults.Count, Datas = sportsTestResults.Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).Select(x => new StatisticsStudent() { StudentNo = x.StudentNo, StudentName = x.StudentName, Sex = x.Sex, Photo = students.FirstOrDefault(x => x.StudentNo == x.StudentNo)?.Photo ?? "", }).ToList() }; return res; } /// /// 统计数据详情 /// /// /// /// public async Task DataStatisticsDetails(DataStatisticsDetailsFilterDto dto) { var res = new DataStatisticsDetailsDto(); var student = await _sportsContext.Student.Where(x => x.StudentNo == dto.StudentNo).FirstOrDefaultAsync(); var classInfo = await _sportsContext.Class.FirstOrDefaultAsync(x => x.Id == dto.ClassId); var categorys = await ( from g in _sportsContext.GradeAssocCategory join s in _sportsContext.SportsTestCategory on g.CategoryValue equals s.CategoryValue where g.GradeId == classInfo.GradeId select new { s.Id, s.CategoryValue, s.CategoryName, g.Weight }).ToListAsync(); if (student == null || categorys == null) return res; var iotQuery = await _sportsContext.SportsTestValue.Where(x => x.IsDisplay && x.SchoolCode == student.SchoolCode && x.StudentNo == dto.StudentNo).Select(x => new SportsTestValueModel() { StudentNo = x.StudentNo, Value = x.Value, Score = x.Score, AdditionalScore = x.AdditionalScore, CategoryValue = x.CategoryValue, Rank = x.Rank }).ToListAsync(); var aiQuery = await _sportsContext.SportsTestData.Where(x => x.IsDisplay && x.SchoolCode == student.SchoolCode && x.StudentNo == dto.StudentNo).Select(x => new SportsTestValueModel() { StudentNo = x.StudentNo, Value = (float)x.Value, Score = x.Score, AdditionalScore = x.AdditionalScore, CategoryValue = x.CategoryValue, Rank = x.Rank }).ToListAsync(); var sportsTestResults = iotQuery.Concat(aiQuery).ToList(); res.StudentNo = student.StudentNo; res.StudentName = student.StudentName; res.Sex = student.Sex == 1 ? "男" : "女"; res.Age = student.Age; res.Photo = student.Photo; res.CategoryScoreList = new List(); double totalScore = 0; foreach (var item in categorys) { var maxResult = sportsTestResults.Where(x => x.CategoryValue == item.Id).OrderByDescending(x => x.Value).FirstOrDefault(); res.CategoryScoreList.Add(new CategoryScore() { CategoryName = item.CategoryName, Value = maxResult != null ? Math.Round((double)maxResult.Value, 0) : 0, Score = maxResult?.Score ?? 0, Rank = maxResult?.Rank ?? "" }); double currentScore = maxResult?.Score ?? 0; double currentAdditionalScore = maxResult?.AdditionalScore ?? 0; // 累积分数 totalScore += ((currentScore + currentAdditionalScore) * item.Weight); } res.ComprehensiveScore = totalScore.ToString("F0"); return res; } /// /// 课堂记录 /// /// /// public async Task> ClassRoomRecord(ClassRoomRecordDto dto) { var res = new PageDataDto(); if (string.IsNullOrWhiteSpace(dto.StudentNo)) { var phoneNo = UserLoginContext.Current.PhoneNo; var teacherId = await _sportsContext.Teacher.Where(x => x.TeacherPhoneNo == phoneNo).Select(x => x.Id).FirstOrDefaultAsync(); var query = from td in _sportsContext.Ai_ClassRoomRecord where td.TeacherId == teacherId select new ClassRoomRecordPageDto() { Id = td.Id, ClassId = td.ClassId, Name = td.Name, StartingEndingTime = $"{(td.StartTime.HasValue ? td.StartTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}{(td.EndTime.HasValue ? " - " + td.EndTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}" }; res.Total = await query.CountAsync(); var list = await query .OrderByDescending(c => c.Id) .Skip((dto.PageIndex - 1) * dto.PageSize) .Take(dto.PageSize) .ToListAsync(); res.Datas = list; } else { var query = from s in _sportsContext.Ai_ClassroomStudentRecord join c in _sportsContext.Ai_ClassRoomRecord on s.ClassRoomRecordId equals c.Id where s.StudentName == dto.StudentNo select new ClassRoomRecordPageDto() { Id = c.Id, ClassId = c.ClassId, Name = c.Name, StartingEndingTime = $"{(c.StartTime.HasValue ? c.StartTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}{(c.EndTime.HasValue ? " - " + c.EndTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}" }; res.Total = await query.CountAsync(); var list = await query .OrderByDescending(c => c.Id) .Skip((dto.PageIndex - 1) * dto.PageSize) .Take(dto.PageSize) .ToListAsync(); res.Datas = list; } return res; } /// /// 课堂详情 /// /// /// public async Task ClassRoomReportDetails(int classRoomId) { var res = new ClassReportDetailsDto(); var query = from hrd in _sportsContext.Ai_HeartRateData where hrd.ClassRoomRecordId == classRoomId select hrd; var heartRateDataList = await query.ToListAsync(); if (heartRateDataList.Count == 0) return res; var classRoom = await _sportsContext.Ai_ClassRoomRecord.Include(x => x.ClassroomStudentRecord) .Where(x => x.Id == classRoomId) .FirstAsync(); var classRoomStudent = await _sportsContext.Ai_ClassroomStudentRecord .Where(x => x.ClassRoomRecordId == classRoomId) .ToListAsync(); res.MaxHR = (int)heartRateDataList.Max(x => x.Value); res.MinHR = (int)heartRateDataList.Min(x => x.Value); res.AvgHR = (int)heartRateDataList.Average(x => x.Value); res.HighIntensity = heartRateDataList.Where(x => x.Strength > 50).Sum(x => x.MotionDuration); var studentTrainingRecordList = classRoom.ClassroomStudentRecord.ToList(); List studentList = new List(); foreach (var item in studentTrainingRecordList) { var studentTrainingData = heartRateDataList.Where(x => x.StudentNo == item.StudentNo).ToList(); if (studentTrainingData.Count > 0) { var student = new StudentTrainingRecordDto() { StudentNo = item.StudentNo, Age = item.Age, Sex = item.Sex }; student.StudentName = studentTrainingData[0].StudentName; studentList.Add(student); } } res.HeartRateTrend = GetHeartRateTrend(heartRateDataList); res.StudentTrainingRecordList = studentList; return res; } /// /// 学员报告 /// /// /// /// public async Task StudentClassRoomReport(int classRoomId, string studentNo) { var res = new StudentClassRoomReportDto(); var query = from hrd in _sportsContext.Ai_HeartRateData where hrd.ClassRoomRecordId == classRoomId && hrd.StudentNo == studentNo select hrd; var heartRateDataList = await query.ToListAsync(); if (heartRateDataList.Count == 0) return res; var student = heartRateDataList[0]; res.MaxHR = (int)heartRateDataList.Max(x => x.Value); res.MinHR = (int)heartRateDataList.Min(x => x.Value); res.AvgHR = (int)heartRateDataList.Average(x => x.Value); res.HighIntensity = heartRateDataList.Where(x => x.Strength > 50).Sum(x => x.MotionDuration); var baseTime = await _sportsContext.Ai_HeartRateData.Where(x => x.ClassRoomRecordId == classRoomId).MinAsync(x => x.ScoreTime); var heartRateWithMinutes = heartRateDataList .Select(data => new { Data = data, MinuteBucket = (int)(data.ScoreTime - baseTime).TotalMinutes }) .ToList(); var maxMinute = heartRateWithMinutes.Max(x => x.MinuteBucket); for (int minute = 0; minute <= maxMinute; minute++) { var minuteData = heartRateWithMinutes .Where(x => x.MinuteBucket == minute) .Select(x => x.Data) .ToList(); if (minuteData.Any()) { res.HeartRateTrend.AxisX.Add($"{minute + 1} 分钟"); res.HeartRateTrend.AxisY.Add((int)minuteData.Average(x => x.Value)); } } return res; } /// /// 心率变化趋势 /// /// /// public ChartDataDto GetHeartRateTrend(List heartRateDataList) { var result = new ChartDataDto(); if (heartRateDataList == null || !heartRateDataList.Any()) return result; var baseTime = heartRateDataList.Min(x => x.ScoreTime); var heartRateWithMinutes = heartRateDataList .Select(data => new { Data = data, MinuteBucket = (int)(data.ScoreTime - baseTime).TotalMinutes }) .ToList(); var maxMinute = heartRateWithMinutes.Max(x => x.MinuteBucket); for (int minute = 0; minute <= maxMinute; minute++) { var minuteData = heartRateWithMinutes .Where(x => x.MinuteBucket == minute) .Select(x => x.Data) .ToList(); if (minuteData.Any()) { result.AxisX.Add($"{minute + 1} 分钟"); result.AxisY.Add((int)minuteData.Average(x => x.Value)); } } return result; } } }