place calculator an separate page

This commit is contained in:
salam committed 2026-09-14 12:33:40 +02:00
1 parent 26052c6cfd
commit ed8a50d044
14 files changed
+720 -249

No files matched your search

+51 -100
View File
@@ -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,57 +37,34 @@ 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()
@@ -120,7 +100,8 @@ class PlayerProps extends Page implements HasForms
->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'),
@@ -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 . '<span class="text-blue-600"> has lineup</span>';
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],
];
}
}
+570 -2
View File
@@ -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],
];
}
}
+24 -70
View File
@@ -2,48 +2,37 @@
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('<div class="text-[11px] p-0 flex flex-row gap-4 font-bold font-mono" style="position: relative; left: -2px; bottom: -13px;">
return new HtmlString('
<div class="w-full grid grid-cols-15 text-[10px] items-center gap-1" style="position: relative; left: -10px; bottom: -13px;">
<div>Gls</div>
<div>Fls</div>
<div>Ofs</div>
@@ -52,56 +41,15 @@ class PlayerPropsTable extends TableWidget
<div>Crd</div>
<div>Foot</div>
<div>Evt</div>
<div>Min Ø</div>
<div>Min</div>
</div>');
}
public function table(Table $table): Table
{
return $table
->headerActions([
Action::make('esc')
->hiddenLabel()
->tooltip('Clear all (esc)')
->icon('phosphor-x-circle')
->color('gray')
->keyBindings(['esc'])
->action(fn () => $this->resetFilters()),
Action::make('lineups')
->tooltip('Lineups explanation')
->color('success')
->hiddenLabel()
->icon('phosphor-question-mark')
->slideOver()
->slideOverPosition(SlideOverPosition::Start)
->modalWidth(Width::ExtraLarge)
->modalSubmitAction(false)
->modalCancelAction(false)
->modalContent(fn () => view('filament.modals.position-abbreviation')),
Action::make('reset')
->hiddenLabel()
->tooltip('Remove all')
->icon('phosphor-arrows-clockwise')
->action(fn () => $this->clearResultTable()),
Action::make('calculate')
->tooltip('Calculate')
->hiddenLabel()
->icon('phosphor-calculator')
->action(fn () => $this->calculateAspg()),
Action::make('copy_results')
->tooltip('Copy results for pasting into a spread sheet')
->hiddenLabel()
->icon('phosphor-copy')
->action(fn () => $this->copyResult()),
Action::make('copy_development')
->tooltip('Copy calculation variables')
->hiddenLabel()
->hidden(fn () => ! in_array(Auth::user()->id, [1, 2]))
->color('warning')
->icon('phosphor-copy')
->action(fn () => $this->copyDevelopment()),
])
->heading($this->team_name)
->heading(false)
->query(User::query()->whereRaw('1 = 0')) // Verhindert DB-Abfragen
->striped()
->defaultSort('name')
@@ -114,26 +62,32 @@ class PlayerPropsTable extends TableWidget
'id' => 'playerdragtable',
])
->filters([
SelectFilter::make('area')
->columnSpanFull()
Filter::make('positions')
->columnSpan(2)
->schema([
Select::make('area')
->hiddenLabel()
->placeholder('Filter Positions')
->native(false)
->allowHtml()
->options([
'attack' => '<span class="text-amber-500">Attack</span>',
'midfield' => '<span class="text-blue-500">Midfield</span>',
'defence' => '<span class="text-green-500">Defence</span>',
'goalkeeper' => '<span class="text-gray-500">Goalkeeper</span>',
])->modifyFormFieldUsing(fn (Select $component) => $component->allowHtml())
]),
])
->query(function ($query) {
return $query;
})->indicateUsing(function (array $data): array {
// WICHTIG: Ein leeres Array sorgt dafür, dass kein Indicator-Badge erzeugt wird
// empty array disables indicator-badge
return [];
}),
], layout: FiltersLayout::AboveContent)
->deferFilters(false)
->records(function () {
$collection = collect($this->sourceRecords);
$selectedPosition = $this->tableFilters['area']['value'] ?? null;
$collection = collect($this->players);
$selectedPosition = $this->tableFilters['positions']['area'] ?? null;
if (! empty($selectedPosition)) {
$collection = $collection->where('area', $selectedPosition);
}
Generated
+6 -6
View File
@@ -81,16 +81,16 @@
},
{
"name": "anourvalar/eloquent-serialize",
"version": "1.3.11",
"version": "1.3.12",
"source": {
"type": "git",
"url": "https://github.com/AnourValar/eloquent-serialize.git",
"reference": "abd890c4d1ad8e90dd454d01283fbf342f80f1e5"
"reference": "eb46e698efe7e20c311f1f93830111fcdcdabd96"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/abd890c4d1ad8e90dd454d01283fbf342f80f1e5",
"reference": "abd890c4d1ad8e90dd454d01283fbf342f80f1e5",
"url": "https://api.github.com/repos/AnourValar/eloquent-serialize/zipball/eb46e698efe7e20c311f1f93830111fcdcdabd96",
"reference": "eb46e698efe7e20c311f1f93830111fcdcdabd96",
"shasum": ""
},
"require": {
@@ -140,9 +140,9 @@
],
"support": {
"issues": "https://github.com/AnourValar/eloquent-serialize/issues",
"source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.11"
"source": "https://github.com/AnourValar/eloquent-serialize/tree/1.3.12"
},
"time": "2026-08-07T06:14:19+00:00"
"time": "2026-09-13T06:25:37+00:00"
},
{
"name": "awcodes/light-switch",
Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

+17 -2
View File
@@ -283,7 +283,7 @@ less padding in table
}
#playerdragtable .fi-ta-content-ctn {
max-height: 800px !important;
max-height: 600px !important;
overflow-y: auto !important;
overflow-x: visible;
scrollbar-width: none;
@@ -296,5 +296,20 @@ less padding in table
position: sticky !important;
top: 0 !important;
z-index: 20 !important;
background-color: var(--fi-background-color, #ffffff) !important;
}
.warning {
@apply bg-amber-100 dark:bg-amber-700 text-amber-600 dark:text-amber-500 text-center border border-amber-300 dark:border-amber-500 rounded my-0.5
}
.info {
@apply bg-blue-100 dark:bg-blue-700 text-blue-600 dark:text-blue-400 text-center border border-blue-300 dark:border-blue-500 rounded my-0.5
}
.success {
@apply bg-green-100 dark:bg-green-700 text-green-600 dark:text-green-400 text-center border border-green-300 dark:border-green-500 rounded my-0.5
}
.gray {
@apply bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 text-center border border-gray-300 dark:border-gray-500 rounded my-0.5
}
+1 -13
View File
@@ -1,13 +1 @@
<svg viewBox="0 0 15 15" version="1.1" id="soccer"
xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path d="M11,1.5C11,2.3284,10.3284,3,9.5,3S8,2.3284,8,1.5S8.6716,0,9.5,0S11,0.6716,11,1.5z M11,11c-0.5523,0-1,0.4477-1,1
s0.4477,1,1,1s1-0.4477,1-1S11.5523,11,11,11z M12.84,6.09l-1.91-1.91l0,0C10.8399,4.0675,10.7041,4.0014,10.56,4H3.5
C3.2239,4,3,4.2239,3,4.5S3.2239,5,3.5,5h2.7L3,11.3l0,0c-0.0138,0.066-0.0138,0.134,0,0.2c-0.058,0.2761,0.1189,0.547,0.395,0.605
C3.6711,12.163,3.942,11.9861,4,11.71l0,0L5,10h2l-1.93,4.24l0,0C5.0228,14.3184,4.9986,14.4085,5,14.5
c-0.0552,0.2761,0.1239,0.5448,0.4,0.6c0.2761,0.0552,0.5448-0.1239,0.6-0.4l0,0l4.7-9.38l1.44,1.48
c0.211,0.1782,0.5264,0.1516,0.7046-0.0593C13.0037,6.5523,13.0018,6.2761,12.84,6.09z"></path>
</g>
</svg>
<svg fill="currentColor" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 961.982 961.982" xml:space="preserve"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path d="M613.297,152.741l-9.985,4.077c-6.357-22.343-12.717-44.685-19.075-67.028c-0.318-1.121-1.982-1.917-3.087-1.163 c-5.225,3.57-10.45,7.14-15.675,10.71c-9.46-20.627-18.919-41.253-28.379-61.88c-0.593-1.294-3.021-1.254-3.629,0 c-3.561,7.338-7.12,14.677-10.679,22.015c-19.294-15.25-33.032-35.329-39.555-58.095c-0.278-0.973-1.291-1.433-2.243-1.372 c-0.951-0.061-1.964,0.399-2.242,1.372c-6.522,22.766-20.261,42.845-39.555,58.095c-3.56-7.338-7.12-14.677-10.679-22.015 c-0.608-1.254-3.036-1.294-3.629,0c-9.46,20.627-18.919,41.254-28.379,61.88c-5.226-3.57-10.45-7.14-15.675-10.71 c-1.104-0.754-2.769,0.042-3.088,1.163c-6.357,22.343-12.717,44.685-19.074,67.028l-9.985-4.077 c-1.333-0.544-3.271,0.059-3.162,1.679c1.484,21.894,1.909,41.428-2.339,62.978c-0.629,3.189-5.459,35.735-9.573,35.683 c-5.758-0.073-11.583,1.588-16.02,5.067c-15.78,12.371-12.26,32.386-5.497,48.139c4.397,10.245,9.213,20.352,13.827,30.515 c3.607,7.948,6.678,16.718,12.744,23.422c4.254,4.701,10.918,8.065,17.617,8.962c0.429,1.258,0.785,2.533,0.997,3.787 c4.122,24.369,17.741,50.322,35.279,68.865c9.177,9.702,25.544,20.997,24.322,35.793c-0.551,6.678-2.892,14.982-10.289,17.125 h-14.216c0.074-0.406,0.148-0.808,0.225-1.219c0.369-1.985,0.75-4.039,1.112-6.116c0.884-5.062-0.317-10.086-3.38-14.146 c-2.936-3.889-7.331-6.486-12.159-7.21c-1.062-0.188-2.139-0.283-3.21-0.283c-6.17,0-11.851,3.144-15.194,8.407 c-4.247,6.687-7.64,13.568-10.433,20.565h-27.989c-87.512,0-158.455,70.942-158.455,158.455v298.771c0,5.523,4.477,10,10,10 H789.09c5.522,0,10-4.477,10-10v-298.77c0-87.513-70.943-158.455-158.455-158.455h-26.401 c-2.792-6.998-6.186-13.879-10.432-20.565c-3.344-5.264-9.024-8.407-15.193-8.407h-0.001c-1.07,0-2.147,0.096-3.21,0.283 c-4.827,0.724-9.223,3.321-12.159,7.21c-3.062,4.06-4.263,9.082-3.38,14.146c0.362,2.076,0.743,4.13,1.112,6.115 c0.076,0.411,0.15,0.812,0.225,1.219h-15.804c-7.397-2.143-9.737-10.447-10.289-17.125c-1.222-14.796,15.146-26.091,24.322-35.793 c17.538-18.543,31.157-44.496,35.278-68.865c0.213-1.254,0.569-2.529,0.997-3.787c6.7-0.897,13.365-4.261,17.618-8.962 c6.066-6.704,9.137-15.474,12.744-23.422c4.614-10.164,9.429-20.27,13.827-30.515c6.763-15.753,10.284-35.768-5.497-48.139 c-4.438-3.479-10.262-5.14-16.02-5.067c-4.114,0.052-8.945-32.494-9.573-35.683c-4.248-21.55-3.823-41.085-2.339-62.978 C616.568,152.8,614.63,152.197,613.297,152.741z M258.635,552.632v374.835h-35.306V557.628c0,0,10.659-17.32,35.306-27.979 V552.632z M703.346,537.643v-7.994c24.646,10.658,35.306,27.979,35.306,27.979v369.84h-35.306V537.643z M399.911,626.473v300.993 h-35.308V615.934v-10.021l10.868-3.512c0.004,0,0.008,0,0.012,0c0.805,0,16.911,12.026,24.427,17.297L399.911,626.473 L399.911,626.473z M455.269,637.357c-15.515-8.643-64.281-42.032-68.599-45.561c-2.824-2.308-7.219-3.707-11.186-3.707 c-1.454,0-2.85,0.188-4.09,0.589l-6.791,2.194l-19.396,6.27c-0.862,0.279-1.641,0.411-2.321,0.411c-2.97,0-4.121-2.52-2.552-6.443 c0,0,7.765-29.925,10.229-43.444c3.306-18.135,6.726-36.197,14.336-52.907c2.003-4.398,4.29-8.705,6.949-12.893 c0.737-1.16,1.905-1.672,3.117-1.688c2.477-0.036,5.135,1.996,4.646,4.787c-0.575,3.299-1.205,6.559-1.79,9.794 c-0.786,4.351-1.491,8.659-1.884,12.959c-0.854,9.386-0.206,18.739,4.409,28.448c1.962,2.834,4.24,5.968,6.841,9.34 c3.584,4.646,7.794,9.753,12.722,15.206c15.046,16.654,36.713,36.48,67.09,55.908 C460.368,621.456,455.882,629.237,455.269,637.357z M597.096,927.466H561.79v-80.971c5.783,1.397,11.702,2.127,17.652,2.127 s11.869-0.729,17.653-2.127V927.466z M632.767,729.883v30.844c0,23.261-14.899,45.883-35.672,54.368 c-5.527,2.258-11.464,3.527-17.653,3.527c-6.188,0-12.127-1.27-17.652-3.527c-20.772-8.486-35.672-31.107-35.672-54.368v-30.844 c0-5.523,4.478-10,10-10h25.672h35.306h25.672C628.29,719.883,632.767,724.359,632.767,729.883z M561.789,689.883V620.57 c7.929-5.527,15.855-11.42,23.45-17.622c0.395-0.23,11.856,2.565,11.856,2.565v84.37L561.789,689.883L561.789,689.883z M561.789,562.589c5.2-5.569,9.678-10.809,13.487-15.587c2.87-3.602,5.371-6.945,7.52-9.97c4.196-8.412,5.373-16.551,5.122-24.667 c-0.182-5.85-1.104-11.688-2.173-17.607c-0.585-3.235-1.215-6.495-1.79-9.795c-0.715-4.094,5.5-6.661,7.764-3.098 c2.66,4.188,4.952,8.493,6.955,12.893c8.013,17.594,11.375,36.69,14.854,55.789c2.52,13.826,5.102,27.654,9.56,40.912 c0.233,0.694,0.251,1.321,0.139,1.885c0.385,2.618-0.821,4.209-3.179,4.209c-0.68,0-1.456-0.133-2.317-0.411 c-4.328-1.399-8.656-2.798-12.983-4.196c-9.029-2.918-19.915-8.146-28.479-1.148c-4.716,3.854-9.573,7.591-14.479,11.189 c-21.58,15.831-44.114,28.978-59.802,37.497c-1.91,1.038-3.664,2.814-5.027,4.928c-1.717,2.66-2.813,5.854-2.813,8.788V755.94 c0,5.265-3.906,9.534-8.724,9.534h-7.194c-4.819,0-8.725-4.268-8.725-9.534c0,0,0-116.685,0-116.686 c0-5.687,3.8Line truncated

Before

Width:  |  Height:  |  Size: 962 B

After

Width:  |  Height:  |  Size: 5.0 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 934.247 934.248" xml:space="preserve"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path d="M109.095,751.761h343.029V581.908c-56.767-7.379-100.755-56.039-100.755-114.783c0-58.746,43.988-107.407,100.755-114.785 V182.486H109.095C48.844,182.486,0,231.329,0,291.581v32.865h127.678c8.284,0,15,6.716,15,15v28.238 c34.855,20.895,56.368,58.675,56.368,99.441c0,41.176-21.398,78.568-56.368,99.455v28.223c0,8.283-6.716,15-15,15H0v32.865 C0,702.917,48.844,751.761,109.095,751.761z"></path> <path d="M553.125,467.125c0-42.304-30.71-77.544-71.001-84.666v169.33C522.415,544.669,553.125,509.427,553.125,467.125z"></path> <rect x="821.569" y="354.446" width="112.555" height="225.356"></rect> <path d="M381.123,467.125c0,42.303,30.71,77.545,71.001,84.664v-169.33C411.833,389.579,381.123,424.82,381.123,467.125z"></path> <path d="M791.569,528.146V406.189c-16.008,15.924-25.378,37.779-25.378,60.935C766.191,490.531,775.523,512.291,791.569,528.146z"></path> <polygon points="0.124,354.446 0.124,383.555 0.124,550.693 0.124,579.802 112.679,579.802 112.679,354.446 "></polygon> <path d="M142.679,405.227v123.867c16.646-15.932,26.368-38.088,26.368-61.969C169.047,443.497,159.288,421.225,142.679,405.227z"></path> <path d="M482.124,182.486V352.34c56.767,7.378,100.755,56.039,100.755,114.785c0,58.744-43.988,107.404-100.755,114.783v169.854 h343.029c60.251,0,109.094-48.842,109.094-109.094v-32.865H806.569c-8.284,0-15-6.715-15-15v-28.836 c-34.378-20.998-55.378-58.059-55.378-98.842c0-40.375,21.106-77.823,55.378-98.835v-28.842c0-8.284,6.716-15,15-15h127.678 v-32.865c0-60.251-48.843-109.095-109.094-109.095L482.124,182.486L482.124,182.486z"></path> </g> </g> </g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+1 -18
View File
@@ -1,18 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="740" height="1110" viewBox="0 0 74 111">
<rect id="" width="74" height="111" fill="#00a000"/>
<g fill="none" stroke="#fff" stroke-width="0.5" transform="translate(3 3)">
<path id="Border" d="M 0 0 h 68 v 105 h -68 Z"/>
<path id="Centre line" d="M 0 52.5 h 68"/>
<circle id="Centre circle" r="9.15" cx="34" cy="52.5"/>
<circle id="Centre mark" r="0.75" cx="34" cy="52.5" fill="#fff" stroke="none"/>
<g id="Penalty area">
<path id="Penalty area line" d="M 13.84 0 v 16.5 h 40.32 v -16.5"/>
<path id="Goal area line" d="M 24.84 0 v 5.5 h 18.32 v -5.5"/>
<circle id="Penalty mark" r="0.75" cx="34" cy="10.94" fill="#fff" stroke="none"/>
<path id="Penalty arc" d="M 26.733027 16.5 a 9.15 9.15 0 0 0 14.533946 0"/>
</g>
<use xlink:href="#Penalty area" transform="rotate(180,34,52.5)" />
<path id="Corner arcs" d="M 0 2 a 2 2 0 0 0 2 -2M 66 0 a 2 2 0 0 0 2 2M 68 103 a 2 2 0 0 0 -2 2M 2 105 a 2 2 0 0 0 -2 -2"/>
</g>
</svg>
<svg fill="currentColor" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 964.248 964.248" xml:space="preserve"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path d="M657.668,0h-47.865H354.447h-47.865c-68.426,0-124.095,55.669-124.095,124.095v716.057 c0,68.426,55.669,124.096,124.095,124.096h47.865h255.354h47.865c68.426,0,124.096-55.67,124.096-124.096V124.094 C781.762,55.668,726.094,0,657.668,0z M369.447,30h225.354v97.679H369.447V30z M544.021,157.678 c-15.998,16.609-38.271,26.368-61.897,26.368c-23.881,0-46.038-9.722-61.969-26.368H544.021z M594.803,934.246H369.447v-97.678 h225.354v97.678H594.803z M421.101,806.568c15.855-16.045,37.615-25.377,61.023-25.377c23.155,0,45.01,9.369,60.934,25.377 H421.101z M751.762,840.152c0,51.883-42.211,94.096-94.094,94.096h-32.865v-112.68c0-8.283-6.717-15-15-15h-28.842 c-21.014-34.27-58.459-55.377-98.835-55.377c-40.782,0-77.843,21-98.841,55.377h-28.837c-8.284,0-15,6.717-15,15v112.678h-32.865 c-51.884,0-94.095-42.211-94.095-94.094V497.125h154.729c7.378,56.834,56.096,100.877,114.908,100.877 c58.813,0,107.53-44.043,114.909-100.879h154.729V840.152L751.762,840.152z M566.664,497.125 c-7.119,40.223-42.305,70.877-84.54,70.877c-42.235,0-77.42-30.654-84.54-70.877H566.664z M397.584,467.125 c7.119-40.224,42.305-70.879,84.54-70.879c42.235,0,77.42,30.655,84.54,70.879H397.584z M751.762,467.125H597.033 c-7.379-56.837-56.096-100.878-114.909-100.878c-58.812,0-107.53,44.042-114.908,100.877h-154.73V124.094 c0-51.884,42.211-94.095,94.095-94.095h32.865v112.679c0,8.284,6.716,15,15,15h28.223c20.885,34.97,58.279,56.368,99.455,56.368 c40.764,0,78.545-21.513,99.44-56.368h28.238c8.283,0,15-6.716,15-15V30h32.865c51.883,0,94.094,42.211,94.094,94.095V467.125 L751.762,467.125z"></path> </g> </g> </g></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg fill="#000000" height="300px" width="200px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 290 290" xml:space="preserve">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path color-rendering="auto" image-rendering="auto" shape-rendering="auto" color-interpolation="sRGB" d="M45,0 c-2.761,0-5,2.239-5,5v280c0,2.761,2.239,5,5,5h200c2.761,0,5-2.239,5-5V5c0-2.761-2.239-5-5-5L45,0L45,0z M50,10h50v15 c0,2.761,2.239,5,5,5h80c2.761,0,5-2.239,5-5V10h50v129.963h-50.285c-2.5-22.452-21.612-40-44.715-40 c-23.103,0-42.213,17.548-44.713,40H50V10z M110,10h70v10h-70V10z M145,109.963c17.69,0,32.229,12.997,34.643,30h-69.283 C112.773,122.96,127.31,109.963,145,109.963z M50,149.963h50.287c2.5,22.453,21.61,40,44.713,40s42.215-17.547,44.715-40H240V280 h-50v-15c0-2.761-2.239-5-5-5h-80c-2.761,0-5,2.239-5,5v15H50V149.963L50,149.963z M110.359,149.963h69.283 c-2.413,17.003-16.952,30-34.643,30C127.31,179.963,112.773,166.966,110.359,149.963z M110,270h70v10h-70C110,280,110,270,110,270z"></path> </g></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

@@ -1,4 +1,4 @@
<div>
<div class="mt-3">
<div x-data="{ activeTab: 'tab1' }">
<x-filament::tabs label="Content tabs">
<x-filament::tabs.item alpine-active="activeTab === 'tab1'" x-on:click="activeTab = 'tab1'">
@@ -1,29 +1,10 @@
@php
$record = $getRecord();
/***
"id" => 1218016
"name" => "Walter Nuñez"
"pos_ori" => "LW"
"pos" => "LW"
"foot" => "Right"
"tot_evt" => 2
"tot_min" => 102
"ave_min" => 51
"gls" => 0
"fls" => 3
"ofs" => 0
"crd" => 0
"snt" => 0
"tsh" => 0
"color_evt" => "success"
"area" => "attack"
"color_pos" => "warning"
*/
@endphp
@if ($record['active'])
<div draggable="false"
class="bgFade w-140 max-w-140 border dark:border-gray-600 border-gray-200 text-xs my-0.5 py-1 select-none rounded transition-colors flex justify-end content-center items-center gap-1 ">
<div class="w-86 text-[11px] min-w-86 text-center grid grid-cols-10 content-center items-center gap-1">
class="w-full mt-1 border dark:border-gray-600 border-gray-200 text-xs select-none rounded transition-colors grid grid-cols-16 gap-1 items-center">
<div class="col-span-10 text-[10px] text-center grid grid-cols-10 content-center items-center gap-1">
<div>{{ $record['gls'] }}</div>
<div>{{ $record['fls'] }}</div>
<div>{{ $record['ofs'] }}</div>
@@ -52,8 +33,8 @@
e.dataTransfer.effectAllowed = 'copy';
e.dataTransfer.setData('text/plain', JSON.stringify({ id: {{ $record['id'] }} }));
}"
class="w-140 max-w-140 border dark:border-gray-600 border-gray-200 hover:border-blue-500 text-xs my-0.5 mx-0 py-1 select-none cursor-grab active:cursor-grabbing rounded transition-colors flex justify-end content-center items-center gap-1">
<div class="w-86 text-[11px] min-w-86 text-center grid grid-cols-10 content-center items-center gap-1">
class="w-full mt-1 border dark:border-gray-600 border-gray-200 hover:border-blue-500 text-xs select-none cursor-grab active:cursor-grabbing rounded transition-colors grid grid-cols-16 gap-1 items-center">
<div class="col-span-10 text-[10px] text-center grid grid-cols-10 content-center items-center gap-1">
<div>{{ $record['gls'] }}</div>
<div>{{ $record['fls'] }}</div>
<div>{{ $record['ofs'] }}</div>
@@ -65,15 +46,15 @@
<div>{{ $record['ave_min'] }}</div>
<div></div>
</div>
<div class="w-18 font-stretch-ultra-condensed">
<x-filament::badge size="sm" color="{{ $record['color_pos'] }}">
<div class="text-center">
<div class="{{ $record['color_pos'] }}">
{{ ucfirst($record['pos_ori']) }}
</x-filament::badge>
</div>
<div class="text-left text-sm tracking-tight flex-1">
</div>
<div class="col-span-4 overflow-hidden font-medium">
{{ $record['name'] }}
</div>
<div class="w-8 flex justify-end">
<div class="flex justify-end">
<x-phosphor-dots-six-vertical class="h-5 w-5" />
</div>
</div>
@@ -1,10 +1,42 @@
<div class="mx-3 p-3 rounded-2xl col-span-3 grid grid-cols-7 grid-rows-5 gap-2 bg-cover bg-center bg-no-repeat aspect-7/5 shadow"
style="background-image: url({{ asset('images/soccerfield-af.jpg') }});">
@php
use Illuminate\Support\Facades\Log;
@endphp
<div class="mt-5 col-span-3 flex flex-col gap-3">
<div class="flex justify-between">
<div class="text-3xl font-bold"> {{ $team_name }} <span
class="text-sm font-light">({{ $player_on_field_counter }})</span></div>
<div class="flex gap-3">
<x-filament::modal id="custom-view-modal" slide-over width="xl">
<x-slot name="trigger">
<x-filament::button icon="phosphor-question-mark" tooltip="Lineup code explanation" />
</x-slot>
<x-slot name="header">
</x-slot>
@include('filament.modals.position-abbreviation')
<x-slot name="footer">
<div class="flex justify-end gap-x-3">
<x-filament::button color="gray"
x-on:click="$dispatch('close-modal', { id: 'custom-view-modal' })">
Close
</x-filament::button>
</div>
</x-slot>
</x-filament::modal>
<x-filament::button icon="phosphor-arrows-clockwise" tooltip="Clear all" wire:click="clearResultTable()" />
<x-filament::button icon="phosphor-calculator" tooltip="Calculate" wire:click="calculateAspg(1)" />
<x-filament::button icon="phosphor-copy" tooltip="Copy results for pasting into a spread sheet"
wire:click="copyResult()" />
<x-filament::button icon="phosphor-copy" color="warning" tooltip="Copy calculation variables"
wire:click="copyDevelopment()" />
</div>
</div>
<div class="border border-gray-500 w-full p-3 rounded grid grid-cols-7 grid-rows-5 gap-2 bg-cover bg-center bg-no-repeat aspect-7/5 shadow"
style="background-image: url({{ asset('images/soccerfield-af4.jpg') }});">
@foreach ($beschriftung as $boxNumber => $benennung)
@if ($benennung)
@if (in_array($boxNumber, $lineup))
<div x-data="{ isOver: false }" @dragover.prevent="isOver = true"
@dragenter.prevent="isOver = true" @dragleave.prevent="isOver = false"
<div x-data="{ isOver: false }" @dragover.prevent="isOver = true" @dragenter.prevent="isOver = true"
@dragleave.prevent="isOver = false"
@drop.prevent="
isOver = false;
const rawData = $event.dataTransfer.getData('text/plain');
@@ -48,8 +80,8 @@
@endif
</div>
@else
<div x-data="{ isOver: false }" @dragover.prevent="isOver = true"
@dragenter.prevent="isOver = true" @dragleave.prevent="isOver = false"
<div x-data="{ isOver: false }" @dragover.prevent="isOver = true" @dragenter.prevent="isOver = true"
@dragleave.prevent="isOver = false"
@drop.prevent="
isOver = false;
const rawData = $event.dataTransfer.getData('text/plain');
@@ -66,3 +98,4 @@
@endif
@endforeach
</div>
</div>