fix: 修复generateInitialScheduleResult方法,根据maxParticipants拆分单人项目分组
- 当单人项目参赛人数超过maxParticipants时,自动拆分成多个分组 - 添加createSingleGroup辅助方法 - 修复Issue #1: 编排分组算法使用错误字段导致分组数计算不准确 Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 参赛人员DTO
|
||||
@@ -52,4 +54,10 @@ public class ParticipantDTO implements Serializable {
|
||||
@Schema(description = "选手姓名")
|
||||
private String playerName;
|
||||
|
||||
/**
|
||||
* 队员列表(集体项目)
|
||||
*/
|
||||
@Schema(description = "队员列表(集体项目)")
|
||||
private List<Map<String, Object>> members;
|
||||
|
||||
}
|
||||
|
||||
+35
-1
@@ -49,6 +49,8 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang
|
||||
private final MartialScheduleDetailMapper scheduleDetailMapper;
|
||||
private final MartialScheduleParticipantMapper scheduleParticipantMapper;
|
||||
private final MartialAthleteMapper athleteMapper;
|
||||
private final MartialTeamMapper teamMapper;
|
||||
private final MartialTeamMemberMapper teamMemberMapper;
|
||||
private final MartialCompetitionMapper competitionMapper;
|
||||
private final MartialVenueMapper venueMapper;
|
||||
private final MartialProjectMapper projectMapper;
|
||||
@@ -213,7 +215,7 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang
|
||||
List<MartialScheduleParticipant> participants = scheduleParticipantMapper.selectList(participantWrapper);
|
||||
|
||||
if (group.getProjectType() == 2) {
|
||||
// 集体项目:按单位分组
|
||||
// 集体项目:按单位分组,并获取队员列表
|
||||
Map<String, List<MartialScheduleParticipant>> orgGroupMap = participants.stream()
|
||||
.collect(Collectors.groupingBy(MartialScheduleParticipant::getOrganization));
|
||||
|
||||
@@ -225,7 +227,39 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang
|
||||
List<Map<String, Object>> orgParticipants = new ArrayList<>();
|
||||
for (MartialScheduleParticipant p : entry.getValue()) {
|
||||
Map<String, Object> pData = new HashMap<>();
|
||||
pData.put("id", p.getParticipantId());
|
||||
pData.put("playerName", p.getPlayerName());
|
||||
pData.put("schoolUnit", p.getOrganization());
|
||||
|
||||
// 查询队伍信息和队员列表
|
||||
String teamName = p.getPlayerName();
|
||||
LambdaQueryWrapper<MartialTeam> teamWrapper = new LambdaQueryWrapper<>();
|
||||
teamWrapper.eq(MartialTeam::getTeamName, teamName)
|
||||
.eq(MartialTeam::getIsDeleted, 0)
|
||||
.last("LIMIT 1");
|
||||
MartialTeam team = teamMapper.selectOne(teamWrapper);
|
||||
|
||||
List<Map<String, Object>> memberList = new ArrayList<>();
|
||||
if (team != null) {
|
||||
// 获取队员列表
|
||||
LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
|
||||
memberWrapper.eq(MartialTeamMember::getTeamId, team.getId())
|
||||
.eq(MartialTeamMember::getIsDeleted, 0);
|
||||
List<MartialTeamMember> members = teamMemberMapper.selectList(memberWrapper);
|
||||
|
||||
for (MartialTeamMember member : members) {
|
||||
// 获取队员详情
|
||||
MartialAthlete athlete = athleteMapper.selectById(member.getAthleteId());
|
||||
if (athlete != null) {
|
||||
Map<String, Object> memberData = new HashMap<>();
|
||||
memberData.put("id", athlete.getId());
|
||||
memberData.put("playerName", athlete.getPlayerName());
|
||||
memberData.put("organization", athlete.getOrganization());
|
||||
memberList.add(memberData);
|
||||
}
|
||||
}
|
||||
}
|
||||
pData.put("members", memberList);
|
||||
orgParticipants.add(pData);
|
||||
}
|
||||
orgGroup.put("participants", orgParticipants);
|
||||
|
||||
+108
-40
@@ -322,9 +322,10 @@ public class MartialScheduleServiceImpl extends ServiceImpl<MartialScheduleMappe
|
||||
Long defaultVenueId = venues.isEmpty() ? null : venues.get(0).getId();
|
||||
String defaultVenueName = venues.isEmpty() ? "未分配" : venues.get(0).getVenueName();
|
||||
|
||||
// 4. 为每个项目生成一个分组
|
||||
// 4. 为每个项目生成分组(单人项目根据maxParticipants拆分)
|
||||
List<CompetitionGroupDTO> groupDTOs = new ArrayList<>();
|
||||
int displayOrder = 0;
|
||||
long tempIdCounter = 1; // Counter for generating unique negative IDs for sub-groups
|
||||
|
||||
for (MartialProject project : projects) {
|
||||
List<MartialAthlete> projectAthletes = athletesByProject.getOrDefault(project.getId(), new ArrayList<>());
|
||||
@@ -334,66 +335,133 @@ public class MartialScheduleServiceImpl extends ServiceImpl<MartialScheduleMappe
|
||||
continue;
|
||||
}
|
||||
|
||||
CompetitionGroupDTO groupDTO = new CompetitionGroupDTO();
|
||||
// 使用负数ID表示这是临时生成的分组(未保存到数据库)
|
||||
groupDTO.setId(-project.getId());
|
||||
groupDTO.setProjectId(project.getId());
|
||||
groupDTO.setTitle(project.getProjectName() + " 未分组");
|
||||
groupDTO.setCode(project.getProjectCode());
|
||||
|
||||
// 设置类型
|
||||
// 判断项目类型
|
||||
Integer projectType = project.getType();
|
||||
String typeStr;
|
||||
if (projectType != null) {
|
||||
switch (projectType) {
|
||||
case 1:
|
||||
groupDTO.setType("单人");
|
||||
typeStr = "单人";
|
||||
break;
|
||||
case 2:
|
||||
groupDTO.setType("集体");
|
||||
break;
|
||||
case 3:
|
||||
groupDTO.setType("集体");
|
||||
typeStr = "集体";
|
||||
break;
|
||||
default:
|
||||
groupDTO.setType("其他");
|
||||
typeStr = "其他";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
groupDTO.setType("单人");
|
||||
typeStr = "单人";
|
||||
}
|
||||
|
||||
// 设置数量
|
||||
groupDTO.setCount(projectAthletes.size() + "人");
|
||||
|
||||
// 设置默认场地和时间段
|
||||
groupDTO.setVenueId(defaultVenueId);
|
||||
groupDTO.setVenueName(defaultVenueName);
|
||||
groupDTO.setTimeSlotIndex(0); // 默认放在第一个时间段
|
||||
groupDTO.setTimeSlot(null);
|
||||
|
||||
// 生成参赛者列表
|
||||
List<ParticipantDTO> participantDTOs = new ArrayList<>();
|
||||
int sortOrder = 1;
|
||||
for (MartialAthlete athlete : projectAthletes) {
|
||||
ParticipantDTO dto = new ParticipantDTO();
|
||||
dto.setId(athlete.getId());
|
||||
dto.setPlayerName(athlete.getPlayerName());
|
||||
dto.setSchoolUnit(athlete.getOrganization());
|
||||
dto.setTeamName(athlete.getTeamName());
|
||||
dto.setStatus("未签到");
|
||||
dto.setSortOrder(sortOrder++);
|
||||
participantDTOs.add(dto);
|
||||
// 单人项目:根据maxParticipants拆分
|
||||
if ("单人".equals(typeStr)) {
|
||||
Integer maxParticipants = project.getMaxParticipants();
|
||||
int athleteCount = projectAthletes.size();
|
||||
|
||||
// 如果maxParticipants有效且人数超过限制,需要拆分
|
||||
if (maxParticipants != null && maxParticipants > 0 && athleteCount > maxParticipants) {
|
||||
int numGroups = (int) Math.ceil((double) athleteCount / maxParticipants);
|
||||
log.info("项目 '{}' 有{}人,maxParticipants={},将拆分成{}组",
|
||||
project.getProjectName(), athleteCount, maxParticipants, numGroups);
|
||||
|
||||
for (int i = 0; i < numGroups; i++) {
|
||||
int startIdx = i * maxParticipants;
|
||||
int endIdx = Math.min(startIdx + maxParticipants, athleteCount);
|
||||
List<MartialAthlete> subGroupAthletes = projectAthletes.subList(startIdx, endIdx);
|
||||
|
||||
CompetitionGroupDTO groupDTO = new CompetitionGroupDTO();
|
||||
// 使用唯一的负数ID
|
||||
groupDTO.setId(-project.getId() - tempIdCounter++);
|
||||
groupDTO.setProjectId(project.getId());
|
||||
|
||||
// 如果只有一组,不加组号后缀
|
||||
if (numGroups == 1) {
|
||||
groupDTO.setTitle(project.getProjectName() + " 未分组");
|
||||
} else {
|
||||
groupDTO.setTitle(project.getProjectName() + " 第" + (i + 1) + "组");
|
||||
}
|
||||
groupDTO.setCode("C" + competitionId + "-P" + String.format("%03d", displayOrder + 1));
|
||||
groupDTO.setType(typeStr);
|
||||
groupDTO.setCount(subGroupAthletes.size() + "人");
|
||||
groupDTO.setVenueId(defaultVenueId);
|
||||
groupDTO.setVenueName(defaultVenueName);
|
||||
groupDTO.setTimeSlotIndex(0);
|
||||
groupDTO.setTimeSlot(null);
|
||||
|
||||
// 生成参赛者列表
|
||||
List<ParticipantDTO> participantDTOs = new ArrayList<>();
|
||||
int sortOrder = 1;
|
||||
for (MartialAthlete athlete : subGroupAthletes) {
|
||||
ParticipantDTO dto = new ParticipantDTO();
|
||||
dto.setId(athlete.getId());
|
||||
dto.setPlayerName(athlete.getPlayerName());
|
||||
dto.setSchoolUnit(athlete.getOrganization());
|
||||
dto.setTeamName(athlete.getTeamName());
|
||||
dto.setStatus("未签到");
|
||||
dto.setSortOrder(sortOrder++);
|
||||
participantDTOs.add(dto);
|
||||
}
|
||||
|
||||
groupDTO.setParticipants(participantDTOs);
|
||||
groupDTOs.add(groupDTO);
|
||||
displayOrder++;
|
||||
}
|
||||
} else {
|
||||
// 不需要拆分,生成单个分组
|
||||
CompetitionGroupDTO groupDTO = createSingleGroup(project, projectAthletes, typeStr,
|
||||
defaultVenueId, defaultVenueName, competitionId, displayOrder);
|
||||
groupDTOs.add(groupDTO);
|
||||
displayOrder++;
|
||||
}
|
||||
} else {
|
||||
// 集体项目:不拆分
|
||||
CompetitionGroupDTO groupDTO = createSingleGroup(project, projectAthletes, typeStr,
|
||||
defaultVenueId, defaultVenueName, competitionId, displayOrder);
|
||||
groupDTOs.add(groupDTO);
|
||||
displayOrder++;
|
||||
}
|
||||
|
||||
groupDTO.setParticipants(participantDTOs);
|
||||
groupDTOs.add(groupDTO);
|
||||
displayOrder++;
|
||||
}
|
||||
|
||||
result.setCompetitionGroups(groupDTOs);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建单个分组DTO
|
||||
*/
|
||||
private CompetitionGroupDTO createSingleGroup(MartialProject project, List<MartialAthlete> athletes,
|
||||
String typeStr, Long venueId, String venueName, Long competitionId, int displayOrder) {
|
||||
CompetitionGroupDTO groupDTO = new CompetitionGroupDTO();
|
||||
groupDTO.setId(-project.getId());
|
||||
groupDTO.setProjectId(project.getId());
|
||||
groupDTO.setTitle(project.getProjectName() + " 未分组");
|
||||
groupDTO.setCode("C" + competitionId + "-P" + String.format("%03d", displayOrder + 1));
|
||||
groupDTO.setType(typeStr);
|
||||
groupDTO.setCount(athletes.size() + "人");
|
||||
groupDTO.setVenueId(venueId);
|
||||
groupDTO.setVenueName(venueName);
|
||||
groupDTO.setTimeSlotIndex(0);
|
||||
groupDTO.setTimeSlot(null);
|
||||
|
||||
List<ParticipantDTO> participantDTOs = new ArrayList<>();
|
||||
int sortOrder = 1;
|
||||
for (MartialAthlete athlete : athletes) {
|
||||
ParticipantDTO dto = new ParticipantDTO();
|
||||
dto.setId(athlete.getId());
|
||||
dto.setPlayerName(athlete.getPlayerName());
|
||||
dto.setSchoolUnit(athlete.getOrganization());
|
||||
dto.setTeamName(athlete.getTeamName());
|
||||
dto.setStatus("未签到");
|
||||
dto.setSortOrder(sortOrder++);
|
||||
participantDTOs.add(dto);
|
||||
}
|
||||
|
||||
groupDTO.setParticipants(participantDTOs);
|
||||
return groupDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存编排草稿
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user