%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/nginx/.vscode-server/data/User/History/-5b5ca2a2/
Upload File :
Create Path :
Current File : //home/nginx/.vscode-server/data/User/History/-5b5ca2a2/SPj7.php

<?php

namespace App\Workers;

use App\Models\Contest;
use App\Models\ContestDivision;
use App\Models\Registration;
use App\Models\ShooterStage;
use App\Models\ShooterStageTarget;
use App\Models\ShooterStageTime;
use App\Models\Stage;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use Ramsey\Uuid\Uuid;
use stdClass;
use ZipArchive;

class ContestImporter
{
    public array $errors = array();
    public array $warnings = array();

    function __construct(Contest $contest, string $filename, string $extension)
    {
        switch ($extension){
            case 'xls':
                $this->importExcel($contest, $filename);
                break;

            case 'xlsx':
                $this->importExcel($contest, $filename, true);
                break;

            case 'psc':
                $this->importPractiScore($contest, $filename);
                break;
        }
    }

    protected function importExcel(Contest $contest, string $filename, bool $isXlsx = false)
    {
        $numStages = $contest->stages;
        $tmpName = tempnam(sys_get_temp_dir(), 'practiscore.xls');
        file_put_contents($tmpName, Storage::disk('contests')->get($filename));
        $reader = $isXlsx ? new Xlsx() : new Xls();
        $spreadsheet = $reader->load($tmpName);
        $ss = $spreadsheet->setActiveSheetIndex(0);

        // Delete old data before import
        DB::statement("DELETE FROM shooter_stage_times WHERE shooter_stage_id in (SELECT id FROM shooter_stages where stage_id in (SELECT id FROM stages WHERE contest_id = ?))", [$contest->id]);
        DB::statement("DELETE FROM shooter_stage_targets WHERE shooter_stage_id in (SELECT id FROM shooter_stages where stage_id in (SELECT id FROM stages WHERE contest_id = ?))", [$contest->id]);
        DB::statement("DELETE FROM shooter_stages WHERE stage_id in (SELECT id FROM stages WHERE contest_id = ?)", [$contest->id]);
        DB::statement("DELETE FROM stages WHERE contest_id = ?", [$contest->id]);

        // Create stages
        $stageIds = array();
        for($i = 0; $i < $numStages; $i++)
        {
            $st = new Stage([
                'contest_id' => $contest->id,
                'name' => "Stage " . ($i + 1),
                'order' => $i + 1,
                'strings' => 1
            ]);
            $st->save();
            $stageIds[$i] = $st->id;
        }

        foreach (ExcelHelper::$divisionDefaultStartPosition as $division => $position)
        {
            // Prepare division ID
            $divisionId = ContestDivision::where(DB::raw('UPPER(bgdivision)'), $division)->first()->id;

            // Get mail and alias, if empty, go to another division
            while($mailalias = trim($ss->getCell("B" . $position)->getValue())) {
                list($email, $alias) = explode("/", $mailalias);
                $alias = strtoupper($alias);
                $notCompeting = strtoupper(rim($ss->getCell("B" . $position)->getValue())) == "MZ";

                list($firstName, $lastName) = explode(" ", $ss->getCell("C" . $position)->getValue());
                $user = $this->getOrCreateUserByAlias($alias, $email, $firstName, $lastName);
                $registration = new Registration([
                    'contest_id' => $contest->id,
                    'user_id' => $user->id,
                    'contest_division_id' => $divisionId,
                    'squad' => 1,
                    'notcomp' => $notCompeting ? 1 : 0
                ]);
                $registration->canceltoken = Str::orderedUuid();
                $registration->save();

                // Get stage data
                $col = 4;
                for ($i = 0; $i < $numStages; $i++) {
                    $shooterStage = new ShooterStage([
                        'registration_id' => $registration->id,
                        'stage_id' => $stageIds[$i],
                        'proc' => $ss->getCell([$col + 8, $position])->getValue() ?? 0,
                        'noshoot' => $ss->getCell([$col + 7, $position])->getValue() ?? 0
                    ]);
                    $shooterStage->save();

                    $shooterStageTime = new ShooterStageTime([
                        'shooter_stage_id' => $shooterStage->id,
                        'time' => $ss->getCell([$col, $position])->getValue(),
                        'order' => 1
                    ]);
                    $shooterStageTime->save();
                    $shooterStageTarget = new ShooterStageTarget([
                        'shooter_stage_id' => $shooterStage->id,
                        'order' => 1,
                        'popper' => $ss->getCell([$col + 1, $position])->getValue() ?? 0,
                        'alpha' => $ss->getCell([$col + 2, $position])->getValue() ?? 0,
                        'charlie' => $ss->getCell([$col + 3, $position])->getValue() ?? 0,
                        'delta' => $ss->getCell([$col + 4, $position])->getValue() ?? 0,
                        'miss' => $ss->getCell([$col + 5, $position])->getValue() ?? 0,
                        'misspopper' => $ss->getCell([$col + 6, $position])->getValue() ?? 0,
                    ]);
                    $shooterStageTarget->save();

                    $col += 10;
                }
                $position++;
            }
        }
    }

