diff --git a/src/main/java/org/springblade/modules/martial/service/schedule/grouping/ParticipantGroupingService.java b/src/main/java/org/springblade/modules/martial/service/schedule/grouping/ParticipantGroupingService.java index 85b87db..78c5c83 100644 --- a/src/main/java/org/springblade/modules/martial/service/schedule/grouping/ParticipantGroupingService.java +++ b/src/main/java/org/springblade/modules/martial/service/schedule/grouping/ParticipantGroupingService.java @@ -124,74 +124,39 @@ public class ParticipantGroupingService { continue; } - // Get distinct team names - List teamNames = members.stream() + // For team projects, skip gender filter as validation is done at registration time + // Team athlete records do not have accurate gender info (they represent the team, not individual members) + // members = filterByCategory(members, project); + + long teamCount = members.stream() .map(MartialAthlete::getTeamName) - .filter(t -> t != null && !t.isEmpty()) + .filter(org -> org != null && !org.isEmpty()) .distinct() - .collect(Collectors.toList()); + .count(); - int teamCount = teamNames.size(); String projectName = project.getProjectName(); String categoryName = getProjectCategoryName(project); - // Calculate max teams per group (use maxParticipants as max teams) - int maxTeamsPerGroup = project.getMaxParticipants() != null && project.getMaxParticipants() > 0 - ? project.getMaxParticipants() : 10; + ScheduleGroupData group = ScheduleGroupData.builder() + .groupName(projectName + (categoryName.isEmpty() ? "" : " " + categoryName)) + .projectId(first.getProjectId()) + .projectType((project.getType() == 2 || project.getType() == 3) ? 2 : 1) + .maxParticipants(project.getMaxParticipants()) + .category(categoryName) + .displayOrder(displayOrder++) + .totalParticipants(members.size()) + .totalTeams((int) teamCount) + .athletes(members) + .build(); - int durationPerTeam = (project.getEstimatedDuration() != null && project.getEstimatedDuration() > 0) - ? project.getEstimatedDuration() : 5; - - if (teamCount <= maxTeamsPerGroup) { - // No need to split - single group - ScheduleGroupData group = ScheduleGroupData.builder() - .groupName(projectName + (categoryName.isEmpty() ? "" : " " + categoryName)) - .projectId(first.getProjectId()) - .projectType((project.getType() == 2 || project.getType() == 3) ? 2 : 1) - .maxParticipants(project.getMaxParticipants()) - .category(categoryName) - .displayOrder(displayOrder++) - .totalParticipants(members.size()) - .totalTeams(teamCount) - .athletes(members) - .estimatedDuration(teamCount * durationPerTeam + Math.max(0, teamCount - 1) * 2) - .build(); - groups.add(group); + int duration; + if (project.getEstimatedDuration() != null && project.getEstimatedDuration() > 0) { + duration = (int) teamCount * project.getEstimatedDuration(); } else { - // Split into multiple groups - int numGroups = (int) Math.ceil((double) teamCount / maxTeamsPerGroup); - - log.info("Team project {} {} has {} teams, splitting into {} groups (max {} per group)", - projectName, categoryName, teamCount, numGroups, maxTeamsPerGroup); - - for (int i = 0; i < numGroups; i++) { - int startIdx = i * maxTeamsPerGroup; - int endIdx = Math.min(startIdx + maxTeamsPerGroup, teamCount); - List subTeamNames = teamNames.subList(startIdx, endIdx); - - // Filter athletes belonging to teams in this sub-group - List subMembers = members.stream() - .filter(a -> subTeamNames.contains(a.getTeamName())) - .collect(Collectors.toList()); - - int subTeamCount = subTeamNames.size(); - - String groupSuffix = " 第" + (i + 1) + "组"; - ScheduleGroupData group = ScheduleGroupData.builder() - .groupName(projectName + " " + categoryName + groupSuffix) - .projectId(first.getProjectId()) - .projectType((project.getType() == 2 || project.getType() == 3) ? 2 : 1) - .maxParticipants(project.getMaxParticipants()) - .category(categoryName) - .displayOrder(displayOrder++) - .totalParticipants(subMembers.size()) - .totalTeams(subTeamCount) - .athletes(subMembers) - .estimatedDuration(subTeamCount * durationPerTeam + Math.max(0, subTeamCount - 1) * 2) - .build(); - groups.add(group); - } + duration = (int) teamCount * 5 + Math.max(0, (int) teamCount - 1) * 2; } + group.setEstimatedDuration(duration); + groups.add(group); } return displayOrder; } @@ -259,17 +224,16 @@ public class ParticipantGroupingService { int totalPeople = members.size(); int numSubGroups = (int) Math.ceil((double) totalPeople / maxPeoplePerGroup); - log.info("Individual project {} {} has {} people, splitting into {} groups (max {} per group)", - projectName, categoryName, totalPeople, numSubGroups, maxPeoplePerGroup); + log.info("Individual project '{}' has {} people, splitting into {} groups (max {} per group)", + projectName + " " + categoryName, totalPeople, numSubGroups, maxPeoplePerGroup); for (int i = 0; i < numSubGroups; i++) { int startIdx = i * maxPeoplePerGroup; int endIdx = Math.min(startIdx + maxPeoplePerGroup, totalPeople); List subGroupMembers = new ArrayList<>(members.subList(startIdx, endIdx)); - String groupSuffix = " 第" + (i + 1) + "组"; ScheduleGroupData group = ScheduleGroupData.builder() - .groupName(projectName + " " + categoryName + groupSuffix) + .groupName(projectName + " " + categoryName + " 第" + (i + 1) + "组") .projectId(project.getId()) .projectType(1) .maxParticipants(maxPeoplePerGroup)