*/ 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 */ 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 */ 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); } }