    protected function importPractiScore(Contest $contest, string $filename)
    {
        $tmpName = tempnam(sys_get_temp_dir(), 'practiscore.zip');
        file_put_contents($tmpName, Storage::disk('contests')->get($filename));
        $zip = new ZipArchive;
        $res = $zip->open($tmpName);
        $txt = $zip->getFromName('match_def.json');
        $matchDef = json_decode($txt);
        $txt = $zip->getFromName('match_scores.json');
        $scores = json_decode($txt);
        unset($txt);
        $zip->close();
        unlink($tmpName);

        // Prepare stages
        $stages = array();
        $numStages = 0;
        foreach ($matchDef->match_stages as $match_stage)
        {
            $stage = new stdClass();
            $stage->guid = $match_stage->stage_uuid;
            $stage->order = $match_stage->stage_number;
            $stage->name = $match_stage->stage_name;
            $stage->deleted = $match_stage->stage_deleted ?? false;
            $stage->strings = $match_stage->stage_strings;
            $stages[$stage->guid] = $stage;
            if(!$stage->deleted) $numStages++;
        }
        if($contest->stages != $numStages)
        {
            $this->errors[] = __('Contest has :cStages but imported PractiScore file contains :psStages stages', ['cStages' => $contest->stages, 'psStages' => $numStages]);
            return;
        }


        $shooters = $this->psProcessShooters($matchDef, $contest);

        DB::statement("DELETE FROM shooter_stage_times WHERE shooter_stage_id in (SELECT id FROM shooter_stages where stage_id in (SELECT id FROM stages WHERE contest_id = ?))", [$contest->id]);
        DB::statement("DELETE FROM shooter_stage_targets WHERE shooter_stage_id in (SELECT id FROM shooter_stages where stage_id in (SELECT id FROM stages WHERE contest_id = ?))", [$contest->id]);
        DB::statement("DELETE FROM shooter_stages WHERE stage_id in (SELECT id FROM stages WHERE contest_id = ?)", [$contest->id]);
        DB::statement("DELETE FROM stages WHERE contest_id = ?", [$contest->id]);



        // Process scores
        foreach ($scores->match_scores as $stage)
        {
            $defStage = $stages[$stage->stage_uuid];
            if($defStage->deleted) continue;
            $st = new Stage([
                'contest_id' => $contest->id,
                'name' => $defStage->name,
                'order' => $defStage->order,
                'strings' => $defStage->strings
            ]);
            $st->save();
            $stageId = $st->id;
            foreach ($stage->stage_stagescores as $score)
            {
                if(!isset($shooters[$score->shtr])) continue;

                $shooterStage = new ShooterStage([
                    'stage_id' => $stageId,
                    'registration_id' => $shooters[$score->shtr]->id,
                    'proc' => $score->proc ?? 0,
                    'noshoot' => 0
                ]);
                $shooterStage->save();
                $stageNo = $shooterStage->id;
                $noshoots = $score->popns ?? 0;

                // Proces times
                $order = 1;
                foreach ($score->str as $time)
                {
                    $strings = null;
                    // parse string splits
                    if(isset($score->meta))
                    {
                        foreach ($score->meta as $meta)
                        {
                            if(strstr($meta->k, "string" . ($order-1)))
                            {
                                $strings = array();
                                $times = explode(",", $meta->v);
                                $curr = 0.0;
                                foreach ($times as $t)
                                {
                                    $strings[] = number_format((double)$t - $curr, 2, '.', '');
                                    $curr = (double)$t;
                                }
                            }
                        }
                    }

                    $shooterStageTime = new ShooterStageTime([
                        'shooter_stage_id' => $stageNo,
                        'time' => $time,
                        'order' => $order++,
                        'string' => $strings != null ? implode(",", $strings) : null
                    ]);
                    $shooterStageTime->save();
                }

                $dataTpl = array(
                    "shooter_stage_id" => $stageNo,
                    "alpha" => 0,
                    "charlie" => 0,
                    "delta" => 0,
                    "miss" => 0,
                    "popper" => 0,
                    "misspopper" => 0
                );
                $order = 1;
                $data = $this->arrayCopy($dataTpl);
                if($score->popm > 0 || $score->poph > 0)
                {
                    $data["order"] = $order++;
                    $data["popper"] = $score->poph;
                    $data["misspopper"] = $score->popm;
                    $target = new ShooterStageTarget($data);
                    $target->save();
                    $data = $this->arrayCopy($dataTpl);
                }
                if(isset($score->ts)) {
                    foreach ($score->ts as $t) {
                        $data["order"] = $order++;
                        $data["alpha"] = ($t & 0xF);
                        $data["charlie"] = ($t & 0xF00) >> 8;
                        $data["delta"] = ($t & 0xF000) >> 12;
                        $data["miss"] = ($t & 0xF00000) >> 20;
                        $noshoots += ($t & 0xF0000) >> 16;

                        $target = new ShooterStageTarget($data);
                        $target->save();
                        $data = $this->arrayCopy($dataTpl);
                    }
                }

                $shooterStage->noshoot = $noshoots;
                $shooterStage->save();
            }
        }
    }

