|
|
@@ -187,7 +187,7 @@ public class XgDormBedStudentServiceImpl implements IXgDormBedStudentService {
|
|
|
Map<Long, String> roomCodeMap = rooms.stream()
|
|
|
.collect(java.util.stream.Collectors.toMap(XgDormRoom::getId, XgDormRoom::getRoomCode));
|
|
|
|
|
|
- // 4. 将床位按房间顺序排列,实现连续分配
|
|
|
+ // 4. 将床位按房间顺序排列,实现房间优先分配
|
|
|
// 按房间编码排序床位,确保同一房间的床位连续
|
|
|
List<XgDormBed> sortedBeds = beds.stream()
|
|
|
.sorted((b1, b2) -> {
|
|
|
@@ -203,10 +203,21 @@ public class XgDormBedStudentServiceImpl implements IXgDormBedStudentService {
|
|
|
})
|
|
|
.collect(java.util.stream.Collectors.toList());
|
|
|
|
|
|
- // 4. 按学院顺序分配床位
|
|
|
+ // 5. 按房间分组床位,实现房间优先分配策略
|
|
|
+ Map<Long, List<XgDormBed>> bedsByRoom = sortedBeds.stream()
|
|
|
+ .collect(java.util.stream.Collectors.groupingBy(XgDormBed::getRoomId));
|
|
|
+
|
|
|
+ // 获取排序后的房间ID列表
|
|
|
+ List<Long> sortedRoomIds = new ArrayList<>(bedsByRoom.keySet());
|
|
|
+ sortedRoomIds.sort((r1, r2) -> roomCodeMap.get(r1).compareTo(roomCodeMap.get(r2)));
|
|
|
+
|
|
|
+ // 6. 房间优先分配算法(四轮分配策略)
|
|
|
+ // 第一轮:优先分配完整房间给学院
|
|
|
+ // 第二轮:同学院学生补充到已分配房间
|
|
|
+ // 第三轮:分配到空闲房间(避免混住)
|
|
|
+ // 第四轮:分配剩余床位(允许混住,确保100%分配)
|
|
|
List<XgDormBedStudent> allocationRecords = new ArrayList<>();
|
|
|
Date now = new Date();
|
|
|
- int currentBedIndex = 0; // 当前分配到的床位索引
|
|
|
int totalBeds = sortedBeds.size();
|
|
|
|
|
|
// 如果没有提供学院人数信息,则平均分配
|
|
|
@@ -229,46 +240,116 @@ public class XgDormBedStudentServiceImpl implements IXgDormBedStudentService {
|
|
|
throw new RuntimeException("学院人数总和(" + totalStudents + ")与床位总数(" + totalBeds + ")不匹配");
|
|
|
}
|
|
|
|
|
|
- // 按学院顺序连续分配床位
|
|
|
+ // 房间使用状态跟踪
|
|
|
+ int[] roomUsage = new int[sortedRoomIds.size()]; // 记录每个房间已使用床位数
|
|
|
+ Map<Integer, Long> roomCollegeMap = new java.util.HashMap<>(); // 记录房间主要分配给哪个学院
|
|
|
+
|
|
|
+ // 按学院顺序,采用房间优先分配策略
|
|
|
for (int collegeIndex = 0; collegeIndex < bo.getCollegeIds().size(); collegeIndex++) {
|
|
|
Long collegeId = bo.getCollegeIds().get(collegeIndex);
|
|
|
- int studentCount = collegeCounts.get(collegeIndex);
|
|
|
+ int remainingStudents = collegeCounts.get(collegeIndex);
|
|
|
+
|
|
|
+ log.info("开始为学院{}分配{}个床位,采用房间优先策略", collegeId, remainingStudents);
|
|
|
+
|
|
|
+ // 第一轮:优先分配完整房间
|
|
|
+ for (int roomIndex = 0; roomIndex < sortedRoomIds.size() && remainingStudents > 0; roomIndex++) {
|
|
|
+ Long roomId = sortedRoomIds.get(roomIndex);
|
|
|
+ List<XgDormBed> roomBeds = bedsByRoom.get(roomId);
|
|
|
+ int roomCapacity = roomBeds.size();
|
|
|
+
|
|
|
+ // 如果房间空闲且学生数足够分配整个房间
|
|
|
+ if (roomUsage[roomIndex] == 0 && remainingStudents >= roomCapacity) {
|
|
|
+ // 分配整个房间给当前学院
|
|
|
+ allocateBedsToCollege(roomBeds, collegeId, allocationRecords, building, bo.getBuildingId(),
|
|
|
+ now);
|
|
|
+ roomUsage[roomIndex] = roomCapacity;
|
|
|
+ roomCollegeMap.put(roomIndex, collegeId);
|
|
|
+ remainingStudents -= roomCapacity;
|
|
|
+
|
|
|
+ log.info("为学院{}分配完整房间{},房间编码{},床位数{}",
|
|
|
+ collegeId, roomId, roomCodeMap.get(roomId), roomCapacity);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- log.info("开始为学院{}分配{}个床位,从第{}个床位开始", collegeId, studentCount, currentBedIndex + 1);
|
|
|
+ // 第二轮:处理剩余学生(优先分配到已有该学院学生的房间)
|
|
|
+ for (int roomIndex = 0; roomIndex < sortedRoomIds.size() && remainingStudents > 0; roomIndex++) {
|
|
|
+ Long roomId = sortedRoomIds.get(roomIndex);
|
|
|
+ List<XgDormBed> roomBeds = bedsByRoom.get(roomId);
|
|
|
+ int availableBeds = roomBeds.size() - roomUsage[roomIndex];
|
|
|
+
|
|
|
+ // 优先分配到已有该学院学生的房间
|
|
|
+ if (availableBeds > 0 && collegeId.equals(roomCollegeMap.get(roomIndex))) {
|
|
|
+ int bedsToAllocate = Math.min(remainingStudents, availableBeds);
|
|
|
+ List<XgDormBed> bedsToAssign = roomBeds.subList(roomUsage[roomIndex],
|
|
|
+ roomUsage[roomIndex] + bedsToAllocate);
|
|
|
+
|
|
|
+ allocateBedsToCollege(bedsToAssign, collegeId, allocationRecords, building, bo.getBuildingId(),
|
|
|
+ now);
|
|
|
+ roomUsage[roomIndex] += bedsToAllocate;
|
|
|
+ remainingStudents -= bedsToAllocate;
|
|
|
+
|
|
|
+ log.info("为学院{}在已分配房间{}补充{}个床位",
|
|
|
+ collegeId, roomId, bedsToAllocate);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 检查是否有足够的床位
|
|
|
- if (currentBedIndex + studentCount > totalBeds) {
|
|
|
- throw new RuntimeException("没有足够的床位分配给学院" + collegeId);
|
|
|
+ // 第三轮:如果还有剩余学生,分配到空闲房间(避免混住)
|
|
|
+ for (int roomIndex = 0; roomIndex < sortedRoomIds.size() && remainingStudents > 0; roomIndex++) {
|
|
|
+ Long roomId = sortedRoomIds.get(roomIndex);
|
|
|
+ List<XgDormBed> roomBeds = bedsByRoom.get(roomId);
|
|
|
+ int availableBeds = roomBeds.size() - roomUsage[roomIndex];
|
|
|
+
|
|
|
+ // 分配到完全空闲的房间
|
|
|
+ if (availableBeds > 0 && roomCollegeMap.get(roomIndex) == null) {
|
|
|
+ int bedsToAllocate = Math.min(remainingStudents, availableBeds);
|
|
|
+ List<XgDormBed> bedsToAssign = roomBeds.subList(roomUsage[roomIndex],
|
|
|
+ roomUsage[roomIndex] + bedsToAllocate);
|
|
|
+
|
|
|
+ allocateBedsToCollege(bedsToAssign, collegeId, allocationRecords, building, bo.getBuildingId(),
|
|
|
+ now);
|
|
|
+ roomUsage[roomIndex] += bedsToAllocate;
|
|
|
+ roomCollegeMap.put(roomIndex, collegeId);
|
|
|
+ remainingStudents -= bedsToAllocate;
|
|
|
+
|
|
|
+ log.info("为学院{}分配空闲房间{}的{}个床位",
|
|
|
+ collegeId, roomId, bedsToAllocate);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // 为当前学院连续分配指定数量的床位
|
|
|
- for (int i = 0; i < studentCount; i++) {
|
|
|
- XgDormBed bed = sortedBeds.get(currentBedIndex + i);
|
|
|
-
|
|
|
- // 创建分配记录
|
|
|
- XgDormBedStudent allocation = new XgDormBedStudent();
|
|
|
- allocation.setCollegeId(collegeId);
|
|
|
- allocation.setMajorId(null); // 没有数据就不填写,为空
|
|
|
- allocation.setClassId(null); // 没有数据就不填写,为空
|
|
|
- allocation.setStudentId(null); // 没有数据就不填写,为空
|
|
|
- allocation.setBedId(bed.getId());
|
|
|
- allocation.setRoomId(bed.getRoomId());
|
|
|
- allocation.setBuildingId(bo.getBuildingId());
|
|
|
- allocation.setAreaId(building.getAreaId()); // 从楼栋信息中获取宿舍区ID
|
|
|
- allocation.setCampusId(building.getCampusId()); // 从楼栋信息中获取校区ID
|
|
|
- allocation.setStatus("0"); // 0-正常
|
|
|
- allocation.setAssignTime(now);
|
|
|
- allocation.setCreateTime(now);
|
|
|
- allocation.setUpdateTime(now);
|
|
|
-
|
|
|
- allocationRecords.add(allocation);
|
|
|
+ // 第四轮:确保所有学生都能分配到床位(允许混住)
|
|
|
+ for (int roomIndex = 0; roomIndex < sortedRoomIds.size() && remainingStudents > 0; roomIndex++) {
|
|
|
+ Long roomId = sortedRoomIds.get(roomIndex);
|
|
|
+ List<XgDormBed> roomBeds = bedsByRoom.get(roomId);
|
|
|
+ int availableBeds = roomBeds.size() - roomUsage[roomIndex];
|
|
|
+
|
|
|
+ // 分配到任何有空闲床位的房间,即使会产生混住
|
|
|
+ if (availableBeds > 0) {
|
|
|
+ int bedsToAllocate = Math.min(remainingStudents, availableBeds);
|
|
|
+ List<XgDormBed> bedsToAssign = roomBeds.subList(roomUsage[roomIndex],
|
|
|
+ roomUsage[roomIndex] + bedsToAllocate);
|
|
|
+
|
|
|
+ allocateBedsToCollege(bedsToAssign, collegeId, allocationRecords, building, bo.getBuildingId(),
|
|
|
+ now);
|
|
|
+ roomUsage[roomIndex] += bedsToAllocate;
|
|
|
+ remainingStudents -= bedsToAllocate;
|
|
|
+
|
|
|
+ Long existingCollegeId = roomCollegeMap.get(roomIndex);
|
|
|
+ if (existingCollegeId != null && !existingCollegeId.equals(collegeId)) {
|
|
|
+ log.warn("房间{}产生混住:学院{}和学院{}",
|
|
|
+ roomCodeMap.get(roomId), existingCollegeId, collegeId);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("为学院{}分配房间{}的{}个床位(可能混住)",
|
|
|
+ collegeId, roomId, bedsToAllocate);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // 更新当前床位索引
|
|
|
- currentBedIndex += studentCount;
|
|
|
+ // 检查是否还有未分配的学生
|
|
|
+ if (remainingStudents > 0) {
|
|
|
+ throw new RuntimeException("学院" + collegeId + "还有" + remainingStudents + "个学生未能分配床位,床位资源不足");
|
|
|
+ }
|
|
|
|
|
|
- log.info("学院{}分配完成,分配了{}个床位,下次从第{}个床位开始",
|
|
|
- collegeId, studentCount, currentBedIndex + 1);
|
|
|
+ log.info("学院{}床位分配完成", collegeId);
|
|
|
}
|
|
|
|
|
|
// 6. 更新床位状态为已分配
|
|
|
@@ -297,4 +378,38 @@ public class XgDormBedStudentServiceImpl implements IXgDormBedStudentService {
|
|
|
throw new RuntimeException("床位分配失败:" + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将床位分配给学院的辅助方法
|
|
|
+ *
|
|
|
+ * @param beds 要分配的床位列表
|
|
|
+ * @param collegeId 学院ID
|
|
|
+ * @param allocationRecords 分配记录列表
|
|
|
+ * @param building 楼栋信息
|
|
|
+ * @param buildingId 楼栋ID
|
|
|
+ * @param now 当前时间
|
|
|
+ */
|
|
|
+ private void allocateBedsToCollege(List<XgDormBed> beds, Long collegeId,
|
|
|
+ List<XgDormBedStudent> allocationRecords,
|
|
|
+ XgDormBuilding building, Long buildingId, Date now) {
|
|
|
+ for (XgDormBed bed : beds) {
|
|
|
+ // 创建分配记录
|
|
|
+ XgDormBedStudent allocation = new XgDormBedStudent();
|
|
|
+ allocation.setCollegeId(collegeId);
|
|
|
+ allocation.setMajorId(null); // 没有数据就不填写,为空
|
|
|
+ allocation.setClassId(null); // 没有数据就不填写,为空
|
|
|
+ allocation.setStudentId(null); // 没有数据就不填写,为空
|
|
|
+ allocation.setBedId(bed.getId());
|
|
|
+ allocation.setRoomId(bed.getRoomId());
|
|
|
+ allocation.setBuildingId(buildingId);
|
|
|
+ allocation.setAreaId(building.getAreaId()); // 从楼栋信息中获取宿舍区ID
|
|
|
+ allocation.setCampusId(building.getCampusId()); // 从楼栋信息中获取校区ID
|
|
|
+ allocation.setStatus("0"); // 0-正常
|
|
|
+ allocation.setAssignTime(now);
|
|
|
+ allocation.setCreateTime(now);
|
|
|
+ allocation.setUpdateTime(now);
|
|
|
+
|
|
|
+ allocationRecords.add(allocation);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|