add sparse workload placement

This commit is contained in:
Yisroel Baum 2026-08-19 22:40:43 +03:00
parent ff8efd7f4a
commit 90dcc8665a
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
3 changed files with 55 additions and 16 deletions

View file

@ -64,7 +64,7 @@ class CreateSchedule
'targetDate must not be before startDate',
);
}
$workloadPlacement = $this->workloadPlacement(
$requestedWorkloadPlacement = $this->workloadPlacement(
$request->workloadPlacement,
);
@ -78,6 +78,13 @@ class CreateSchedule
throw new BadRequestException('level has no elements');
}
$workloadPlacement = $this->resolvedWorkloadPlacement(
requestedWorkloadPlacement: $requestedWorkloadPlacement,
assignmentCount: count($elements),
startDate: $startDate,
targetDate: $targetDate,
);
$scheduledDates = $this->evenDistributionScheduler->scheduledDates(
assignmentCount: count($elements),
startDate: $startDate,
@ -225,19 +232,50 @@ class CreateSchedule
/**
* @throws BadRequestException
*/
private function workloadPlacement(?string $value): WorkloadPlacement
private function workloadPlacement(?string $value): ?WorkloadPlacement
{
if ($value === null) {
return WorkloadPlacement::Middle;
return null;
}
$workloadPlacement = WorkloadPlacement::tryFrom($value);
if ($workloadPlacement === null) {
throw new BadRequestException(
'workloadPlacement must be start, middle, or end',
'workloadPlacement must be spread, start, middle, or end',
);
}
return $workloadPlacement;
}
/**
* @throws BadRequestException
*/
private function resolvedWorkloadPlacement(
?WorkloadPlacement $requestedWorkloadPlacement,
int $assignmentCount,
DateTimeImmutable $startDate,
DateTimeImmutable $targetDate,
): WorkloadPlacement {
$differenceInDays = $startDate->diff($targetDate)->days;
$dayCount = $differenceInDays + 1;
$isSparse = $assignmentCount < $dayCount;
if ($requestedWorkloadPlacement === null) {
return $isSparse
? WorkloadPlacement::Spread
: WorkloadPlacement::Middle;
}
if (
$requestedWorkloadPlacement === WorkloadPlacement::Spread
&& ! $isSparse
) {
throw new BadRequestException(
'spread placement requires fewer assignments than days',
);
}
return $requestedWorkloadPlacement;
}
}