diff --git a/app/Filament/Pages/PlayerProps.php b/app/Filament/Pages/PlayerProps.php index 21d293b0..6c65bb6c 100644 --- a/app/Filament/Pages/PlayerProps.php +++ b/app/Filament/Pages/PlayerProps.php @@ -8,6 +8,7 @@ use App\Actions\LoadStatisticFixturesMatchOptions; use App\Filament\Widgets\PlayerPropsDrop; use App\Filament\Widgets\PlayerPropsTable; use App\Models\SofaScoreRosa; +use App\Models\SsLineupMemory; use App\Models\StatisticFixtures; use BackedEnum; use Filament\Forms\Components\Select; @@ -16,6 +17,8 @@ use Filament\Forms\Contracts\HasForms; use Filament\Pages\Page; use Filament\Schemas\Components\Utilities\Get; use Filament\Schemas\Schema; +use Illuminate\Support\Facades\Auth; +use Livewire\Attributes\On; class PlayerProps extends Page implements HasForms { @@ -34,66 +37,43 @@ class PlayerProps extends Page implements HasForms protected static ?int $navigationSort = 2; - public array $boxes; - - public array $activeBoxes; - - public array $sourceRecords; - public ?array $filterData; - public array $beschriftung; - - public array $lineup; - public array $lineUpOptinos; - public array $lineUpMap; + public string $activeLineUp = '3313'; - public string $lineupActive = '3313'; + public array $players = []; + public array $clientLineUps = []; + + public int $team_id; public function mount(): void { // Initialisiert das Formular mit leeren Werten $this->form->fill(); - - $this->activeBoxes = $this->boxNames(); - $this->lineUpMap = $this->linUpMap(); - $this->lineUpOptinos = $this->lineUpOptinos(); - $this->lineup = $this->lineUpMap[$this->lineupActive]; - - for ($i = 1; $i <= 35; $i++) { - $this->boxes[$i] = []; - if (isset($this->activeBoxes[$i])) { - $this->beschriftung[$i] = $this->activeBoxes[$i]; - } else { - $this->beschriftung[$i] = ''; - } - } } public function getWidgetData(): array { return [ - 'beschriftung' => $this->beschriftung, - 'lineup' => $this->lineup, - 'boxes' => $this->boxes, + 'activeLineUp' => $this->activeLineUp, ]; } public function form(Schema $schema): Schema { return $schema - ->columns(4) + ->columns(5) ->components([ Select::make('cid') ->live() ->preload() ->searchable(false) - ->prefixIconColor(fn (Get $get): string => $get('cid') ? 'success' : 'danger') + ->prefixIconColor(fn(Get $get): string => $get('cid') ? 'success' : 'danger') ->prefixIcon('phosphor-globe-fill') ->hiddenLabel() - ->options(fn () => LoadSofaScoreCategory::load()) + ->options(fn() => LoadSofaScoreCategory::load()) ->placeholder('Country') ->afterStateUpdated(function (callable $set, $state) { $set('lid', null); @@ -103,10 +83,10 @@ class PlayerProps extends Page implements HasForms Select::make('lid') ->live() ->preload() - ->prefixIconColor(fn (Get $get): string => $get('lid') ? 'success' : 'danger') + ->prefixIconColor(fn(Get $get): string => $get('lid') ? 'success' : 'danger') ->prefixIcon('phosphor-trophy-fill') ->hiddenLabel() - ->options(fn (Get $get) => LoadStatisticFixturesLeaguesOptions::load($get('cid'))) + ->options(fn(Get $get) => LoadStatisticFixturesLeaguesOptions::load($get('cid'))) ->placeholder('League') ->afterStateUpdated(function (callable $set) { $set('mid', null); @@ -115,12 +95,13 @@ class PlayerProps extends Page implements HasForms Select::make('mid') ->live() ->hiddenLabel() - ->prefixIconColor(fn (Get $get): string => $get('mid') ? 'success' : 'danger') + ->prefixIconColor(fn(Get $get): string => $get('mid') ? 'success' : 'danger') ->prefixIcon('phosphor-calendar-check-fill') ->options(function (Get $get) { return LoadStatisticFixturesMatchOptions::load($get('lid')); }) - ->afterStateUpdated(function (callable $set) { + ->afterStateUpdated(function (callable $set, $state) { + $this->dispatch('match-update', match_id: $state); $set('tid', null); }) ->placeholder('Events'), @@ -128,7 +109,7 @@ class PlayerProps extends Page implements HasForms Select::make('tid') ->live() ->hiddenLabel() - ->prefixIconColor(fn (Get $get): string => $get('tid') ? 'success' : 'danger') + ->prefixIconColor(fn(Get $get): string => $get('tid') ? 'success' : 'danger') ->prefixIcon('phosphor-users-three-fill') ->options(function (Get $get) { if ($get('mid')) { @@ -144,33 +125,58 @@ class PlayerProps extends Page implements HasForms } }) ->placeholder('Team')->afterStateUpdated(function ($state) { - // Speichert das ausgewählte Team direkt in der Session - // session(['player_props_filter_team' => $state]); - - // Widget informieren - $this->dispatch('refreshFilters', team_id: $state); + $this->dispatch('team-update', team_id: $state); + }), + Select::make('lineup') + ->live() + ->hiddenLabel() + ->allowHtml() + ->native(false) + ->prefixIconColor('info') + ->prefixIcon('icon-soccerfield-fill') + ->options(function () { + $res = $this->lineUpOptinos(); + $arr = []; + foreach ($res as $key => $value) { + if ($this->players && in_array($key, $this->clientLineUps)) + $arr[$key] = $value . ' has lineup'; + else + $arr[$key] = $value; + } + return $arr; + }) + ->placeholder('LineUp') + ->searchable() + ->default($this->activeLineUp) + ->afterStateUpdated(function ($state) { + $this->dispatch('lineup-update', activeLineUp: $state); }), ])->statePath('filterData'); } + #[On('team-update')] + public function syncData(int $team_id) + { + $this->team_id = $team_id; + $this->clientLineUps = SsLineupMemory::where('team_id', $team_id)->where('client_id', Auth::user()->client_id)->pluck('lineup')->toArray(); + } + + #[On('update-players')] + public function updatePlayers(array $players) + { + $this->players = $players; + } protected function getFooterWidgets(): array { return [ - PlayerPropsTable::class, - PlayerPropsDrop::class, + PlayerPropsTable::make(['players' => $this->players]), + PlayerPropsDrop::make(['players' => $this->players]), ]; } - public function getFooterWidgetsColumns(): int|array { return 5; } - - private function boxNames(): array - { - return [2 => 'DR', 4 => 'MR', 6 => 'LW', 9 => 'DC', 10 => 'DM', 11 => 'MC', 12 => 'AM', 15 => 'SW', 16 => 'DC', 17 => 'DM', 18 => 'MC', 19 => 'AM', 20 => 'SM', 21 => 'ST', 23 => 'DC', 24 => 'DM', 25 => 'MC', 26 => 'AM', 30 => 'DL', 32 => 'ML', 34 => 'RW']; - } - private function lineUpOptinos(): array { return [ @@ -225,59 +231,4 @@ class PlayerProps extends Page implements HasForms '541+' => '541+', ]; } - - private function linUpMap(): array - { - return [ - '3313' => [9, 16, 23, 11, 18, 25, 19, 6, 34, 21], - '3331' => [9, 16, 23, 17, 11, 25, 12, 19, 26, 21], - '3331-' => [9, 16, 23, 10, 18, 24, 12, 19, 26, 21], - '3331+' => [9, 16, 23, 11, 18, 25, 12, 19, 26, 21], - '3412-' => [9, 16, 23, 4, 10, 24, 32, 19, 20, 21], - '3412+' => [9, 16, 23, 4, 11, 25, 32, 19, 20, 21], - '3421-' => [9, 16, 23, 4, 10, 24, 32, 12, 26, 21], - '3421+' => [9, 16, 23, 4, 11, 25, 32, 12, 26, 21], - '343-' => [9, 16, 23, 4, 10, 24, 32, 6, 34, 21], - '343+' => [9, 16, 23, 4, 11, 25, 32, 6, 34, 21], - '3511' => [9, 16, 23, 4, 11, 17, 25, 32, 19, 21], - '3511-' => [9, 16, 23, 4, 10, 18, 24, 32, 19, 21], - '3511+' => [9, 16, 23, 4, 11, 18, 25, 32, 19, 21], - '352' => [9, 16, 23, 4, 11, 17, 25, 32, 20, 21], - '352-' => [9, 16, 23, 4, 10, 18, 24, 32, 20, 21], - '352+' => [9, 16, 23, 4, 11, 18, 25, 32, 20, 21], - '4132' => [2, 9, 23, 30, 17, 12, 19, 26, 20, 21], - '4213-' => [2, 9, 23, 30, 10, 24, 19, 6, 34, 21], - '4213+' => [2, 9, 23, 30, 11, 25, 19, 6, 34, 21], - '4222' => [2, 9, 23, 30, 10, 24, 12, 26, 20, 21], - '4231' => [2, 9, 23, 30, 10, 24, 12, 19, 26, 21], - '424' => [2, 9, 23, 30, 10, 24, 6, 34, 20, 21], - '4312' => [2, 9, 23, 30, 17, 11, 25, 19, 20, 21], - '4312-' => [2, 9, 23, 30, 10, 18, 24, 19, 20, 21], - '4312+' => [2, 9, 23, 30, 11, 18, 25, 19, 20, 21], - '4321' => [2, 9, 23, 30, 17, 11, 25, 12, 26, 21], - '4321-' => [2, 9, 23, 30, 10, 18, 24, 12, 26, 21], - '4321+' => [2, 9, 23, 30, 11, 18, 25, 12, 26, 21], - '433' => [2, 9, 23, 30, 17, 11, 25, 6, 34, 21], - '433-' => [2, 9, 23, 30, 10, 18, 24, 6, 34, 21], - '433+' => [2, 9, 23, 30, 11, 18, 25, 6, 34, 21], - '4411-' => [2, 9, 23, 30, 4, 10, 24, 32, 19, 21], - '4411+' => [2, 9, 23, 30, 4, 11, 25, 32, 19, 21], - '442' => [2, 9, 23, 30, 4, 17, 18, 32, 20, 21], - '442-' => [2, 9, 23, 30, 4, 10, 24, 32, 20, 21], - '442+' => [2, 9, 23, 30, 4, 11, 25, 32, 20, 21], - '451' => [2, 9, 23, 30, 4, 17, 11, 25, 32, 21], - '451-' => [2, 9, 23, 30, 4, 10, 18, 24, 32, 21], - '451+' => [2, 9, 23, 30, 4, 11, 18, 25, 32, 21], - '523-' => [2, 9, 16, 23, 30, 10, 24, 6, 34, 21], - '523+' => [2, 9, 16, 23, 30, 11, 25, 6, 34, 21], - '5311' => [2, 9, 16, 23, 30, 17, 11, 25, 19, 21], - '5311-' => [2, 9, 16, 23, 30, 10, 18, 24, 19, 21], - '5311+' => [2, 9, 16, 23, 30, 11, 18, 25, 19, 21], - '532' => [2, 9, 16, 23, 30, 17, 11, 25, 20, 21], - '532-' => [2, 9, 16, 23, 30, 10, 18, 24, 20, 21], - '532+' => [2, 9, 16, 23, 30, 11, 18, 25, 20, 21], - '541-' => [2, 9, 16, 23, 30, 4, 10, 24, 32, 21], - '541+' => [2, 9, 16, 23, 30, 4, 11, 25, 32, 21], - ]; - } } diff --git a/app/Filament/Widgets/PlayerPropsDrop.php b/app/Filament/Widgets/PlayerPropsDrop.php index 92f6e611..ab41ae00 100644 --- a/app/Filament/Widgets/PlayerPropsDrop.php +++ b/app/Filament/Widgets/PlayerPropsDrop.php @@ -2,15 +2,583 @@ namespace App\Filament\Widgets; +use App\Livewire\PlayerCalculator; +use App\Models\SofaScorePlayerPerSeason; +use App\Models\SofaScorePlayerPosition; +use App\Models\SofaScoreRosa; +use App\Models\SsLineupMemory; +use App\Models\StatisticFixtures; +use App\Models\StatistikoDetail; +use Filament\Notifications\Notification; use Filament\Widgets\Widget; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; +use Livewire\Attributes\On; class PlayerPropsDrop extends Widget { protected string $view = 'livewire.player-props-drop'; + public float $x_value = 3; + public float $y_value = 180; + public array $activeBoxes; public array $beschriftung; - public array $lineup; - + public array $lineUpMap; + public string $activeLineUp; public array $boxes; + public string $team_name = ''; + public int $team_id = 0; + public int $match_id; + public int $player_on_field_counter; + public array $calculationVariables; + + public array $players; + + public function mount(): void + { + $this->activeBoxes = $this->boxNames(); + + $this->lineUpMap = $this->lineUpMap(); + + $this->player_on_field_counter = 0; + + for ($i = 1; $i <= 35; $i++) { + $this->boxes[$i] = []; + if (isset($this->activeBoxes[$i])) { + $this->beschriftung[$i] = $this->activeBoxes[$i]; + } else { + $this->beschriftung[$i] = ''; + } + } + + $this->lineup = $this->lineUpMap[$this->activeLineUp]; + } + + #[On('match-update')] + public function matchUpdate(int $match_id) + { + $this->match_id = $match_id; + } + + #[On('team-update')] + public function syncData(int $team_id) + { + $this->players = PlayerCalculator::load($team_id); + $this->team_name = SofaScoreRosa::where('ss_team_id', $team_id)->value('ss_team_name'); + $this->team_id = $team_id; + $this->loadPlacement(); + + $this->dispatch('update-players', players: $this->players); + } + + #[On('lineup-update')] + public function lineUpUpdate(int|string $activeLineUp) + { + $this->activeLineUp = $activeLineUp; + $this->lineup = $this->lineUpMap[$activeLineUp]; + $this->loadPlacement(); + } + + #[On('element-dropped-in-box')] + public function handleElementDropped(mixed $elementData, mixed $boxNumber): void + { + $boxNumber = (int) $boxNumber; + $player = is_array($elementData) ? $elementData : json_decode($elementData, true); + + if (! $player || ! isset($player['id'])) { + return; + } + + // when drag from field to field remove from prviouse field to prevent doubles + foreach ($this->boxes as $k => $record) { + if (count($record) && $record['id'] == (int) $player['id']) { + $this->clearBox($k); + } + } + + // when drag from source remove from proviuse field + foreach ($this->players as $k => $record) { + if ($record['id'] == (int) $player['id']) { + if ($this->boxes[$boxNumber]) { + $this->clearBox($boxNumber); + } + $this->boxes[$boxNumber] = $record; + $this->players[$k]['active'] = 1; + $this->players[$k]['pos'] = $this->activeBoxes[$boxNumber]; + + $this->player_on_field_counter++; + } + } + + $this->storePlacement(); + + if ($this->player_on_field_counter >= 10) { + $this->calculateAspg(); + } else { + $this->dispatch('update-players', players: $this->players); + } + } + + + + public function loadPlacement() + { + $this->clearResultTable(); + + if ($this->team_id) { + + $this->player_on_field_counter = 0; + + $res = SsLineupMemory::where('client_id', Auth::user()->client_id)->where('team_id', $this->team_id)->where('lineup', $this->activeLineUp)->first(); + + if ($res) { + // Log::debug('SsLineupMemory', $res->toArray()); + + $placement = json_decode($res->placement, 1); + + foreach ($this->players as $k => $record) { + + // dd($this->lineup, $record, $stored_positions); + + $id = $record['id']; + if (isset($placement[$id]) && in_array($placement[$id], $this->lineup)) { + $this->boxes[$placement[$id]] = $record; + $this->players[$k]['active'] = 1; + $this->players[$k]['pos'] = $record['pos_ori']; + + $this->player_on_field_counter++; + } + } + } + } + } + + public function storePlacement() + { + $store = []; + foreach ($this->boxes as $pos => $value) { + if ($value) { + $store[$value['id']] = $pos; + } + } + SsLineupMemory::updateOrCreate([ + 'client_id' => Auth::user()->client_id, + 'team_id' => $this->team_id, + 'lineup' => $this->activeLineUp, + ], [ + 'placement' => json_encode($store), + 'team_name' => $this->team_name, + ]); + } + + public function updateLineup(?string $state) + { + $this->clearResultTable(); + + if (isset($this->lineupsMap[$state])) { + $this->lineup = $this->lineupsMap[$state]; + } else { + $this->lineup = []; + } + } + + public function clearBox(int $boxNumber): void + { + if (isset($this->boxes[$boxNumber])) { + $tmp = $this->boxes[$boxNumber]; + $player_id = 0; + foreach ($tmp as $key => $value) { + if ($key == 'id') { + $player_id = $value; + } + } + foreach ($this->players as $k => $record) { + if ($record['id'] == (int) $player_id) { + $this->boxes[$boxNumber] = []; + $this->players[$k]['pos'] = ''; + $this->players[$k]['active'] = 0; + + $this->player_on_field_counter--; + } + } + + foreach ($this->players as $k => $record) { + $this->players[$k]['gls'] = ''; + $this->players[$k]['fls'] = ''; + $this->players[$k]['ofs'] = ''; + $this->players[$k]['snt'] = ''; + $this->players[$k]['tsh'] = ''; + $this->players[$k]['crd'] = ''; + } + + $this->storePlacement(); + } + } + + public function clearResultTable(): void + { + for ($i = 1; $i <= 35; $i++) { + $this->boxes[$i] = []; + } + foreach ($this->players as $k => $record) { + $this->players[$k]['active'] = 0; + $this->players[$k]['gls'] = ''; + $this->players[$k]['fls'] = ''; + $this->players[$k]['ofs'] = ''; + $this->players[$k]['snt'] = ''; + $this->players[$k]['tsh'] = ''; + $this->players[$k]['crd'] = ''; + } + + $this->player_on_field_counter = 0; + } + + public function copyDevelopment() + { + if ($this->player_on_field_counter < 10) { + return; + } + + $copystring = ''; + foreach ($this->calculationVariables as $row) { + if ($copystring == '') { + $keys = array_keys($row); + $copystring .= implode(';', $keys) . "\n"; + } + $copystring .= implode(';', $row) . "\n"; + } + $this->js("navigator.clipboard.writeText(`$copystring`)"); + + Notification::make() + ->title('Calculation variables copied') + ->success() + ->send(); + } + + public function copyResult() + { + if ($this->player_on_field_counter < 10) { + return; + } + $header = ['name', 'foot', 'events', 'average min', 'position', 'on field', 'gls', 'fls', 'ofs', 'snt', 'tsh', 'crd']; + $copystring = implode(';', $header) . "\n"; + foreach ($this->players as $row) { + $tmp = []; + $tmp[] = $row['name']; + $tmp[] = $row['foot']; + $tmp[] = $row['tot_evt']; + $tmp[] = $row['ave_min']; + if ($row['pos']) { + $tmp[] = $row['pos']; + } else { + $tmp[] = $row['pos_ori']; + } + $tmp[] = $row['active']; + $tmp[] = $row['gls']; + $tmp[] = $row['fls']; + $tmp[] = $row['ofs']; + $tmp[] = $row['snt']; + $tmp[] = $row['tsh']; + $tmp[] = $row['crd']; + + $copystring .= implode(';', $tmp) . "\n"; + } + $this->js("navigator.clipboard.writeText(`$copystring`)"); + + Notification::make() + ->title('Results copied') + ->success() + ->send(); + } + + public function calculateAspg($manual = false): void + { + if ($this->player_on_field_counter < 10) { + foreach ($this->players as $k => $record) { + $this->players[$k]['gls'] = ''; + $this->players[$k]['fls'] = ''; + $this->players[$k]['ofs'] = ''; + $this->players[$k]['snt'] = ''; + $this->players[$k]['tsh'] = ''; + $this->players[$k]['crd'] = ''; + } + + if ($manual) { + Notification::make()->title('Calculation needs 10 player on field') + ->info() + ->send(); + } + + return; + } + // Calcolare Aspettativa Team per GOALS + // (il valore che appare quando viene selezionato un Evento): nell' esempio, + // se scegliamo come Team il Remo (Home) il valore di riferimento sarà 1.2 + $team_id = $this->team_id; + $res = StatisticFixtures::where('id', $this->match_id)->first(); + $asp_team = 0; + if ((int) $res->home_id == (int) $team_id) { + $asp_team = (float) $res->exp_home; + } elseif ((int) $res->away_id == (int) $team_id) { + $asp_team = (float) $res->exp_away; + } + + $player = StatistikoDetail::where('ss_team_id', (int) $team_id)->where('pos', '!=', 'GK')->where('is_active', 1)->get(); + + // Aspettativa Team di Riferimento + // (ATR) = Aspettativa Team * Numero di Giocatori di Team in Rosters (esclusi i portieri) / 10. + // Ad esempio per Remo (supponiamo 24 giocatori nel Roster esclusi i portieri): ATR = 1.2 * 24 / 10 = 2.88 + + $asp_team_riferimento = (float) $asp_team * $player->count() / 10; + + $player_totals = SofaScorePlayerPerSeason::with('details')->where('season', 'total')->where('ss_team_id', $team_id)->get(); + + /*** + "id" => 35067 + "ss_player_id" => 233856 + "ss_team_id" => 3212 + "season" => "total" + "total_events" => 12 + "total_min" => 667 + "average_min" => 56 + "events_played_home" => 7 + "events_played_away" => 0 + "minutes_played_home" => 398 + "minutes_played_away" => 274 + "goals" => 0 + "fouls" => 5 + "cards" => 2 + "offsides" => 0 + "shots_on_target" => 1 + "shots_off_target" => 0 + */ + $results = []; + $this->calculationVariables = []; + foreach ($player_totals as $val) { + if ($val->details && $val->details->is_active) { + + $ss_player_id = $val->ss_player_id; + $position = $val->details->position; + + $tmp = []; + $tmp['id'] = $ss_player_id; + $tmp['name'] = $val->details->player_name; + + $tmp['asp_team'] = $asp_team; + $tmp['asp_team_riferimento'] = $asp_team_riferimento; + + $position_field = $this->get_position($ss_player_id); + if ($position_field) { + $position = $position_field; + $tmp['active'] = 1; + } else { + $tmp['active'] = 0; + } + $tmp['pos'] = $position; + + // Aspettativa di Gioco (AdG) = Somma Goals fatti da Player nel DB / Somma Minuti Giocati da Player (SMG) nel DB * 90. + // Se la SMG è < Y per quel Player prenderemo in considerazione solo l'Aspettativa Statistica (AS). + // Il valore Y dovrebbe essere configurabile in una interfaccia. Il valore iniziale lo fissiamo a Y = 180 + + // Somma Minuti Giocati da Player (SMG) nel DB + $tmp['somma_minuti'] = $val->total_min; + + // il valore corrispondente al ruolo del Player (esempio un giocatore in Details ha ruolo = RW + // quindi Aspettativa Statistica (AS) per RW = 0.219) + // exp_goals + // exp_assists + // exp_cards + // exp_fouls + // exp_was_fouled + // exp_offsides + // exp_total_shots + // exp_shots_on_target + + $bettypes = ['goals', 'cards', 'fouls', 'offsides', 'total_shots', 'shots_on_target']; + foreach ($bettypes as $bettype) { + + $asp_statistica = (float) SofaScorePlayerPosition::where('ss_code', $position)->value('exp_' . $bettype); + $tmp['asp_statistica_' . $bettype] = $asp_statistica; + + switch ($bettype) { + case 'goals': + if ($val->total_min < $this->y_value || $val->goals == 0) { + $tmp['asp_gioco_' . $bettype] = $asp_statistica; + $tmp['asp_teorica_' . $bettype] = $asp_statistica; + } else { + $asp_gioco = $val->goals / $val->total_min * 90; + $tmp['asp_gioco_' . $bettype] = $asp_gioco; + $tmp['asp_teorica_' . $bettype] = ($this->x_value * $asp_gioco + $asp_statistica) / (1 + $this->x_value); + } + break; + case 'cards': + if ($val->total_min < $this->y_value || $val->cards == 0) { + $tmp['asp_gioco_' . $bettype] = $asp_statistica; + $tmp['asp_teorica_' . $bettype] = $asp_statistica; + } else { + $asp_gioco = $val->cards / $val->total_min * 90; + $tmp['asp_gioco_' . $bettype] = $asp_gioco; + $tmp['asp_teorica_' . $bettype] = ($this->x_value * $asp_gioco + $asp_statistica) / (1 + $this->x_value); + } + break; + case 'fouls': + if ($val->total_min < $this->y_value || $val->fouls == 0) { + $tmp['asp_gioco_' . $bettype] = $asp_statistica; + $tmp['asp_teorica_' . $bettype] = $asp_statistica; + } else { + $asp_gioco = $val->fouls / $val->total_min * 90; + $tmp['asp_gioco_' . $bettype] = $asp_gioco; + $tmp['asp_teorica_' . $bettype] = ($this->x_value * $asp_gioco + $asp_statistica) / (1 + $this->x_value); + } + break; + case 'offsides': + if ($val->total_min < $this->y_value || $val->offsides == 0) { + $tmp['asp_gioco_' . $bettype] = $asp_statistica; + $tmp['asp_teorica_' . $bettype] = $asp_statistica; + } else { + $asp_gioco = $val->offsides / $val->total_min * 90; + $tmp['asp_gioco_' . $bettype] = $asp_gioco; + $tmp['asp_teorica_' . $bettype] = ($this->x_value * $asp_gioco + $asp_statistica) / (1 + $this->x_value); + } + break; + case 'total_shots': + if ($val->total_min < $this->y_value || $val->total_shots == 0) { + $tmp['asp_gioco_' . $bettype] = $asp_statistica; + $tmp['asp_teorica_' . $bettype] = $asp_statistica; + } else { + $asp_gioco = $val->total_shots / $val->total_min * 90; + $tmp['asp_gioco_' . $bettype] = $asp_gioco; + $tmp['asp_teorica_' . $bettype] = ($this->x_value * $asp_gioco + $asp_statistica) / (1 + $this->x_value); + } + break; + case 'shots_on_target': + if ($val->total_min < $this->y_value || $val->shots_on_target == 0) { + $tmp['asp_gioco_' . $bettype] = $asp_statistica; + $tmp['asp_teorica_' . $bettype] = $asp_statistica; + } else { + $asp_gioco = $val->shots_on_target / $val->total_min * 90; + $tmp['asp_gioco_' . $bettype] = $asp_gioco; + $tmp['asp_teorica_' . $bettype] = ($this->x_value * $asp_gioco + $asp_statistica) / (1 + $this->x_value); + } + break; + } + } + + // Calcolare la Somma di tutte le AT (colonna G della Tabella) + // Considerare la ATR calcolata allo Step 1 (colonna I della Tabella) + // Aspettativa per Player: AP = AT * ATR / TOT AT + $results[] = $tmp; + + Log::debug('calc', $results); + + // for dev copy + $this->calculationVariables[] = $tmp; + } + } + + $bettypes = ['goals', 'cards', 'fouls', 'offsides', 'total_shots', 'shots_on_target']; + foreach ($bettypes as $bettype) { + $total_bettype = array_sum(array_column($results, 'asp_teorica_' . $bettype)); + foreach ($results as $key => $value) { + // Aspettativa per Player: AP = AT * ATR / TOT AT + $results[$key]['asp_total_' . $bettype] = $total_bettype; + // $results[$key]['asp_player_'.$bettype] = ((float) $value['asp_team'] * (float) $value['asp_teorica_'.$bettype]) / $total_bettype; + $results[$key]['asp_player_' . $bettype] = ($asp_team * $asp_team_riferimento) / $total_bettype; + } + } + + // dd($results); + + // update frontend + foreach ($this->players as $k => $record) { + + foreach ($results as $key => $result) { + if ($record['id'] == $result['id']) { + // dd($result); + $this->players[$k]['active'] = $result['active']; + $this->players[$k]['gls'] = number_format($result['asp_player_goals'], 3); + $this->players[$k]['fls'] = number_format($result['asp_player_fouls'], 3); + $this->players[$k]['ofs'] = number_format($result['asp_player_offsides'], 3); + $this->players[$k]['snt'] = number_format($result['asp_player_total_shots'], 3); + $this->players[$k]['tsh'] = number_format($result['asp_player_shots_on_target'], 3); + $this->players[$k]['crd'] = number_format($result['asp_player_cards'], 3); + } + } + } + + $this->dispatch('update-players', players: $this->players); + } + + public function get_position(int $ss_player_id) + { + // see if player is in field and if yes get new position + foreach ($this->players as $record) { + if ($record['id'] == $ss_player_id) { + return $record['pos']; + } + } + + return false; + } + + private function boxNames(): array + { + return [2 => 'DR', 4 => 'MR', 6 => 'LW', 9 => 'DC', 10 => 'DM', 11 => 'MC', 12 => 'AM', 15 => 'SW', 16 => 'DC', 17 => 'DM', 18 => 'MC', 19 => 'AM', 20 => 'SM', 21 => 'ST', 23 => 'DC', 24 => 'DM', 25 => 'MC', 26 => 'AM', 30 => 'DL', 32 => 'ML', 34 => 'RW']; + } + + private function lineUpMap(): array + { + return [ + '3313' => [9, 16, 23, 11, 18, 25, 19, 6, 34, 21], + '3331' => [9, 16, 23, 17, 11, 25, 12, 19, 26, 21], + '3331-' => [9, 16, 23, 10, 18, 24, 12, 19, 26, 21], + '3331+' => [9, 16, 23, 11, 18, 25, 12, 19, 26, 21], + '3412-' => [9, 16, 23, 4, 10, 24, 32, 19, 20, 21], + '3412+' => [9, 16, 23, 4, 11, 25, 32, 19, 20, 21], + '3421-' => [9, 16, 23, 4, 10, 24, 32, 12, 26, 21], + '3421+' => [9, 16, 23, 4, 11, 25, 32, 12, 26, 21], + '343-' => [9, 16, 23, 4, 10, 24, 32, 6, 34, 21], + '343+' => [9, 16, 23, 4, 11, 25, 32, 6, 34, 21], + '3511' => [9, 16, 23, 4, 11, 17, 25, 32, 19, 21], + '3511-' => [9, 16, 23, 4, 10, 18, 24, 32, 19, 21], + '3511+' => [9, 16, 23, 4, 11, 18, 25, 32, 19, 21], + '352' => [9, 16, 23, 4, 11, 17, 25, 32, 20, 21], + '352-' => [9, 16, 23, 4, 10, 18, 24, 32, 20, 21], + '352+' => [9, 16, 23, 4, 11, 18, 25, 32, 20, 21], + '4132' => [2, 9, 23, 30, 17, 12, 19, 26, 20, 21], + '4213-' => [2, 9, 23, 30, 10, 24, 19, 6, 34, 21], + '4213+' => [2, 9, 23, 30, 11, 25, 19, 6, 34, 21], + '4222' => [2, 9, 23, 30, 10, 24, 12, 26, 20, 21], + '4231' => [2, 9, 23, 30, 10, 24, 12, 19, 26, 21], + '424' => [2, 9, 23, 30, 10, 24, 6, 34, 20, 21], + '4312' => [2, 9, 23, 30, 17, 11, 25, 19, 20, 21], + '4312-' => [2, 9, 23, 30, 10, 18, 24, 19, 20, 21], + '4312+' => [2, 9, 23, 30, 11, 18, 25, 19, 20, 21], + '4321' => [2, 9, 23, 30, 17, 11, 25, 12, 26, 21], + '4321-' => [2, 9, 23, 30, 10, 18, 24, 12, 26, 21], + '4321+' => [2, 9, 23, 30, 11, 18, 25, 12, 26, 21], + '433' => [2, 9, 23, 30, 17, 11, 25, 6, 34, 21], + '433-' => [2, 9, 23, 30, 10, 18, 24, 6, 34, 21], + '433+' => [2, 9, 23, 30, 11, 18, 25, 6, 34, 21], + '4411-' => [2, 9, 23, 30, 4, 10, 24, 32, 19, 21], + '4411+' => [2, 9, 23, 30, 4, 11, 25, 32, 19, 21], + '442' => [2, 9, 23, 30, 4, 17, 18, 32, 20, 21], + '442-' => [2, 9, 23, 30, 4, 10, 24, 32, 20, 21], + '442+' => [2, 9, 23, 30, 4, 11, 25, 32, 20, 21], + '451' => [2, 9, 23, 30, 4, 17, 11, 25, 32, 21], + '451-' => [2, 9, 23, 30, 4, 10, 18, 24, 32, 21], + '451+' => [2, 9, 23, 30, 4, 11, 18, 25, 32, 21], + '523-' => [2, 9, 16, 23, 30, 10, 24, 6, 34, 21], + '523+' => [2, 9, 16, 23, 30, 11, 25, 6, 34, 21], + '5311' => [2, 9, 16, 23, 30, 17, 11, 25, 19, 21], + '5311-' => [2, 9, 16, 23, 30, 10, 18, 24, 19, 21], + '5311+' => [2, 9, 16, 23, 30, 11, 18, 25, 19, 21], + '532' => [2, 9, 16, 23, 30, 17, 11, 25, 20, 21], + '532-' => [2, 9, 16, 23, 30, 10, 18, 24, 20, 21], + '532+' => [2, 9, 16, 23, 30, 11, 18, 25, 20, 21], + '541-' => [2, 9, 16, 23, 30, 4, 10, 24, 32, 21], + '541+' => [2, 9, 16, 23, 30, 4, 11, 25, 32, 21], + ]; + } } diff --git a/app/Filament/Widgets/PlayerPropsTable.php b/app/Filament/Widgets/PlayerPropsTable.php index 8c9e8d5c..69cacf34 100644 --- a/app/Filament/Widgets/PlayerPropsTable.php +++ b/app/Filament/Widgets/PlayerPropsTable.php @@ -2,138 +2,92 @@ namespace App\Filament\Widgets; -use App\Livewire\PlayerCalculator; -use App\Models\SofaScoreRosa; use App\Models\User; -use Filament\Actions\Action; use Filament\Forms\Components\Select; use Filament\Forms\Concerns\InteractsWithForms; -use Filament\Support\Enums\SlideOverPosition; -use Filament\Support\Enums\Width; use Filament\Tables\Columns\ViewColumn; use Filament\Tables\Enums\FiltersLayout; -use Filament\Tables\Filters\SelectFilter; +use Filament\Tables\Filters\Filter; use Filament\Tables\Table; use Filament\Widgets\TableWidget; -use Illuminate\Support\Facades\Auth; use Illuminate\Support\HtmlString; use Livewire\Attributes\On; -use Livewire\Attributes\Reactive; class PlayerPropsTable extends TableWidget { use InteractsWithForms; protected int|string|array $columnSpan = 2; + public int $team_id; - public string $team_name = ''; + public array $players; - // #[Reactive] - public array $sourceRecords = []; - - #[On('refreshFilters')] - public function refreshTable(?int $team_id = 0): void + #[On('update-players')] + public function updatePlayers(array $players) { - if ($team_id) { - $this->team_name = SofaScoreRosa::where('ss_team_id', $team_id)->value('ss_team_name'); - $this->sourceRecords = PlayerCalculator::load($team_id); - $this->resetTable(); - } + $this->players = $players; } public function getHeadingTable(): HtmlString { - return new HtmlString('