%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /www/loslex/demo/app/Models/
Upload File :
Create Path :
Current File : /www/loslex/demo/app/Models/Contest.php

<?php

namespace App\Models;

use App\Enums\ContestCategoryEnum;
use App\Enums\ContestLevelEnum;
use App\Enums\ContestPublicationStatusEnum;
use App\Enums\ContestRegistrationEnum;
use App\Models\ContestCategory;
use App\Models\ContestDivision;
use App\Models\ContestLevel;
use App\Models\OrganizerGroup;
use App\Models\Range;
use App\Models\Registration;
use App\Models\User;
use App\Workers\AccountNote;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

class Contest extends Model
{
    use HasFactory;

    protected $fillable = [
        'published',
        'contestname',
        'range_id',
        'organizer_group_id',
        'date',
        'contest_category_id',
        'contest_level_id',
        'registration_start',
        'registration_end',
        'registration_type',
        'director_id',
        'rangemaster_id',
        'instructions',
    ];

    protected $casts = [
        'settings'              => 'array',
        'date'                  => 'date',
        'registration_type'     => ContestRegistrationEnum::class,
        'published'             => ContestPublicationStatusEnum::class,
    ];

    protected $locale;
    protected $now;

    public function __construct() {
        parent::__construct();

        $this->locale = App::currentLocale();
        $this->now = Carbon::now()->locale($this->locale);
    }


    /** Fill request values into JSON Settings field */
    public function fillSettings(Request $request) {
        $fields = array(
            "presentation_start", "presentation_end",
            "contest_start", "contest_end",
            "stages", "squads", "capacity", "distribution",
            "feelex", "feeothers", "protestdeposit",
            "accountnumber","accvarsym", "accnote", "acccondition",
            "calibrationwpn","caliberlimit",
            "secretstages", "flashlight","canteen","toilet",
            "squadshootstyle",
            "offsiteregurl", "organizeremail",
            "restrictionstext","legend", "partners"
        );
        $trimfields = array("presentation_start", "presentation_end", "contest_start", "contest_end");
        $data = array();

        foreach ($fields as $key) {
            if (empty($request->input($key))) { continue; }

            switch($key) {
                case "restrictionstext":
                case "legend":
                case "partners":
                    $data[$key] = $this->normalizeInstructions($request->input($key));
                    break;

                default:
                    $data[$key] = $request->input($key);
                    break;
            }
        }

        // if squad shoots together no need to store separate times.
        // OTOH we need to store the null for [0] field to avoid array shifting when reading to use in contest
        if ($request->squadshootstyle == 'together') {
            foreach ($trimfields as $key) { $data[$key] = array_splice($data[$key], 0, 1); }
        }

        $this->settings = $data;
    }

    /** Normalize freetext instructions text - trims whitespaces, converts all linebreaks to \n and reduces extra newlines */
    protected function normalizeInstructions(String $instructions) : String
    {
        $result = trim($instructions);                                      // trim starting and ending whitespaces
        $result = str_replace(array("\r\n", "\r", "\n"), "\n", $result);    // replace all wariants to single \n
        $result = preg_replace("/\n{3,}/", "\n\n", $result);                // avoid extra whitespacing of the of the content

        return $result;
    }

    public function instructions(): Attribute
    {
        return Attribute::make(
            get: fn ($value) => $value,
            set: fn ($value) => $this->normalizeInstructions($value),
        );
    }

    public function partnersArr(): Attribute
    {
        return Attribute::make(
            get: function () {
                $raw = $this->settings['partners'] ?? null;
                if (is_null($raw)) { return null; }

                $partnerlines = preg_split("/[\n;]/", $raw);
                foreach ($partnerlines as $partner) {
                    if (preg_match("/\[(.*?)\]\((.*?)\)/", $partner, $matches)) {
                        $partners[] = array('name' => $matches[1], 'url' => $matches[2]);
                    } else {
                        $partners[] = array('name' => $partner);
                    }
                }

                return $partners;
            },
        );
    }

    /* ========== ========== Getters for reg_start/end  ========== ========== */
    public function registrationStart():    Attribute { return Attribute::make(get: fn($value) => is_null($value) ? null : new Carbon($value) ); }
    public function registrationEnd():      Attribute { return Attribute::make(get: fn($value) => is_null($value) ? null : new Carbon($value) ); }

