using YD_Event.Application.Arrangement.Dtos; using YD_Event.Core.Entities; using MiniExcelLibs; using SqlSugar; namespace YD_Event.Application.Arrangement; /// /// 赛事编排服务 /// public class EventArrangementService : ITransient { private readonly ISqlSugarRepository _projectRepository; private readonly ISqlSugarRepository _groupRepository; private readonly ISqlSugarRepository _personRepository; private readonly ISqlSugarRepository _registrationRepository; public EventArrangementService( ISqlSugarRepository projectRepository, ISqlSugarRepository groupRepository, ISqlSugarRepository personRepository, ISqlSugarRepository registrationRepository) { _projectRepository = projectRepository; _groupRepository = groupRepository; _personRepository = personRepository; _registrationRepository = registrationRepository; } /// /// 获取编排项目列表 /// [DisplayName("获取编排项目列表")] public async Task> GetList(long eventId) { var projects = await _projectRepository.GetListAsync(x => x.EventId == eventId); projects = projects.OrderBy(x => x.SortIndex).ToList(); var groups = await _groupRepository.GetListAsync(x => projects.Select(p => p.Id).Contains(x.ProjectId)); // 统计各组别报名人数(仅统计已支付或审核通过的) var counts = await _personRepository.AsQueryable() .InnerJoin((p, r) => p.RegistrationId == r.Id) .Where((p, r) => r.EventId == eventId && (r.PaymentStatus == 1 || r.RegistrationStatus == 2)) .GroupBy(p => new { p.ProjectId, p.GroupName }) .Select(p => new { p.ProjectId, p.GroupName, Count = SqlFunc.AggregateCount(p.Id) }) .ToListAsync(); var result = new List(); foreach (var proj in projects) { var dto = new ArrangementProjectListOutput { ProjectId = proj.Id, ProjectName = proj.ProjectName, ProjectType = $"{proj.ProjectMainType}-{proj.ProjectSubType}", DurationSeconds = proj.DurationSeconds, VenueCount = proj.VenueCount, SortIndex = proj.SortIndex, Groups = new List() }; var projGroups = groups.Where(g => g.ProjectId == proj.Id).ToList(); foreach (var group in projGroups) { var countObj = counts.FirstOrDefault(c => c.ProjectId == proj.Id && c.GroupName == group.GroupName); dto.Groups.Add(new ArrangementGroupDto { GroupName = group.GroupName, ParticipantCount = countObj?.Count ?? 0 }); } // 估算总时长 int venueCount = proj.VenueCount > 0 ? proj.VenueCount : 1; int totalParticipants = dto.Groups.Sum(g => g.ParticipantCount); int rounds = (int)Math.Ceiling((double)totalParticipants / venueCount); dto.TotalDurationMinutes = (rounds * proj.DurationSeconds) / 60; result.Add(dto); } return result; } /// /// 更新编排设置 /// [UnitOfWork] [DisplayName("更新编排设置")] public async Task Update(ArrangementUpdateInput input) { foreach (var setting in input.Settings) { await _projectRepository.UpdateAsync(x => new EventProject { VenueCount = setting.VenueCount, SortIndex = setting.SortIndex }, x => x.Id == setting.ProjectId); } } /// /// 编排预览 /// [DisplayName("编排预览")] public async Task> Preview(long eventId) { // 1. 获取项目(按顺序) var projects = await _projectRepository.GetListAsync(x => x.EventId == eventId); projects = projects.OrderBy(x => x.SortIndex).ToList(); var result = new List(); // 2. 生成排期 foreach (var proj in projects) { int venueCount = proj.VenueCount > 0 ? proj.VenueCount : 1; // 获取参赛人员(排序:组别 -> ID) var persons = await _personRepository.AsQueryable() .InnerJoin((p, r) => p.RegistrationId == r.Id) .Where((p, r) => p.ProjectId == proj.Id && (r.PaymentStatus == 1 || r.RegistrationStatus == 2)) .OrderBy(p => p.GroupName) .OrderBy(p => p.Id) .Select((p, r) => new { p.Name, p.GroupName, r.TeamName, Duration = proj.DurationSeconds }) .ToListAsync(); if (!persons.Any()) continue; // 分组逻辑 int currentRound = 1; int currentVenue = 1; foreach (var person in persons) { result.Add(new ArrangementPreviewOutput { TimeRange = $"{proj.DurationSeconds}''", ProjectName = proj.ProjectName, GroupName = person.GroupName, TeamName = person.TeamName, AthleteName = person.Name, SessionIndex = currentRound, VenueIndex = currentVenue }); currentVenue++; if (currentVenue > venueCount) { currentVenue = 1; currentRound++; } } } return result; } /// /// 导出编排 /// [DisplayName("导出编排")] public async Task Export(long eventId) { var data = await Preview(eventId); using var stream = new MemoryStream(); stream.SaveAs(data); return stream.ToArray(); } }