add workload placement
This commit is contained in:
parent
465db4a5b8
commit
46ba265f38
8 changed files with 291 additions and 34 deletions
114
backend/app/Schedule/EvenDistributionScheduler.php
Normal file
114
backend/app/Schedule/EvenDistributionScheduler.php
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
namespace App\Schedule;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
class EvenDistributionScheduler
|
||||
{
|
||||
/**
|
||||
* @return list<DateTimeImmutable>
|
||||
*/
|
||||
public function scheduledDates(
|
||||
int $assignmentCount,
|
||||
DateTimeImmutable $startDate,
|
||||
DateTimeImmutable $targetDate,
|
||||
WorkloadPlacement $workloadPlacement,
|
||||
): array {
|
||||
$differenceInDays = $startDate->diff($targetDate)->days;
|
||||
$dayCount = $differenceInDays + 1;
|
||||
|
||||
if ($assignmentCount < $dayCount) {
|
||||
return $this->sparseDates(
|
||||
assignmentCount: $assignmentCount,
|
||||
dayCount: $dayCount,
|
||||
startDate: $startDate,
|
||||
);
|
||||
}
|
||||
|
||||
return $this->dailyDates(
|
||||
assignmentCount: $assignmentCount,
|
||||
dayCount: $dayCount,
|
||||
startDate: $startDate,
|
||||
workloadPlacement: $workloadPlacement,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<DateTimeImmutable>
|
||||
*/
|
||||
private function sparseDates(
|
||||
int $assignmentCount,
|
||||
int $dayCount,
|
||||
DateTimeImmutable $startDate,
|
||||
): array {
|
||||
if ($assignmentCount === 1) {
|
||||
return [$startDate];
|
||||
}
|
||||
|
||||
$dates = [];
|
||||
for ($assignmentIndex = 0;
|
||||
$assignmentIndex < $assignmentCount;
|
||||
$assignmentIndex++
|
||||
) {
|
||||
$scaledIndex = $assignmentIndex * ($dayCount - 1)
|
||||
/ ($assignmentCount - 1);
|
||||
$dayIndex = (int) floor($scaledIndex + 0.5);
|
||||
$dates[] = $startDate->modify("+{$dayIndex} days");
|
||||
}
|
||||
|
||||
return $dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<DateTimeImmutable>
|
||||
*/
|
||||
private function dailyDates(
|
||||
int $assignmentCount,
|
||||
int $dayCount,
|
||||
DateTimeImmutable $startDate,
|
||||
WorkloadPlacement $workloadPlacement,
|
||||
): array {
|
||||
$assignmentsPerDay = intdiv($assignmentCount, $dayCount);
|
||||
$heavierDayCount = $assignmentCount % $dayCount;
|
||||
$heavierBlockStart = $this->heavierBlockStart(
|
||||
dayCount: $dayCount,
|
||||
heavierDayCount: $heavierDayCount,
|
||||
workloadPlacement: $workloadPlacement,
|
||||
);
|
||||
$dates = [];
|
||||
|
||||
for ($dayIndex = 0; $dayIndex < $dayCount; $dayIndex++) {
|
||||
$assignmentCountForDay = $assignmentsPerDay;
|
||||
if (
|
||||
$dayIndex >= $heavierBlockStart
|
||||
&& $dayIndex < $heavierBlockStart + $heavierDayCount
|
||||
) {
|
||||
$assignmentCountForDay++;
|
||||
}
|
||||
|
||||
$date = $startDate->modify("+{$dayIndex} days");
|
||||
for ($index = 0; $index < $assignmentCountForDay; $index++) {
|
||||
$dates[] = $date;
|
||||
}
|
||||
}
|
||||
|
||||
return $dates;
|
||||
}
|
||||
|
||||
private function heavierBlockStart(
|
||||
int $dayCount,
|
||||
int $heavierDayCount,
|
||||
WorkloadPlacement $workloadPlacement,
|
||||
): int {
|
||||
if ($workloadPlacement === WorkloadPlacement::Start) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($workloadPlacement === WorkloadPlacement::End) {
|
||||
return $dayCount - $heavierDayCount;
|
||||
}
|
||||
|
||||
return intdiv($dayCount - $heavierDayCount, 2);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue