%PDF- %PDF-
Direktori : /www/loslex/demo/app/Workers/Cup/ |
Current File : //www/loslex/demo/app/Workers/Cup/LosCupProcessor.php |
<?php namespace App\Workers\Cup; use App\Models\User; use App\Models\Cup\Contest; use App\Models\Cup\CupInfo; use App\Models\Cup\Shooter; use App\Models\Cup\Division; use App\Models\Cup\CupViewModel; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; class LosCupProcessor implements ICupProcessor { private CupViewModel $cupResults; private array $divisions = array(); private array $divContests = array(); private int $notPublishedCount = 0; private int $futureUsedContests = 0; public function __construct($cupName, $decisionDate) { $this->cupResults = new CupViewModel(); $this->cupResults->CupInfo = new CupInfo($cupName, $decisionDate); } public function ProcessCupResults(array $contests): CupViewModel { foreach ($contests as $contest) { if (!$contest->results_published) { $this->notPublishedCount++; if ($contest->date->lte($this->cupResults->CupInfo->decisionDate)) { $this->futureUsedContests++; } } else { $this->processContest($contest); } } $this->processDivisions($contests); return $this->cupResults; } private function processContest(\App\Models\Contest $contest): void { $validDivisions = array(); // first get valid contest divisions - with at least 4 contestants $contestResults = DB::select("SELECT bgdivision,count(user_id) as contestants FROM `cup_contest_results` WHERE `contest_id` = ? GROUP BY bgdivision;", [$contest->id]); foreach ($contestResults as $result) { if ($result->bgdivision == "All") { continue; } // skip "All" division - not needed for cup if ($result->contestants >= 4) { $validDivisions[] = $result->bgdivision; } } $contestResults = DB::select("SELECT * FROM `cup_contest_results` WHERE `contest_id` = ? AND `dq`=0", [$contest->id]); foreach ($contestResults as $result) { if ($result->bgdivision == "All" || !in_array($result->bgdivision, $validDivisions)) { continue; } if (!isset($this->divContests[$result->bgdivision])) { $this->divContests[$result->bgdivision] = array(); } if (!isset($this->divisions[$result->bgdivision])) { $this->divisions[$result->bgdivision] = array(); } if (!in_array($result->contest_id, $this->divContests[$result->bgdivision])) { $this->divContests[$result->bgdivision][] = $result->contest_id; } if (!isset($this->divisions[$result->bgdivision][$result->user_id])) { $this->divisions[$result->bgdivision][$result->user_id] = array(); } $this->divisions[$result->bgdivision][$result->user_id][] = $result; } } private function processDivisions($contests): void { $contestsCollection = collect($contests); foreach ($this->divContests as $bgdiv => $dContests) { $division = new Division(); $division->BgDivision = $bgdiv; $division->PastContests = count($dContests); $division->FutureContests = $this->notPublishedCount; $division->FutureUsedContests = $this->futureUsedContests; $division->TotalContests = $division->PastContests + $division->FutureContests; $division->UsedContestsBase = 0; foreach ($this->divContests[$bgdiv] as $contestId) { if ($contestsCollection->where('id', $contestId)->first()->date->lte($this->cupResults->CupInfo->decisionDate)) { $division->UsedContestsBase++; } } $division->UsedContests = max(round(($division->UsedContestsBase + $this->futureUsedContests) / 3, 0, PHP_ROUND_HALF_UP), 3); $shooters = $this->getShooters($bgdiv, $division->UsedContests); uasort($shooters, function ($a, $b) { return ($a->TotalPercent < $b->TotalPercent) ? 1 : -1; }); foreach ($shooters as $sh) { if ($sh->Eligible) { $division->EligibleShooters[] = $sh; } else { $division->NotEligibleShooters[] = $sh; } } $this->cupResults->Divisions[] = $division; } uasort($this->cupResults->Divisions, function ($a, $b) { $divPrio = array( "ALL" => 1, "PI" => 2, "KPI" => 3, "MPI" => 4, "RE" => 5, "MRE" => 6, "OPT" => 7, "PDW" => 8, "PSA" => 9, "POP" => 10, "BSA" => 11, "BOP" => 12, "BOS" => 13 ); return $divPrio[strtoupper($a->BgDivision)] > $divPrio[strtoupper($b->BgDivision)] ? 1 : -1; }); } private function getShooters(string $bgdiv, int $eligibleContests): array { $returnShooters = array(); foreach ($this->divisions[$bgdiv] as $shooterId => $contests) { $ranges = array(); uasort($contests, function ($a, $b) { if ($a->percent < $b->percent) { return 1; } elseif ($a->percent > $b->percent) { return -1; } else { // in case of the same percent value (especially 100%) if ($a->date > $b->date) { return 1; } return -1; } }); $contestCount = min(count($contests), $eligibleContests); $shModel = User::where('id', $shooterId)->select(['firstname','lastname','namesuffix'])->first(); $sh = new Shooter(); $sh->ShooterId = $shooterId; $sh->Name = $shModel->displayname; $sh->AnonName = $shModel->displayanonname; $sh->Contests = array(); $sh->TotalPercent = 0; $con = null; foreach ($contests as $c) { if (!in_array($c->range_id, $ranges)) { $ranges[] = $c->range_id; } $con = new Contest(); $con->ContestDate = $c->date; $con->ContestName = $c->contestname; $con->ContestId = $c->contest_id; $con->Percent = $c->percent; if (count($sh->Contests) == ($contestCount - 1) && count($ranges) == 1) { // Try to find last result from different range break; } $sh->Contests[] = $con; } if (count($sh->Contests) < $contestCount) { $sh->Contests[] = $con; // Shooter is not eligible for cup, but add the last contest just to be correct } if (count($ranges) >= 2) { $sh->Eligible = true; } // count total percent using first contestCount results for ($i = 0; $i < $contestCount; $i++) { $sh->TotalPercent += $sh->Contests[$i]->Percent; } $returnShooters[] = $sh; } return $returnShooters; } }