    /* ========== ========== Custom settings attributes ========== ========== */
    public function acccondition():         Attribute { return Attribute::make(get: fn () => $this->settings['acccondition'] ?? null); }
    public function accnote():              Attribute { return Attribute::make(get: fn () => $this->settings['accnote'] ?? null); }
    public function accountnumber():        Attribute { return Attribute::make(get: fn () => $this->settings['accountnumber'] ?? null); }
    public function accvarsym():            Attribute { return Attribute::make(get: fn () => $this->settings['accvarsym'] ?? null); }
    public function caliberlimit():         Attribute { return Attribute::make(get: fn () => $this->settings['caliberlimit'] ?? null); }
    public function calibrationwpn():       Attribute { return Attribute::make(get: fn () => $this->settings['calibrationwpn'] ?? null); }
    public function canteen():              Attribute { return Attribute::make(get: fn () => $this->settings['canteen'] ?? 0); }
    public function capacity():             Attribute { return Attribute::make(get: fn () => $this->settings['capacity'] ?? 0); }
    public function contestEnd():           Attribute { return Attribute::make(get: fn () => $this->settings['contest_end'] ?? null); }
    public function contestStart():         Attribute { return Attribute::make(get: fn () => $this->settings['contest_start'] ?? null); }
    public function distribution():         Attribute { return Attribute::make(get: fn () => $this->settings['distribution'] ?? null); }
    public function feelex():               Attribute { return Attribute::make(get: fn () => $this->settings['feelex'] ?? 0); }
    public function feeothers():            Attribute { return Attribute::make(get: fn () => $this->settings['feeothers'] ?? 0); }
    public function flashlight():           Attribute { return Attribute::make(get: fn () => $this->settings['flashlight'] ?? 0); }
    public function legend():               Attribute { return Attribute::make(get: fn () => $this->settings['legend'] ?? null); }
    public function offsiteregurl():        Attribute { return Attribute::make(get: fn () => $this->settings['offsiteregurl'] ?? ""); }
    public function organizerEmail():       Attribute { return Attribute::make(get: fn () => $this->settings['organizeremail'] ?? null); }
    public function partners():             Attribute { return Attribute::make(get: fn () => $this->settings['partners'] ?? null); }
    public function presentationEnd():      Attribute { return Attribute::make(get: fn () => $this->settings['presentation_end'] ?? null); }
    public function presentationStart():    Attribute { return Attribute::make(get: fn () => $this->settings['presentation_start'] ?? null); }
    public function protestdeposit():       Attribute { return Attribute::make(get: fn () => $this->settings['protestdeposit'] ?? 0); }
    public function restrictionstext():     Attribute { return Attribute::make(get: fn () => $this->settings['restrictionstext'] ?? null); }
    public function secretstages():         Attribute { return Attribute::make(get: fn () => $this->settings['secretstages'] ?? 0); }
    public function squads():               Attribute { return Attribute::make(get: fn () => $this->settings['squads'] ?? 0); }
    public function squadShootStyle():      Attribute { return Attribute::make(get: fn () => $this->settings['squadshootstyle'] ?? null); }
    public function stages():               Attribute { return Attribute::make(get: fn () => $this->settings['stages'] ?? 0); }
    public function toilet():               Attribute { return Attribute::make(get: fn () => $this->settings['toilet'] ?? 0); }

    public function paymentnote(): Attribute
    {
        return Attribute::make(
            get: function() {
                $paymentnote = new AccountNote($this->accnote, Auth::user());
                return $paymentnote->getPaymentNote();
            }
        );
    }


    /* ========== ========== Other helpers ========== ========== */
    /** Is registration active flag */
    public function isRegActive(): Attribute
    {
        $result = $this->now->gte($this->registration_start) && $this->now->lte($this->registration_end);
        return Attribute::make(
            get: fn() => $result,
        );
    }

    /** Waiting for registration to begin flag */
    public function isBeforeReg(): Attribute
    {
        $regStart = Carbon::parse($this->registration_start)->locale($this->locale);

        return Attribute::make(
            get: fn () => $this->now->lt($regStart),
        );
    }

    /** Registration ended flag */
    public function isAfterReg(): Attribute
    {
        $regEnd = Carbon::parse($this->registration_end)->locale($this->locale);

        return Attribute::make(
            get: fn () => $this->now->gt($regEnd),
        );
    }

