Files
hzdyjs/docs/开发文档/床位分配逻辑优化说明.md
T
2025-08-13 08:28:48 +08:00

6.3 KiB
Raw Blame History

床位分配逻辑优化说明

📋 优化概述

优化时间: 2025-01-03
修改文件: backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgDormBedStudentServiceImpl.java
修改方法: batchAllocateBedsToCollege

🎯 优化目标

将床位分配逻辑从分散分配调整为连续分配,确保同一学院的学生尽量分配在相邻的房间或同一房间内,提高宿舍管理效率。

🔄 分配逻辑对比

原有逻辑(分散分配)

❌ 问题:每次从不同房间各取一个床位分配给同一学院
- 房间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个)
- 房间2:床位3-8 → 学院B(6个)  
- 房间3:床位1-2 → 学院B(2个)
- 房间3:床位3-8 → 学院C(6个)
...
结果:每个学院的学生相对集中

🎯 分配示例

场景: 4个房间,每个房间8个床位,总计32个床位

学院需求

  • 学院A:10个床位
  • 学院B:8个床位
  • 学院C:7个床位
  • 学院D:7个床位

分配结果

房间1(8个床位):学院A(床位1-8)
房间2(8个床位):学院A(床位1-2)+ 学院B(床位3-8)  
房间3(8个床位):学院C(床位1-7)+ 学院D(床位8)
房间4(8个床位):学院D(床位1-6)+ 空余2个床位

🔧 技术实现

核心算法改进

1. 床位排序

// 获取房间信息,建立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());

2. 连续分配算法

int currentBedIndex = 0; // 当前分配到的床位索引

for (int collegeIndex = 0; collegeIndex < bo.getCollegeIds().size(); collegeIndex++) {
    Long collegeId = bo.getCollegeIds().get(collegeIndex);
    int studentCount = collegeCounts.get(collegeIndex);
    
    // 为当前学院连续分配指定数量的床位
    for (int i = 0; i < studentCount; i++) {
        XgDormBed bed = sortedBeds.get(currentBedIndex + i);
        // 创建分配记录...
    }
    
    // 更新当前床位索引
    currentBedIndex += studentCount;
}

关键优化点

1. 索引管理

  • 原逻辑: 复杂的房间遍历和床位查找
  • 新逻辑: 简单的索引递增,O(1)时间复杂度

2. 内存效率

  • 原逻辑: 需要维护房间分组Map和动态删除操作
  • 新逻辑: 一次性排序,线性访问,内存占用更少

3. 分配可预测性

  • 原逻辑: 分配结果难以预测
  • 新逻辑: 分配结果完全可预测,便于调试和验证

4. 排序优化

  • 原逻辑: 按房间ID和床位ID排序,不符合物理布局
  • 新逻辑: 按房间编码(roomCode)和床位编码(bedCode)排序,符合实际物理顺序

📊 优化效果

宿舍管理优势

  1. 集中管理: 每个学院的学生相对集中,便于管理员统一管理
  2. 减少跨楼层: 学生活动和管理主要在相邻房间,减少跨楼层流动
  3. 便于统计: 学院相关的宿舍统计更加方便

学生体验优势

  1. 同学院聚集: 同学院学生住宿相对集中,便于学习和生活交流
  2. 减少陌生感: 周边多为同学院学生,归属感更强
  3. 便于组织活动: 学院活动组织更加便利

系统性能优势

  1. 算法效率: 时间复杂度从O(n²)降低到O(n log n)
  2. 内存占用: 减少临时数据结构,内存使用更高效
  3. 代码维护: 逻辑更清晰,便于理解和维护

🧪 测试验证

测试用例1:标准分配

输入:
- 房间数:4个,每个8床位
- 学院需求:[10, 8, 7, 7]

预期输出:
- 房间1:学院1(全部8个)
- 房间2:学院1(2个)+ 学院2(6个)
- 房间3:学院2(2个)+ 学院3(6个)
- 房间4:学院3(1个)+ 学院4(7个)

测试用例2:边界情况

输入:
- 床位数:1个
- 学院数:1个
- 学院需求:[1]

预期输出:
- 成功分配1个床位给学院1

📝 注意事项

开发注意点

  1. 排序稳定性: 确保相同房间内床位按编码顺序排列
  2. 索引边界: 严格检查数组边界,避免越界访问
  3. 事务安全: 分配过程中如有异常,确保数据回滚

业务规则

  1. 房间优先级: 按房间编码(roomCode)升序分配,确保分配顺序的一致性
  2. 床位顺序: 同一房间内按床位编码(bedCode)升序分配,符合物理布局
  3. 学院顺序: 严格按照传入的学院顺序进行分配
  4. 床位状态: 只分配状态为"空闲"的床位

🔮 后续优化方向

功能增强

  1. 智能分配: 考虑学院特性(如男女比例)优化分配策略
  2. 自定义规则: 支持管理员自定义分配优先级规则
  3. 冲突检测: 提前检测可能的分配冲突并给出建议

性能优化

  1. 批量操作: 进一步优化数据库批量操作性能
  2. 缓存机制: 对房间和床位信息增加缓存机制
  3. 异步处理: 对大规模分配支持异步处理模式

📅 更新记录

  • 2025-01-03:完成连续分配逻辑实现
  • 2025-01-03:创建优化说明文档
  • 2025-01-03:修改排序逻辑,改为按房间编码(roomCode)和床位编码(bedCode)排序