优化时间: 2025-01-03
修改文件: backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBedStudentServiceImpl.java
修改方法: batchAllocateBedsToCollege
将床位分配逻辑从分散分配调整为房间优先分配,采用四轮分配策略:优先分配完整房间,尽量避免混住,但确保所有床位100%分配利用,提高宿舍管理效率。
❌ 问题:每次从不同房间各取一个床位分配给同一学院
- 房间1:床位1 → 学院A
- 房间2:床位1 → 学院A
- 房间3:床位1 → 学院A
- 房间4:床位1 → 学院A
- 房间1:床位2 → 学院A
...
结果:学院A的学生分散在所有房间
✅ 优化:优先分配完整房间,避免学院混住
- 房间1:床位1-8 → 学院A(8个)
- 房间2:床位1-2 → 学院A(2个)
- 房间3:床位1-8 → 学院B(8个)
- 房间4:床位1-7 → 学院C(7个)
...
结果:同一房间尽量安排同一学院学生,避免混住
场景: 4个房间,每个房间8个床位,总计32个床位
房间1(8个床位):学院A(床位1-8,完整房间)
房间2(8个床位):学院A(床位1-2,同学院补充)
房间3(8个床位):学院B(床位1-8,完整房间)
房间4(8个床位):学院C(床位1-7)+ 空余1个床位
剩余:学院D(7个)→ 需要新增房间或调整分配
🔴 避免的问题(连续分配):
房间2:学院A(床位1-2)+ 学院B(床位3-8)← 混住
房间3:学院B(床位1-2)+ 学院C(床位3-8)← 混住
✅ 实现的效果(房间优先):
房间2:学院A(床位1-2)← 同学院
房间3:学院B(床位1-8)← 完整房间
// 获取房间信息,建立roomId到roomCode的映射
Set<Long> roomIds = beds.stream().map(XgDormBed::getRoomId).collect(java.util.stream.Collectors.toSet());
List<XgDormRoom> rooms = xgDormRoomMapper.selectBatchIds(roomIds);
Map<Long, String> roomCodeMap = rooms.stream()
.collect(java.util.stream.Collectors.toMap(XgDormRoom::getId, XgDormRoom::getRoomCode));
// 将床位按房间顺序排列,实现连续分配
List<XgDormBed> sortedBeds = beds.stream()
.sorted((b1, b2) -> {
// 首先按房间编码排序
String roomCode1 = roomCodeMap.get(b1.getRoomId());
String roomCode2 = roomCodeMap.get(b2.getRoomId());
int roomCompare = roomCode1.compareTo(roomCode2);
if (roomCompare != 0) {
return roomCompare;
}
// 同一房间内按床位编码排序
return b1.getBedCode().compareTo(b2.getBedCode());
})
.collect(java.util.stream.Collectors.toList());
// 按房间分组床位
Map<Long, List<XgDormBed>> bedsByRoom = sortedBeds.stream()
.collect(java.util.stream.Collectors.groupingBy(XgDormBed::getRoomId));
// 房间使用状态跟踪
int[] roomUsage = new int[sortedRoomIds.size()];
Map<Integer, Long> roomCollegeMap = new HashMap<>();
for (每个学院) {
// 第一轮:优先分配完整房间
for (每个房间) {
if (房间空闲 && 学生数量 >= 房间容量) {
分配整个房间给当前学院;
}
}
// 第二轮:补充分配到已有该学院学生的房间
for (每个房间) {
if (房间有剩余床位 && 房间已分配给当前学院) {
分配剩余床位给当前学院;
}
}
// 第三轮:分配到空闲房间(避免混住)
for (每个房间) {
if (房间有剩余床位 && 房间完全空闲) {
分配床位给当前学院;
标记房间为当前学院所有;
}
}
// 第四轮:确保100%分配(允许混住)
for (每个房间) {
if (房间有剩余床位) {
分配剩余床位给当前学院;
记录混住警告信息;
}
}
}
/**
* 将床位分配给学院的辅助方法
*/
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.setBedId(bed.getId());
allocation.setRoomId(bed.getRoomId());
// ... 其他字段设置
allocationRecords.add(allocation);
}
}
新算法采用智能的四轮分配模式,平衡房间管理和床位利用率:
优点:房间管理简单
缺点:可能导致床位浪费,学生无床位分配
场景:床位充足时可行
优点:既尽量避免混住,又确保100%分配
缺点:少量房间可能产生混住
场景:适用于床位紧张的实际情况
输入:
- 房间数:4个,每个8床位
- 学院需求:[10, 8, 7, 7]
预期输出(房间优先策略):
- 房间1:学院A(全部8个,完整房间)
- 房间2:学院A(2个,同学院补充)
- 房间3:学院B(全部8个,完整房间)
- 房间4:学院C(7个)+ 空余1个
优势:避免了学院混住,每个房间最多只有一个学院
连续分配结果(会产生混住):
- 房间1:学院A(8个)
- 房间2:学院A(2个)+ 学院B(6个)← 混住
- 房间3:学院B(2个)+ 学院C(6个)← 混住
- 房间4:学院C(1个)+ 学院D(7个)← 混住
房间优先分配结果(避免混住):
- 房间1:学院A(8个)
- 房间2:学院A(2个)← 同学院
- 房间3:学院B(8个)
- 房间4:学院C(7个)+ 学院D(1个)
- 需要:为学院D新增房间分配剩余6个床位
输入:
- 床位数:1个
- 学院数:1个
- 学院需求:[1]
预期输出:
- 成功分配1个床位给学院1
📅 更新记录