feat(schedule): split team projects into groups when exceeding maxParticipants
- Added splitTeamIntoSubGroups method for team project grouping - Team projects now split by maxParticipants (max teams per group) - Display format: projectName + category + 第X组 (when split) - Consistent with individual project grouping behavior Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
+51
-19
@@ -124,38 +124,70 @@ public class ParticipantGroupingService {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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(org -> org != null && !org.isEmpty())
|
||||
.distinct()
|
||||
.count();
|
||||
|
||||
String projectName = project.getProjectName();
|
||||
String categoryName = getProjectCategoryName(project);
|
||||
int maxTeamsPerGroup = (project.getMaxParticipants() != null && project.getMaxParticipants() > 0)
|
||||
? project.getMaxParticipants() : members.size();
|
||||
int durationPerTeam = (project.getEstimatedDuration() != null && project.getEstimatedDuration() > 0)
|
||||
? project.getEstimatedDuration() : 5;
|
||||
|
||||
// Team projects: each record in members represents one team
|
||||
int teamCount = members.size();
|
||||
|
||||
if (teamCount <= maxTeamsPerGroup) {
|
||||
// No need to split, create 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())
|
||||
.projectType(2)
|
||||
.maxParticipants(maxTeamsPerGroup)
|
||||
.category(categoryName)
|
||||
.displayOrder(displayOrder++)
|
||||
.totalParticipants(members.size())
|
||||
.totalTeams((int) teamCount)
|
||||
.totalTeams(teamCount)
|
||||
.athletes(members)
|
||||
.estimatedDuration(teamCount * durationPerTeam)
|
||||
.build();
|
||||
|
||||
int duration;
|
||||
if (project.getEstimatedDuration() != null && project.getEstimatedDuration() > 0) {
|
||||
duration = (int) teamCount * project.getEstimatedDuration();
|
||||
groups.add(group);
|
||||
} else {
|
||||
duration = (int) teamCount * 5 + Math.max(0, (int) teamCount - 1) * 2;
|
||||
// Split into sub-groups like individual projects
|
||||
displayOrder = splitTeamIntoSubGroups(members, project, projectName, categoryName,
|
||||
maxTeamsPerGroup, durationPerTeam, groups, displayOrder);
|
||||
}
|
||||
group.setEstimatedDuration(duration);
|
||||
}
|
||||
return displayOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split team project into sub-groups when team count exceeds maxParticipants
|
||||
*/
|
||||
private int splitTeamIntoSubGroups(List<MartialAthlete> members, MartialProject project,
|
||||
String projectName, String categoryName, int maxTeamsPerGroup,
|
||||
int durationPerTeam, List<ScheduleGroupData> groups, int displayOrder) {
|
||||
int totalTeams = members.size();
|
||||
int numSubGroups = (int) Math.ceil((double) totalTeams / maxTeamsPerGroup);
|
||||
|
||||
log.info("Team project '{}' has {} teams, splitting into {} groups (max {} per group)",
|
||||
projectName + " " + categoryName, totalTeams, numSubGroups, maxTeamsPerGroup);
|
||||
|
||||
for (int i = 0; i < numSubGroups; i++) {
|
||||
int startIdx = i * maxTeamsPerGroup;
|
||||
int endIdx = Math.min(startIdx + maxTeamsPerGroup, totalTeams);
|
||||
List<MartialAthlete> subGroupMembers = new ArrayList<>(members.subList(startIdx, endIdx));
|
||||
int subGroupTeamCount = subGroupMembers.size();
|
||||
|
||||
ScheduleGroupData group = ScheduleGroupData.builder()
|
||||
.groupName(projectName + " " + categoryName + " 第" + (i + 1) + "组")
|
||||
.projectId(project.getId())
|
||||
.projectType(2)
|
||||
.maxParticipants(maxTeamsPerGroup)
|
||||
.displayOrder(displayOrder++)
|
||||
.category(categoryName)
|
||||
.totalParticipants(subGroupMembers.size())
|
||||
.totalTeams(subGroupTeamCount)
|
||||
.athletes(subGroupMembers)
|
||||
.estimatedDuration(subGroupTeamCount * durationPerTeam)
|
||||
.build();
|
||||
groups.add(group);
|
||||
}
|
||||
return displayOrder;
|
||||
|
||||
Reference in New Issue
Block a user