Hallo,
ich habe ein Problem mit der Planung von Serienmails. Ich steuere die Planung über einen PHP-Code, der für Teilnehmende den Versand von Mails zu randomisierten Zeitpunkten innerhalb festgelegter Zeitslots planen soll. Die Studie soll über 10 Tage laufen, pro Tag vier Mails pro Teilnehmer planen.
Bei der ersten Planung schient alles zu funktionieren, wie es soll. Allerdings werden dann immer wieder zusätzliche Mails für schon bestehende Teilnehmer geplant. Und zwar immer direkt korrekt für jede Welle eine. Eine Logik dahinter erschließt sich mir nicht.
Das hier ist der PHP-Code, den ich verwende:
if (getRoute() != 'repeat') {
$expireFinal = 172800; // 2 Tage
$expireRegular = 2820; // 47 Minuten
$minGap = 3600; // 1 Stunde Mindestabstand
$mailId = 2;
$plannedTimes = [];
$plannedMails = [];
$abortAll = false;
$baseDate = strtotime('today');
// Teilnehmer-Offset (0–5 Minuten)
$participantOffset = time() % 300;
// ======================================================
// Phase 1: Slots berechnen (Sampling + Shuffle)
// ======================================================
for ($day = 1; $day <= 10; $day++) {
if ($abortAll) {
break;
}
$currentDate = strtotime("+" . $day . " day", $baseDate);
if ($currentDate === false) {
$abortAll = true;
break;
}
$weekday = (int) date('N', $currentDate);
// Tagesfenster
$windows = [];
if ($weekday <= 5) {
$windows[] = [
'start' => mktime(7,0,0,date('n',$currentDate),date('j',$currentDate),date('Y',$currentDate)),
'end' => mktime(7,55,0,date('n',$currentDate),date('j',$currentDate),date('Y',$currentDate))
];
$windows[] = [
'start' => mktime(14,0,0,date('n',$currentDate),date('j',$currentDate),date('Y',$currentDate)),
'end' => mktime(22,0,0,date('n',$currentDate),date('j',$currentDate),date('Y',$currentDate))
];
} else {
$windows[] = [
'start' => mktime(10,0,0,date('n',$currentDate),date('j',$currentDate),date('Y',$currentDate)),
'end' => mktime(22,0,0,date('n',$currentDate),date('j',$currentDate),date('Y',$currentDate))
];
}
// Alle möglichen Slots sammeln
$allSlots = [];
foreach ($windows as $w) {
for ($t = $w['start']; $t <= $w['end']; $t += 300) {
if ($t > time()) {
$allSlots[] = min($t + $participantOffset, $w['end']);
}
}
}
if (count($allSlots) < 4) {
$abortAll = true;
break;
}
shuffle($allSlots);
// 4 Slots mit Mindestabstand auswählen
$daySlots = [];
foreach ($allSlots as $slot) {
$ok = true;
foreach ($daySlots as $ds) {
if (abs($slot - $ds) < $minGap) {
$ok = false;
break;
}
}
if ($ok) {
foreach ($plannedTimes as $pt) {
if (abs($slot - $pt) < $minGap) {
$ok = false;
break;
}
}
}
if ($ok) {
$daySlots[] = $slot;
if (count($daySlots) === 4) {
break;
}
}
}
if (count($daySlots) !== 4) {
$abortAll = true;
break;
}
// Slots fixieren
foreach ($daySlots as $candidateTime) {
if ($mailId > 82) {
$abortAll = true;
break;
}
$plannedMails[] = [
'mailId' => $mailId,
'plannedTime' => $candidateTime,
'expire' => $candidateTime + $expireRegular
];
$plannedTimes[] = $candidateTime;
$mailId++;
if ($mailId >= 3 && $mailId <= 43) {
$mailId = 44;
}
}
}
// ======================================================
// Phase 2: Mails planen (unverändert)
// ======================================================
if (!$abortAll) {
foreach ($plannedMails as $pm) {
$plannedTime = $pm['plannedTime'];
$expireAt = $pm['expire'];
if ($expireAt <= time()) {
$expireAt = time() + $expireRegular;
}
mailSchedule(false, $pm['mailId'], $plannedTime, [
'expire' => $expireAt
]);
}
// Abschlussfragebogen ID 84
if (count($plannedTimes) > 0) {
$lastMailTime = max($plannedTimes);
$plannedTime = $lastMailTime + $expireRegular;
$lastDay = strtotime('+10 day', $baseDate);
$weekday = (int) date('N', $lastDay);
if ($weekday <= 5) {
$windows = [
[
'start'=>mktime(7,0,0,date('n',$lastDay),date('j',$lastDay),date('Y',$lastDay)),
'end' =>mktime(7,55,0,date('n',$lastDay),date('j',$lastDay),date('Y',$lastDay))
],
[
'start'=>mktime(14,0,0,date('n',$lastDay),date('j',$lastDay),date('Y',$lastDay)),
'end' =>mktime(22,0,0,date('n',$lastDay),date('j',$lastDay),date('Y',$lastDay))
]
];
} else {
$windows = [
[
'start'=>mktime(10,0,0,date('n',$lastDay),date('j',$lastDay),date('Y',$lastDay)),
'end' =>mktime(22,0,0,date('n',$lastDay),date('j',$lastDay),date('Y',$lastDay))
]
];
}
$plannedTime = max($plannedTime, max($plannedTimes) + $minGap);
$plannedTime = min($plannedTime, $windows[count($windows) - 1]['end']);
$ok = mailSchedule(false, 84, $plannedTime, [
'expire' => $plannedTime + $expireFinal
]);
if ($ok !== false) {
$plannedMails[] = [
'mailId' => 84,
'plannedTime' => $plannedTime,
'expire' => $plannedTime + $expireFinal
];
} else {
$abortAll = true;
$plannedTimes = [];
}
}
}
} // Ende if getRoute() != 'repeat'