добавил денение на подгруппы для лабораторных работ
This commit is contained in:
@@ -26,6 +26,7 @@ public class ScheduleRuleAdminController {
|
||||
private final UserRepository userRepository;
|
||||
private final ClassroomRepository classroomRepository;
|
||||
private final LessonTypesRepository lessonTypesRepository;
|
||||
private final SubgroupRepository subgroupRepository;
|
||||
private final ScheduleGeneratorService scheduleGeneratorService;
|
||||
|
||||
public ScheduleRuleAdminController(ScheduleRuleRepository scheduleRuleRepository,
|
||||
@@ -36,6 +37,7 @@ public class ScheduleRuleAdminController {
|
||||
UserRepository userRepository,
|
||||
ClassroomRepository classroomRepository,
|
||||
LessonTypesRepository lessonTypesRepository,
|
||||
SubgroupRepository subgroupRepository,
|
||||
ScheduleGeneratorService scheduleGeneratorService) {
|
||||
this.scheduleRuleRepository = scheduleRuleRepository;
|
||||
this.subjectRepository = subjectRepository;
|
||||
@@ -45,6 +47,7 @@ public class ScheduleRuleAdminController {
|
||||
this.userRepository = userRepository;
|
||||
this.classroomRepository = classroomRepository;
|
||||
this.lessonTypesRepository = lessonTypesRepository;
|
||||
this.subgroupRepository = subgroupRepository;
|
||||
this.scheduleGeneratorService = scheduleGeneratorService;
|
||||
}
|
||||
|
||||
@@ -187,7 +190,8 @@ public class ScheduleRuleAdminController {
|
||||
.orElseThrow(() -> new IllegalArgumentException("Аудитория не найдена"));
|
||||
LessonType lessonType = lessonTypesRepository.findById(slotDto.lessonTypeId())
|
||||
.orElseThrow(() -> new IllegalArgumentException("Тип занятия не найден"));
|
||||
ScheduleLessonCategory.fromLessonType(lessonType);
|
||||
ScheduleLessonCategory category = ScheduleLessonCategory.fromLessonType(lessonType);
|
||||
Subgroup subgroup = resolveSubgroup(rule, slotDto.subgroupId(), category);
|
||||
if (slotDto.lessonFormat() == null || slotDto.lessonFormat().isBlank()) {
|
||||
throw new IllegalArgumentException("Формат занятия обязателен");
|
||||
}
|
||||
@@ -197,7 +201,7 @@ public class ScheduleRuleAdminController {
|
||||
slot.setDayOfWeek(slotDto.dayOfWeek());
|
||||
slot.setParity(slotDto.parity());
|
||||
slot.setTimeSlot(timeSlot);
|
||||
slot.setSubgroupId(slotDto.subgroupId());
|
||||
slot.setSubgroup(subgroup);
|
||||
slot.setTeacher(teacher);
|
||||
slot.setClassroom(classroom);
|
||||
slot.setLessonType(lessonType);
|
||||
@@ -205,6 +209,23 @@ public class ScheduleRuleAdminController {
|
||||
return slot;
|
||||
}
|
||||
|
||||
private Subgroup resolveSubgroup(ScheduleRule rule, Long subgroupId, ScheduleLessonCategory category) {
|
||||
if (subgroupId == null) {
|
||||
return null;
|
||||
}
|
||||
if (category != ScheduleLessonCategory.LABORATORY) {
|
||||
throw new IllegalArgumentException("Подгруппы можно выбирать только для лабораторных занятий");
|
||||
}
|
||||
Subgroup subgroup = subgroupRepository.findById(subgroupId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Подгруппа не найдена"));
|
||||
boolean subgroupBelongsToRuleGroups = rule.getGroups().stream()
|
||||
.anyMatch(group -> group.getId().equals(subgroup.getStudentGroup().getId()));
|
||||
if (!subgroupBelongsToRuleGroups) {
|
||||
throw new IllegalArgumentException("Подгруппа должна относиться к одной из групп правила");
|
||||
}
|
||||
return subgroup;
|
||||
}
|
||||
|
||||
private String validateTypeHours(ScheduleRuleDto request) {
|
||||
if (isMissing(request.lectureAcademicHours())
|
||||
|| isMissing(request.laboratoryAcademicHours())
|
||||
@@ -306,6 +327,7 @@ public class ScheduleRuleAdminController {
|
||||
timeSlot.getOrderNumber(),
|
||||
formatTimeSlot(timeSlot),
|
||||
slot.getSubgroupId(),
|
||||
slot.getSubgroup() == null ? null : slot.getSubgroup().getName(),
|
||||
slot.getTeacher().getId(),
|
||||
ScheduleGeneratorService.displayUserName(slot.getTeacher()),
|
||||
slot.getClassroom().getId(),
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.magistr.app.controller;
|
||||
|
||||
import com.magistr.app.dto.SubgroupDto;
|
||||
import com.magistr.app.model.StudentGroup;
|
||||
import com.magistr.app.model.Subgroup;
|
||||
import com.magistr.app.repository.GroupRepository;
|
||||
import com.magistr.app.repository.ScheduleRuleSlotRepository;
|
||||
import com.magistr.app.repository.SubgroupRepository;
|
||||
import com.magistr.app.service.ScheduleGeneratorService;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
public class SubgroupController {
|
||||
|
||||
private final SubgroupRepository subgroupRepository;
|
||||
private final GroupRepository groupRepository;
|
||||
private final ScheduleRuleSlotRepository scheduleRuleSlotRepository;
|
||||
private final ScheduleGeneratorService scheduleGeneratorService;
|
||||
|
||||
public SubgroupController(SubgroupRepository subgroupRepository,
|
||||
GroupRepository groupRepository,
|
||||
ScheduleRuleSlotRepository scheduleRuleSlotRepository,
|
||||
ScheduleGeneratorService scheduleGeneratorService) {
|
||||
this.subgroupRepository = subgroupRepository;
|
||||
this.groupRepository = groupRepository;
|
||||
this.scheduleRuleSlotRepository = scheduleRuleSlotRepository;
|
||||
this.scheduleGeneratorService = scheduleGeneratorService;
|
||||
}
|
||||
|
||||
@GetMapping("/api/subgroups")
|
||||
public List<SubgroupDto> getAll() {
|
||||
return subgroupRepository.findAllWithGroupsOrderByGroupNameAndName().stream()
|
||||
.map(this::toDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@GetMapping("/api/groups/{groupId}/subgroups")
|
||||
public ResponseEntity<?> getByGroup(@PathVariable Long groupId) {
|
||||
if (!groupRepository.existsById(groupId)) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok(subgroupRepository.findByStudentGroupIdOrderByNameAsc(groupId).stream()
|
||||
.map(this::toDto)
|
||||
.toList());
|
||||
}
|
||||
|
||||
@PostMapping("/api/groups/{groupId}/subgroups")
|
||||
public ResponseEntity<?> create(@PathVariable Long groupId, @RequestBody SubgroupDto request) {
|
||||
StudentGroup group = groupRepository.findById(groupId).orElse(null);
|
||||
if (group == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
String validationError = validate(request);
|
||||
if (validationError != null) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", validationError));
|
||||
}
|
||||
if (subgroupRepository.existsByStudentGroupIdAndNameIgnoreCase(groupId, request.name().trim())) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "Подгруппа с таким названием уже есть в группе"));
|
||||
}
|
||||
|
||||
Subgroup subgroup = new Subgroup();
|
||||
subgroup.setStudentGroup(group);
|
||||
subgroup.setName(request.name().trim());
|
||||
subgroup.setStudentCapacity(request.studentCapacity());
|
||||
Subgroup saved = subgroupRepository.save(subgroup);
|
||||
scheduleGeneratorService.clearCache();
|
||||
return ResponseEntity.ok(toDto(saved));
|
||||
}
|
||||
|
||||
@PutMapping("/api/groups/{groupId}/subgroups/{id}")
|
||||
public ResponseEntity<?> update(@PathVariable Long groupId,
|
||||
@PathVariable Long id,
|
||||
@RequestBody SubgroupDto request) {
|
||||
Subgroup subgroup = subgroupRepository.findByIdAndStudentGroupId(id, groupId).orElse(null);
|
||||
if (subgroup == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
String validationError = validate(request);
|
||||
if (validationError != null) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", validationError));
|
||||
}
|
||||
String newName = request.name().trim();
|
||||
boolean duplicateName = subgroupRepository.existsByStudentGroupIdAndNameIgnoreCase(groupId, newName)
|
||||
&& !subgroup.getName().equalsIgnoreCase(newName);
|
||||
if (duplicateName) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "Подгруппа с таким названием уже есть в группе"));
|
||||
}
|
||||
|
||||
subgroup.setName(newName);
|
||||
subgroup.setStudentCapacity(request.studentCapacity());
|
||||
Subgroup saved = subgroupRepository.save(subgroup);
|
||||
scheduleGeneratorService.clearCache();
|
||||
return ResponseEntity.ok(toDto(saved));
|
||||
}
|
||||
|
||||
@DeleteMapping("/api/groups/{groupId}/subgroups/{id}")
|
||||
public ResponseEntity<?> delete(@PathVariable Long groupId, @PathVariable Long id) {
|
||||
Subgroup subgroup = subgroupRepository.findByIdAndStudentGroupId(id, groupId).orElse(null);
|
||||
if (subgroup == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
if (scheduleRuleSlotRepository.existsBySubgroupId(id)) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "Подгруппа используется в расписании"));
|
||||
}
|
||||
try {
|
||||
subgroupRepository.delete(subgroup);
|
||||
scheduleGeneratorService.clearCache();
|
||||
return ResponseEntity.ok(Map.of("message", "Подгруппа удалена"));
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "Подгруппа используется в расписании"));
|
||||
}
|
||||
}
|
||||
|
||||
private String validate(SubgroupDto request) {
|
||||
if (request == null || request.name() == null || request.name().isBlank()) {
|
||||
return "Название подгруппы обязательно";
|
||||
}
|
||||
if (request.studentCapacity() != null && request.studentCapacity() < 0) {
|
||||
return "Численность подгруппы не может быть отрицательной";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SubgroupDto toDto(Subgroup subgroup) {
|
||||
StudentGroup group = subgroup.getStudentGroup();
|
||||
return new SubgroupDto(
|
||||
subgroup.getId(),
|
||||
group.getId(),
|
||||
group.getName(),
|
||||
subgroup.getName(),
|
||||
subgroup.getStudentCapacity()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public record RenderedLessonDto(
|
||||
String lessonTypeName,
|
||||
String lessonFormat,
|
||||
Long subgroupId,
|
||||
String subgroupName,
|
||||
List<Long> groupIds,
|
||||
List<String> groupNames,
|
||||
String activityType,
|
||||
|
||||
@@ -11,6 +11,7 @@ public record ScheduleRuleSlotDto(
|
||||
Integer timeSlotOrder,
|
||||
String timeSlotLabel,
|
||||
Long subgroupId,
|
||||
String subgroupName,
|
||||
Long teacherId,
|
||||
String teacherName,
|
||||
Long classroomId,
|
||||
|
||||
10
backend/src/main/java/com/magistr/app/dto/SubgroupDto.java
Normal file
10
backend/src/main/java/com/magistr/app/dto/SubgroupDto.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.magistr.app.dto;
|
||||
|
||||
public record SubgroupDto(
|
||||
Long id,
|
||||
Long groupId,
|
||||
String groupName,
|
||||
String name,
|
||||
Integer studentCapacity
|
||||
) {
|
||||
}
|
||||
@@ -25,8 +25,9 @@ public class ScheduleRuleSlot {
|
||||
@JoinColumn(name = "time_slot_id", nullable = false)
|
||||
private TimeSlot timeSlot;
|
||||
|
||||
@Column(name = "subgroup_id")
|
||||
private Long subgroupId;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "subgroup_id")
|
||||
private Subgroup subgroup;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "teacher_id", nullable = false)
|
||||
@@ -84,11 +85,15 @@ public class ScheduleRuleSlot {
|
||||
}
|
||||
|
||||
public Long getSubgroupId() {
|
||||
return subgroupId;
|
||||
return subgroup == null ? null : subgroup.getId();
|
||||
}
|
||||
|
||||
public void setSubgroupId(Long subgroupId) {
|
||||
this.subgroupId = subgroupId;
|
||||
public Subgroup getSubgroup() {
|
||||
return subgroup;
|
||||
}
|
||||
|
||||
public void setSubgroup(Subgroup subgroup) {
|
||||
this.subgroup = subgroup;
|
||||
}
|
||||
|
||||
public User getTeacher() {
|
||||
|
||||
54
backend/src/main/java/com/magistr/app/model/Subgroup.java
Normal file
54
backend/src/main/java/com/magistr/app/model/Subgroup.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.magistr.app.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "subgroups")
|
||||
public class Subgroup {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "group_id", nullable = false)
|
||||
private StudentGroup studentGroup;
|
||||
|
||||
@Column(nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "student_capacity")
|
||||
private Integer studentCapacity;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public StudentGroup getStudentGroup() {
|
||||
return studentGroup;
|
||||
}
|
||||
|
||||
public void setStudentGroup(StudentGroup studentGroup) {
|
||||
this.studentGroup = studentGroup;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getStudentCapacity() {
|
||||
return studentCapacity;
|
||||
}
|
||||
|
||||
public void setStudentCapacity(Integer studentCapacity) {
|
||||
this.studentCapacity = studentCapacity;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ public interface ScheduleRuleRepository extends JpaRepository<ScheduleRule, Long
|
||||
left join fetch r.groups groups
|
||||
left join fetch r.slots slots
|
||||
left join fetch slots.timeSlot
|
||||
left join fetch slots.subgroup subgroup
|
||||
left join fetch subgroup.studentGroup
|
||||
left join fetch slots.teacher
|
||||
left join fetch slots.classroom
|
||||
left join fetch slots.lessonType
|
||||
@@ -40,6 +42,8 @@ public interface ScheduleRuleRepository extends JpaRepository<ScheduleRule, Long
|
||||
left join fetch r.groups groups
|
||||
left join fetch r.slots slots
|
||||
left join fetch slots.timeSlot
|
||||
left join fetch slots.subgroup subgroup
|
||||
left join fetch subgroup.studentGroup
|
||||
left join fetch slots.teacher
|
||||
left join fetch slots.classroom
|
||||
left join fetch slots.lessonType
|
||||
@@ -60,6 +64,8 @@ public interface ScheduleRuleRepository extends JpaRepository<ScheduleRule, Long
|
||||
left join fetch r.groups groups
|
||||
left join fetch r.slots slots
|
||||
left join fetch slots.timeSlot
|
||||
left join fetch slots.subgroup subgroup
|
||||
left join fetch subgroup.studentGroup
|
||||
left join fetch slots.teacher
|
||||
left join fetch slots.classroom
|
||||
left join fetch slots.lessonType
|
||||
@@ -76,6 +82,8 @@ public interface ScheduleRuleRepository extends JpaRepository<ScheduleRule, Long
|
||||
left join fetch r.groups groups
|
||||
left join fetch r.slots slots
|
||||
left join fetch slots.timeSlot
|
||||
left join fetch slots.subgroup subgroup
|
||||
left join fetch subgroup.studentGroup
|
||||
left join fetch slots.teacher
|
||||
left join fetch slots.classroom
|
||||
left join fetch slots.lessonType
|
||||
|
||||
@@ -2,6 +2,11 @@ package com.magistr.app.repository;
|
||||
|
||||
import com.magistr.app.model.ScheduleRuleSlot;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ScheduleRuleSlotRepository extends JpaRepository<ScheduleRuleSlot, Long> {
|
||||
|
||||
@Query("select case when count(slot) > 0 then true else false end from ScheduleRuleSlot slot where slot.subgroup.id = :subgroupId")
|
||||
boolean existsBySubgroupId(@Param("subgroupId") Long subgroupId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.magistr.app.repository;
|
||||
|
||||
import com.magistr.app.model.Subgroup;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface SubgroupRepository extends JpaRepository<Subgroup, Long> {
|
||||
|
||||
@Query("""
|
||||
select subgroup
|
||||
from Subgroup subgroup
|
||||
join fetch subgroup.studentGroup studentGroup
|
||||
order by studentGroup.name, subgroup.name
|
||||
""")
|
||||
List<Subgroup> findAllWithGroupsOrderByGroupNameAndName();
|
||||
|
||||
@Query("""
|
||||
select subgroup
|
||||
from Subgroup subgroup
|
||||
join fetch subgroup.studentGroup
|
||||
where subgroup.studentGroup.id = :groupId
|
||||
order by subgroup.name
|
||||
""")
|
||||
List<Subgroup> findByStudentGroupIdOrderByNameAsc(@Param("groupId") Long groupId);
|
||||
|
||||
@Query("""
|
||||
select subgroup
|
||||
from Subgroup subgroup
|
||||
join fetch subgroup.studentGroup
|
||||
where subgroup.id = :id
|
||||
and subgroup.studentGroup.id = :groupId
|
||||
""")
|
||||
Optional<Subgroup> findByIdAndStudentGroupId(@Param("id") Long id, @Param("groupId") Long groupId);
|
||||
|
||||
@Query("""
|
||||
select case when count(subgroup) > 0 then true else false end
|
||||
from Subgroup subgroup
|
||||
where subgroup.studentGroup.id = :groupId
|
||||
and lower(subgroup.name) = lower(:name)
|
||||
""")
|
||||
boolean existsByStudentGroupIdAndNameIgnoreCase(@Param("groupId") Long groupId, @Param("name") String name);
|
||||
}
|
||||
@@ -190,7 +190,7 @@ public class ScheduleGeneratorService {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<ScheduleLessonCategory, Integer> consumedHoursByCategory = new EnumMap<>(ScheduleLessonCategory.class);
|
||||
Map<String, Integer> consumedHoursByBucket = new HashMap<>();
|
||||
|
||||
for (ScheduleRuleSlot slot : slots) {
|
||||
ScheduleLessonCategory category = ScheduleLessonCategory.fromLessonType(slot.getLessonType());
|
||||
@@ -201,17 +201,22 @@ public class ScheduleGeneratorService {
|
||||
if (totalHours <= 0) {
|
||||
continue;
|
||||
}
|
||||
int consumedHours = consumedHoursByCategory.computeIfAbsent(
|
||||
category,
|
||||
key -> calculateConsumedHoursBeforeDate(rule, targetGroup, date, key)
|
||||
List<StudentGroup> lessonGroups = groupsForSlot(slot, eligibleGroups);
|
||||
if (lessonGroups.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String consumptionBucket = consumptionBucket(category, slot);
|
||||
int consumedHours = consumedHoursByBucket.computeIfAbsent(
|
||||
consumptionBucket,
|
||||
key -> calculateConsumedHoursBeforeDate(rule, targetGroup, date, category, slot.getSubgroupId())
|
||||
);
|
||||
if (consumedHours >= totalHours) {
|
||||
continue;
|
||||
}
|
||||
int remainingAfterLesson = Math.max(0, totalHours - consumedHours - ACADEMIC_HOURS_PER_SLOT);
|
||||
result.add(toRenderedLesson(rule, slot, date, weekNumber, dateParity, eligibleGroups,
|
||||
result.add(toRenderedLesson(rule, slot, date, weekNumber, dateParity, lessonGroups,
|
||||
totalHours, consumedHours, remainingAfterLesson));
|
||||
consumedHoursByCategory.put(category, consumedHours + ACADEMIC_HOURS_PER_SLOT);
|
||||
consumedHoursByBucket.put(consumptionBucket, consumedHours + ACADEMIC_HOURS_PER_SLOT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,17 +234,23 @@ public class ScheduleGeneratorService {
|
||||
private int calculateConsumedHoursBeforeDate(ScheduleRule rule,
|
||||
StudentGroup targetGroup,
|
||||
LocalDate targetDate,
|
||||
ScheduleLessonCategory category) {
|
||||
ScheduleLessonCategory category,
|
||||
Long subgroupId) {
|
||||
Long groupId = targetGroup == null ? null : targetGroup.getId();
|
||||
String cacheKey = rule.getId() + ":" + category.name() + ":" + (groupId == null ? "all" : groupId) + ":" + targetDate;
|
||||
String cacheKey = rule.getId()
|
||||
+ ":" + category.name()
|
||||
+ ":" + (subgroupId == null ? "whole" : subgroupId)
|
||||
+ ":" + (groupId == null ? "all" : groupId)
|
||||
+ ":" + targetDate;
|
||||
return consumedHoursCache.computeIfAbsent(cacheKey,
|
||||
ignored -> calculateConsumedHours(rule, targetGroup, targetDate, category));
|
||||
ignored -> calculateConsumedHours(rule, targetGroup, targetDate, category, subgroupId));
|
||||
}
|
||||
|
||||
private int calculateConsumedHours(ScheduleRule rule,
|
||||
StudentGroup targetGroup,
|
||||
LocalDate targetDate,
|
||||
ScheduleLessonCategory category) {
|
||||
ScheduleLessonCategory category,
|
||||
Long subgroupId) {
|
||||
int consumed = 0;
|
||||
for (LocalDate date = rule.getSemester().getStartDate(); date.isBefore(targetDate); date = date.plusDays(1)) {
|
||||
Semester semester = rule.getSemester();
|
||||
@@ -250,7 +261,8 @@ public class ScheduleGeneratorService {
|
||||
if (weekNumber < rule.startWeekFor(category)) {
|
||||
continue;
|
||||
}
|
||||
if (eligibleGroups(rule, targetGroup, semester, date).isEmpty()) {
|
||||
List<StudentGroup> eligibleGroups = eligibleGroups(rule, targetGroup, semester, date);
|
||||
if (eligibleGroups.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -260,6 +272,8 @@ public class ScheduleGeneratorService {
|
||||
.filter(slot -> Objects.equals(slot.getDayOfWeek(), dayOfWeek))
|
||||
.filter(slot -> slot.getParity() == ScheduleParity.BOTH || slot.getParity() == dateParity)
|
||||
.filter(slot -> ScheduleLessonCategory.fromLessonType(slot.getLessonType()) == category)
|
||||
.filter(slot -> Objects.equals(slot.getSubgroupId(), subgroupId))
|
||||
.filter(slot -> !groupsForSlot(slot, eligibleGroups).isEmpty())
|
||||
.count();
|
||||
consumed += (int) activeSlots * ACADEMIC_HOURS_PER_SLOT;
|
||||
if (consumed >= rule.academicHoursFor(category)) {
|
||||
@@ -269,6 +283,20 @@ public class ScheduleGeneratorService {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
private String consumptionBucket(ScheduleLessonCategory category, ScheduleRuleSlot slot) {
|
||||
return category.name() + ":" + (slot.getSubgroupId() == null ? "whole" : slot.getSubgroupId());
|
||||
}
|
||||
|
||||
private List<StudentGroup> groupsForSlot(ScheduleRuleSlot slot, List<StudentGroup> eligibleGroups) {
|
||||
if (slot.getSubgroup() == null) {
|
||||
return eligibleGroups;
|
||||
}
|
||||
Long subgroupGroupId = slot.getSubgroup().getStudentGroup().getId();
|
||||
return eligibleGroups.stream()
|
||||
.filter(group -> Objects.equals(group.getId(), subgroupGroupId))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private RenderedLessonDto toRenderedLesson(ScheduleRule rule,
|
||||
ScheduleRuleSlot slot,
|
||||
LocalDate date,
|
||||
@@ -305,6 +333,7 @@ public class ScheduleGeneratorService {
|
||||
slot.getLessonType().getLessonType(),
|
||||
slot.getLessonFormat(),
|
||||
slot.getSubgroupId(),
|
||||
slot.getSubgroup() == null ? null : slot.getSubgroup().getName(),
|
||||
sortedGroups.stream().map(StudentGroup::getId).toList(),
|
||||
sortedGroups.stream().map(StudentGroup::getName).collect(Collectors.toList()),
|
||||
"Т",
|
||||
|
||||
Reference in New Issue
Block a user