%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /www/loslex/demo/app/Workers/Cup/
Upload File :
Create Path :
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;
    }
}

Zerion Mini Shell 1.0