su-secret-santa/app/Services/MatcherService.php

71 lines
1.7 KiB
PHP

<?php
namespace App\Services;
use App\Models\Participant;
use Illuminate\Support\Collection;
class MatcherService
{
public function match(): void
{
$participants = Participant::all();
if ($participants->count() < 2) {
return;
}
$assignments = [];
$newParticipantIds = $participants
->filter(fn($p) => $p->is_unmatched)
->pluck('id')
->shuffle()
->all();
$desperateGiverIds = $participants
->filter(fn($p) => $p->is_desperate && !$p->hasReceiver())
->pluck('id')
->shuffle()
->all();
$desperateReceiverIds = $participants
->filter(fn($p) => $p->is_desperate && !$p->hasGiver())
->pluck('id')
->shuffle()
->all();
while (!empty($desperateGiverIds) && !empty($desperateReceiverIds)) {
$giverId = array_shift($desperateGiverIds);
$receiverId = array_shift($desperateReceiverIds);
if ($giverId === $receiverId) {
array_unshift($desperateReceiverIds, $receiverId);
continue;
}
$assignments[$giverId] = $receiverId;
}
$newCount = count($newParticipantIds);
if ($newCount >= 2) {
for ($i = 0; $i < $newCount; $i++) {
$currentId = $newParticipantIds[$i];
$nextId = $newParticipantIds[($i + 1) % $newCount];
$assignments[$currentId] = $nextId;
}
}
foreach ($assignments as $giverId => $receiverId) {
Participant::where('id', $giverId)->update([
'giving_id' => $receiverId,
]);
}
}
}