%PDF- %PDF-
| Direktori : /www/loslex_o/demo/app/Workers/Cup/ |
| Current File : /www/loslex_o/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()
{
$this->cupResults = new CupViewModel();
$this->cupResults->CupInfo = new CupInfo("Pohár LOS 2024");
}
public function ProcessCupResults(array $contests): CupViewModel
{
$limitDate = Carbon::parse("2024-06-30");
foreach ($contests as $contest) {
if (!$contest->results_published) {
$this->notPublishedCount++;
if ($contest->date->lte($limitDate)) {
$this->futureUsedContests++;
}
} else {
$this->processContest($contest);
}
}
$this->processDivisions();
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(): void
{
foreach ($this->divContests as $bgdiv => $contests) {
$division = new Division();
$division->BgDivision = $bgdiv;
$division->PastContests = count($contests);
$division->FutureContests = $this->notPublishedCount;
$division->FutureUsedContests = $this->futureUsedContests;
$division->TotalContests = $division->PastContests + $division->FutureContests;
$division->UsedContests = max(round((count($this->divContests[$bgdiv]) + $this->futureUsedContests) / 3), 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;
}
}