    /** Returns true if "today" is after contest date */
    public function isAfterContest(): Attribute
    {
        $today = Carbon::today()->locale($this->locale);

        return Attribute::make(
            get: fn() => $this->date->lt($today)
        );
    }

    /** Contest date flag */
    public function isContestDay(): Attribute
    {
        $today = Carbon::today()->locale($this->locale);

        return Attribute::make(
            get: fn() => $this->date->eq($today)
        );
    }

    /** returns number of days related to "today" */
    public function dayShift(): Attribute
    {
        $today = Carbon::today()->locale($this->locale);

        return Attribute::make(
            get: fn() => $today->diffInDays($this->date, false)
        );
    }

    // /* Get the localized date formats */
    public function dateDay(): Attribute
    {
        $this->date->settings(['formatFunction' => 'translatedFormat']);
        return Attribute::make(get: fn () => $this->date->format('d'));
    }

    public function dateMth(): Attribute
    {
        $dateval =  Carbon::parse($this->date)->locale($this->locale);
        $dateval->settings(['formatFunction' => 'translatedFormat']);

        return Attribute::make(get: fn () => $dateval->format('M'));
    }

    public function dateDow(): Attribute
    {
        $dateval =  Carbon::parse($this->date)->locale($this->locale);
        $dateval->settings(['formatFunction' => 'translatedFormat']);

        return Attribute::make(get: fn () => $dateval->format('l'));
    }

    /** Helper function to equally distribute capacity of the contest between squads */
    public function squadSize(): Attribute
    {
        return Attribute::make(
            get: function() {
                $base = intdiv($this->capacity, $this->squads);
                $arr = array_fill(1, $this->squads, $base);

                $reduction = array_reduce($arr, function($res, $a) { return $res + $a; }, 0);
                if ($reduction == $this->capacity) { return $arr; }

                if ($this->distribution == "asc") {
                    for ($i = 1; $i <= $this->squads; $i++) {
                        $arr[$i]++;
                        $reduction = array_reduce($arr, function($res, $a) { return $res + $a; }, 0);
                        if ($reduction == $this->capacity) { return $arr; }
                    }
                }
                else {
                    for ($i = $this->squads; $i > 0; $i--) {
                        $arr[$i]++;
                        $reduction = array_reduce($arr, function($res, $a) { return $res + $a; }, 0);
                        if ($reduction == $this->capacity) { return $arr; }
                    }
                }
            }
        );
    }

    /** Returns collection of divisions and count of registered */
    public function divisionCounts(): Attribute
    {
        return Attribute::make(
            get: function() {
                return $this->registrations->groupBy(function(Registration $item) {
                    return $item->division?->bgdivision;
                })->map->count();
            }
        );
    }

    /** Identifies whether the contest is LOSík */
    public function isLosik(): bool
    {
        return $this->contest_level_id == ContestLevelEnum::LOSIK->value;
    }

    /** identifies whether the contest is classification for Voluntary State Reserves */
    public function isSzsClassification(): bool
    {
        return $this->contest_level_id == ContestLevelEnum::SZSCLASSIFICATION->value;
    }

    public function getCacheKeyPrefix(string $use): string
    {
        return "contest/" . $this->id . "/" . $use . "/";
    }

    /* ========== ========== Foreign keys ========== ========== */
    /** Get the level of contest/event is placed
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */
    public function contest_level(): BelongsTo
    {
        return $this->belongsTo(ContestLevel::class);
    }

    /** Get the category of contest
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */
    public function contest_category(): BelongsTo
    {
        return $this->belongsTo(ContestCategory::class);
    }

    /** Get the range where contest is placed
    * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */
    public function range(): BelongsTo
    {
        return $this->belongsTo(Range::class);
    }

    /** Get the organizer that owns the Contest
    * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */
    public function organizer_group(): BelongsTo
    {
        return $this->belongsTo(OrganizerGroup::class);
    }

    /** Get the director of the Contest
    * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */
    public function director(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /** Get the range master of the Contest
    * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */
    public function rangemaster(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /** Registrations for the contest
    * @return \Illuminate\Database\Eloquent\Relations\HasMany */
    public function registrations() : HasMany
    {
        return $this->hasMany(Registration::class);
    }
}

Zerion Mini Shell 1.0