    private function getUserByAlias(string $alias)
    {
        return User::where(DB::raw('UPPER(username)'), strtoupper($alias))->first();
    }

    private function getUserByEmail(string $email)
    {
        return User::where(DB::raw('UPPER(email)'), strtoupper($email))->first();
    }

    /**
     * @param mixed $matchDef
     * @param Contest $contest
     * @return void
     */
    public function psProcessShooters(mixed $matchDef, Contest $contest): array
    {
        $shooters = array();
        foreach ($matchDef->match_shooters as $match_shooter) {
            if ($match_shooter->sh_del || $match_shooter->sh_dq) continue;
            $shooter = new stdClass();
            $shooter->id = null;
            $shooter->firstName = $match_shooter->sh_fn;
            $shooter->lastName = $match_shooter->sh_ln;
            $shooter->mail = (isset($match_shooter->sh_eml) && $match_shooter->sh_eml) ? $match_shooter->sh_eml : Uuid::uuid4() . "@test.com";
            $shooter->uid = $match_shooter->sh_uid;
            $shooter->division = strtoupper($match_shooter->sh_dvp);
            $shooter->squad = $match_shooter->sh_sqd;
            $shooter->alias = (isset($match_shooter->sh_id) && $match_shooter->sh_id) ? strtoupper($match_shooter->sh_id) : (string)(Uuid::uuid4());
            $shooter->notCompeting = isset($match_shooter->sh_chkins) && in_array("NotCompeting", $match_shooter->sh_chkins);
            $registration = $contest->registrations()->where('canceltoken', $shooter->uid)->first();
            if (!$registration) {
                // try to create registration
                $user = $this->getOrCreateUserByAlias($shooter->alias, $shooter->mail, $shooter->firstName, $shooter->lastName);
                $registration = new Registration([
                    'contest_id' => $contest->id,
                    'user_id' => $user->id,
                    'contest_division_id' => 1,
                    'squad' => $shooter->squad,
                    'notcomp' => $shooter->notCompeting ? 1 : 0
                ]);
                $registration->canceltoken = $shooter->uid;
                $registration->save();
            }
            if (strtoupper($registration->division->bgdivision) != $shooter->division) {
                // update division
                $registration->contest_division_id = ContestDivision::where(DB::raw('UPPER(bgdivision)'), $shooter->division)->first()->id;
                $registration->save();
            }
            $shooter->id = $registration->id;
            $shooters[$shooter->uid] = $shooter;
        }
        return $shooters;
    }

    public function hasMessages()
    {
        return count($this->errors) > 0 || count($this->warnings) > 0;
    }

    private function arrayCopy($arr) {
        $newArray = array();
        foreach($arr as $key => $value) {
            if(is_array($value)) $newArray[$key] = $this->arrayCopy($value);
            else if(is_object($value)) $newArray[$key] = clone $value;
            else $newArray[$key] = $value;
        }
        return $newArray;
    }

    /**
     * @param stdClass $shooter
     * @return User
     */
    public function getOrCreateUserByAlias($alias, $email, $firstName, $lastName): User
    {
        $user = $this->getUserByAlias($alias);
        if (!$user) {
            // Create new user
            $this->warnings[] = __('User with name :name and alias :alias does not exist, creating new one', ['name' => $firstName . " " . $lastName, 'alias' => $alias]);
            $user = new User([
                'username' => $alias,
                'firstname' => $firstName,
                'lastname' => $lastName,
                'email' => $email,
                'password' => ""
            ]);
            $user->personaltoken = Str::orderedUuid();
            $user->save();
        }
        return $user;
    }
}

Zerion Mini Shell 1.0