以下是一个基于Java的教练培训排课系统源码的核心架构与关键代码实现解析,该系统结合了Spring Boot框架、MySQL数据库、遗传算法优化排课以及实时通信技术,能够满足教练培训行业的排课需求。
一、系统架构设计
二、核心功能模块
三、关键代码实现
1. 排课实体类
java
@Data
public class Schedule {
private Long id;
private Long coachId;
private Long courseId;
private Long roomId;
private LocalDateTime startTime;
private LocalDateTime endTime;
private Boolean conflictFlag; // 是否冲突标记
}
2. 遗传算法排课引擎核心逻辑
java
@Service
public class ScheduleOptimizer {
@Autowired
private ResourceService resourceService;
public Schedule generateOptimalSchedule(List<CourseRequest> requests) {
// 1. 初始化种群(随机生成100个排课方案)
List<Schedule> population = initializePopulation(requests, 100);
// 2. 迭代优化(20代)
for (int generation = 0; generation < 20; generation++) {
// 计算适应度
List<Double> fitnessScores = population.stream()
.map(this::calculateFitness)
.collect(Collectors.toList());
// 选择(轮盘赌)
List<Schedule> selected = selectByRoulette(population, fitnessScores);
// 交叉(单点交叉)
List<Schedule> crossed = crossover(selected);
// 变异(随机调整时间/教室)
List<Schedule> mutated = mutate(crossed, 0.1);
population = mutated;
}
// 3. 返回最优解
return population.stream()
.max(Comparator.comparingDouble(this::calculateFitness))
.orElseThrow();
}
private List<Schedule> initializePopulation(List<CourseRequest> requests, int size) {
List<Schedule> population = new ArrayList<>();
for (int i = 0; i < size; i++) {
Schedule schedule = new Schedule();
for (CourseRequest request : requests) {
// 随机分配资源(教室/教练/时间)
Room room = resourceService.getRandomAvailableRoom(request.getStartTime());
Teacher teacher = resourceService.getRandomAvailableTeacher(request.getStartTime());
if (room != null && teacher != null) {
schedule.addCourse(new Course(request, room, teacher));
}
}
population.add(schedule);
}
return population;
}
private double calculateFitness(Schedule schedule) {
double conflictPenalty = schedule.getConflictFlag() ? 10 : 0;
double idlePenalty = schedule.getRoomIdleHours() * 0.5;
double continuityBonus = schedule.getConsecutiveCourses() * 2;
return 100 / (1 + conflictPenalty + idlePenalty – continuityBonus);
}
// 其他方法:selectByRoulette, crossover, mutate…
}
3. 冲突检测服务
java
@Service
public class ConflictDetector {
@Autowired
private RedisTemplate<String, Boolean> redisTemplate;
public boolean checkCoachConflict(Long coachId, LocalDateTime start, LocalDateTime end) {
String lockKey = "coach_lock:" + coachId;
try (RedissonLock lock = redissonClient.getLock(lockKey)) {
lock.lock(5, TimeUnit.SECONDS);
// 查询Redis中教练当前时段占用状态
Boolean isOccupied = redisTemplate.opsForValue().get("coach_time:" + coachId + ":" + start);
return Boolean.TRUE.equals(isOccupied);
}
}
}
四、数据库设计
1. 教练表(coach)
sql
CREATE TABLE `coach` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`specialty` VARCHAR(100) COMMENT '擅长课程',
`available_time` JSON NOT NULL COMMENT '格式: [{"dayOfWeek":1,"startPeriod":9,"endPeriod":18}]',
`max_continuous_hours` INT DEFAULT 4 COMMENT '最大连续授课时长'
);
2. 排课结果表(schedule)
sql
CREATE TABLE `schedule` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`coach_id` BIGINT NOT NULL,
`course_id` BIGINT NOT NULL,
`room_id` BIGINT NOT NULL,
`start_time` DATETIME NOT NULL,
`end_time` DATETIME NOT NULL,
`conflict_flag` BOOLEAN DEFAULT 0,
FOREIGN KEY (`coach_id`) REFERENCES `coach`(`id`)
);
3. 冲突日志表(conflict_log,MongoDB)
json
{
"_id": ObjectId("…"),
"schedule_id": 123,
"conflict_type": "ROOM",
"conflict_detail": {
"room_id": 456,
"time_range": ["2026-02-06T09:00:00", "2026-02-06T10:30:00"]
}
}



