@extends('layouts.app-admin') @php use Carbon\Carbon; // Hacer disponibles las variables para las funciones $GLOBALS['video_result'] = $video_result ?? null; $GLOBALS['video_stats'] = $video_stats ?? null; @endphp @section('content')
{{ __('all.back_to_players') }}

{{ $user->first_name }} {{ $user->last_name }}

{{ __('all.club') }}: {{ $user->association ?? 'N/A' }}

{{ __('all.group') }}: {{ $user->group ?? 'N/A' }}

{{ __('all.subgroup') }}: {{ $user->subgroup ?? 'N/A' }}

@isset($current_game)
{{ __('all.current_test') }}: {{ \Carbon\Carbon::parse($current_game->date_time_start)->format('d/m/Y H:i') }}
@endisset
@php $year = $current_date->year; $month = $current_date->month; $firstDay = \Carbon\Carbon::create($year,$month,1); $startWeekday = $firstDay->dayOfWeek; // Convertir el día de la semana para que lunes sea 0 y domingo sea 6 $startWeekday = $startWeekday === 0 ? 6 : $startWeekday - 1; $daysInMonth = $firstDay->daysInMonth; // Obtener el primer y último día del mes actual $firstDayOfMonth = Carbon::create($year, $month, 1)->startOfDay(); $lastDayOfMonth = Carbon::create($year, $month, 1)->endOfMonth()->endOfDay(); // Asegurarnos de que test_dates sea una colección $test_dates_collection = collect($test_dates ?? []); // Calcular meses con tests $months_with_tests = []; $years_with_tests = []; foreach($test_dates_collection as $test_date) { $date = Carbon::parse($test_date); if (!isset($months_with_tests[$date->year])) { $months_with_tests[$date->year] = []; } $months_with_tests[$date->year][$date->month] = true; $years_with_tests[$date->year] = true; } // Verificar si hay tests en el mes anterior $firstDayPrevMonth = $firstDayOfMonth->copy()->subMonth()->startOfMonth(); $lastDayPrevMonth = $firstDayOfMonth->copy()->subMonth()->endOfMonth(); $hasTestsPrevMonth = $test_dates_collection->filter(function($date) use ($firstDayPrevMonth, $lastDayPrevMonth) { $d = Carbon::parse($date); return $d->between($firstDayPrevMonth, $lastDayPrevMonth); })->isNotEmpty(); // Verificar si hay tests en el mes siguiente $firstDayNextMonth = $lastDayOfMonth->copy()->addDay()->startOfDay(); $lastDayNextMonth = $lastDayOfMonth->copy()->addMonth()->endOfDay(); $hasTestsNextMonth = $test_dates_collection->filter(function($date) use ($firstDayNextMonth, $lastDayNextMonth) { $d = Carbon::parse($date); return $d->between($firstDayNextMonth, $lastDayNextMonth); })->isNotEmpty(); @endphp
{{ __('all.months.' . $current_date->month) }}
@foreach(range(1, 12) as $num)
{{ __('all.months.' . $num) }}
@endforeach
{{ $current_date->year }}
@for($y = $current_date->year - 5; $y <= $current_date->year + 5; $y++)
{{ $y }}
@endfor
@php $cell=0; @endphp @for($i=0;$i<$startWeekday;$i++) @php $cell++; @endphp @endfor @for($day=1;$day<=$daysInMonth;$day++) @php $d = \Carbon\Carbon::create($year,$month,$day)->format('Y-m-d'); $hasTest = $test_dates_collection->contains($d); $classes = $hasTest ? ' has-test ' : ''; if($d == $current_date->format('Y-m-d')) $classes .= ' selected-day '; @endphp @php $cell++; if($cell%7==0) echo ''; @endphp @endfor @while($cell%7!=0) @php $cell++; @endphp @endwhile
{{ __('all.calendar_days.L') }} {{ __('all.calendar_days.M') }} {{ __('all.calendar_days.X') }} {{ __('all.calendar_days.J') }} {{ __('all.calendar_days.V') }} {{ __('all.calendar_days.S') }} {{ __('all.calendar_days.D') }}
{{ $day }} @if($hasTest) @php $dayTests = $tests_by_date[$d] ?? collect(); @endphp @if($dayTests->isNotEmpty()) @endif @endif
@if($last_period=='anterior')
@endif
A
{{ __('all.metrics') }}
{{ __('all.current') }}
{{ __('all.last') }}
{{ __('all.global') }}
{{ __('all.performance') }}
Attention
A1 - PROCESSING
@if(isset($metrics_current['VPS'])) {{ number_format($metrics_current['VPS'],2) }}% @else N/A @endif
@if(isset($metrics_last['VPS'])) {{ number_format($metrics_last['VPS'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['VPS'])) {{ number_format($metrics_global['VPS'],2) }}% @else N/A @endif
@php $diffVPS = $metrics_performance['VPS'] ?? null; @endphp @if(!is_null($diffVPS) && !$is_current_game_in_first_three)
{{ number_format($diffVPS,2) }}%
@else
N/A
@endif
A2 - PERIPHERAL
@if(isset($metrics_current['VRP'])) {{ number_format($metrics_current['VRP'],2) }}% @else N/A @endif
@if(isset($metrics_last['VRP'])) {{ number_format($metrics_last['VRP'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['VRP'])) {{ number_format($metrics_global['VRP'],2) }}% @else N/A @endif
@php $perf = $metrics_performance['VRP'] ?? null; @endphp @if(!is_null($perf) && !$is_current_game_in_first_three)
{{ number_format($perf,2) }}%
@else
N/A
@endif
A3 - CENTRAL
@if(isset($metrics_current['VRC'])) {{ number_format($metrics_current['VRC'],2) }}% @else N/A @endif
@if(isset($metrics_last['VRC'])) {{ number_format($metrics_last['VRC'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['VRC'])) {{ number_format($metrics_global['VRC'],2) }}% @else N/A @endif
@php $perf = $metrics_performance['VRC'] ?? null; @endphp @if(!is_null($perf) && !$is_current_game_in_first_three)
{{ number_format($perf,2) }}%
@else
N/A
@endif
V1 - POSE
@if(empty($video_result) || empty($video_result['images']['face'] ?? null)) N/A @elseif(isset($video_stats['current']['static'])) {{ number_format(100 - $video_stats['current']['static'],2) }}% @else N/A @endif
@if(isset($video_stats['week']['static'])) {{ number_format(100 - $video_stats['week']['static'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($video_stats['average']['static'])) {{ number_format(100 - $video_stats['average']['static'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three)
N/A
@else @php $current_inverted = isset($video_stats['current']['static']) ? (100 - $video_stats['current']['static']) : null; $average_inverted = isset($video_stats['average']['static']) ? (100 - $video_stats['average']['static']) : null; $diffValue = ($current_inverted !== null && $average_inverted !== null) ? round($current_inverted - $average_inverted, 2) : null; @endphp @if(!is_null($diffValue) && !empty($video_result) && !empty($video_result['images']['face'] ?? null)) @php // ARREGLADO: V1 POSE solo rojo cuando es SUPERIOR (> 0) $poseClass = ''; if ($diffValue > 0) { $poseClass = 'negative'; } @endphp
{{ number_format($diffValue,2) }}%
@else
N/A
@endif @endif
Tiredness
T1 - MEMORY
@if(isset($metrics_current['M'])) {{ number_format($metrics_current['M'],2) }}% @else N/A @endif
@if(isset($metrics_last['M'])) {{ number_format($metrics_last['M'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['M'])) {{ number_format($metrics_global['M'],2) }}% @else N/A @endif
@php $perf = $metrics_performance['M'] ?? null; @endphp @if(!is_null($perf) && !$is_current_game_in_first_three)
{{ number_format($perf,2) }}%
@else
N/A
@endif
T2 - VALULESS
@if(isset($metrics_current['SIN_VALOR'])) {{ number_format($metrics_current['SIN_VALOR'],2) }}% @else N/A @endif
@if(isset($metrics_last['SIN_VALOR'])) {{ number_format($metrics_last['SIN_VALOR'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['SIN_VALOR'])) {{ number_format($metrics_global['SIN_VALOR'],2) }}% @else N/A @endif
@php $perf = $metrics_performance['SIN_VALOR'] ?? null; @endphp @if(!is_null($perf) && !$is_current_game_in_first_three)
{{ number_format($perf,2) }}%
@else
N/A
@endif
V2 - DCUE
@if(empty($video_result) || empty($video_result['images']['face'] ?? null)) N/A @elseif(isset($video_stats['current']['visio_bee']) && $video_stats['current']['visio_bee'] > 0) @php $circles_count = $video_stats['current']['visio_bee']; @endphp @for ($i = 0; $i < 6; $i++) @if ($i < $circles_count) @else @endif @endfor @else N/A @endif
@if(isset($video_stats['week']['visio_bee']) && $video_stats['week']['visio_bee'] > 0) @php $circles_count = $video_stats['week']['visio_bee']; @endphp @for ($i = 0; $i < 6; $i++) @if ($i < $circles_count) @else @endif @endfor @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($video_stats['average']['visio_bee']) && $video_stats['average']['visio_bee'] > 0) @php $circles_count = $video_stats['average']['visio_bee']; @endphp @for ($i = 0; $i < 6; $i++) @if ($i < $circles_count) @else @endif @endfor @else N/A @endif
Mental fatigue
MF1 – RESPONSIVNESS PR
@if(isset($metrics_current['CR_total_correct']) && isset($metrics_current['CR_total_incorrect'])) {{ $metrics_current['CR_total_correct'] }} in @if($metrics_current['CR_average_time'] !== null) {{ number_format($metrics_current['CR_average_time'], 3, ',', '') }}s @else  N/A @endif @else N/A @endif
@if(isset($metrics_last['CR_total_correct']) && isset($metrics_last['CR_total_incorrect'])) {{ $metrics_last['CR_total_correct'] }} in @if($metrics_last['CR_average_time'] !== null) {{ number_format($metrics_last['CR_average_time'], 3, ',', '') }}s @else N/A @endif @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['CR_total_correct']) && isset($metrics_global['CR_total_incorrect'])) {{ $metrics_global['CR_total_correct'] }} in @if($metrics_global['CR_average_time'] !== null) {{ number_format($metrics_global['CR_average_time'], 3, ',', '') }}s @else N/A @endif @else N/A @endif
@php $perfCR = $metrics_performance['CR'] ?? null; // Calcular diferencia absoluta para MF1 $current_aciertos = $metrics_current['CR_total_correct'] ?? 0; $global_aciertos = $metrics_global['CR_total_correct'] ?? 0; $current_time = $metrics_current['CR_average_time'] ?? null; $global_time = $metrics_global['CR_average_time'] ?? null; $diff_aciertos = $current_aciertos - $global_aciertos; $diff_tiempo = $current_time !== null && $global_time !== null ? $current_time - $global_time : null; $sign_aciertos = $diff_aciertos >= 0 ? '+' : ''; $sign_tiempo = $diff_tiempo !== null && $diff_tiempo >= 0 ? '+' : ''; $diff_display = $current_time === null ? "N/A" : "{$sign_aciertos}{$diff_aciertos} in ({$sign_tiempo}" . number_format($diff_tiempo, 3) . ")s"; @endphp @if(!is_null($perfCR) && isset($metrics_current['CR_total_correct']) && isset($metrics_global['CR_total_correct'])) @php $mf1_data = [ 'diff_correct' => $diff_aciertos, 'diff_time' => $current_time === null ? null : $diff_tiempo ]; $titleClass = getTitleClass('MF1', $metrics_current, $metrics_global, $metrics_performance['CR'] ?? null, $is_current_game_in_first_three); $performanceClass = str_contains($titleClass, 'text-danger') ? 'negative' : getPerformancePillClass('MF1', $mf1_data); @endphp
{{ $diff_display }}
@else
N/A
@endif
MF2 – RESPONSIVNESS C
@if(isset($metrics_current['CR_PALABRAS_total_correct']) && isset($metrics_current['CR_PALABRAS_total_incorrect'])) {{ $metrics_current['CR_PALABRAS_total_correct'] }} in @if($metrics_current['CR_PALABRAS_average_time'] !== null) {{ number_format($metrics_current['CR_PALABRAS_average_time'], 3, ',', '') }}s @else  N/A @endif @else N/A @endif
@if(isset($metrics_last['CR_PALABRAS_total_correct']) && isset($metrics_last['CR_PALABRAS_total_incorrect'])) {{ $metrics_last['CR_PALABRAS_total_correct'] }} in @if($metrics_last['CR_PALABRAS_average_time'] !== null) {{ number_format($metrics_last['CR_PALABRAS_average_time'], 3, ',', '') }}s @else N/A @endif @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['CR_PALABRAS_total_correct']) && isset($metrics_global['CR_PALABRAS_total_incorrect'])) {{ number_format($metrics_global['CR_PALABRAS_total_correct'], 2) }} in @if($metrics_global['CR_PALABRAS_average_time'] !== null) {{ number_format($metrics_global['CR_PALABRAS_average_time'], 3, ',', '') }}s @else N/A @endif @else N/A @endif
@if($is_current_game_in_first_three)
N/A
@else @php $perfCRPalabras = $metrics_performance['CR_PALABRAS'] ?? null; // Calcular diferencia absoluta para MF2 $current_aciertos = $metrics_current['CR_PALABRAS_total_correct'] ?? 0; $global_aciertos = $metrics_global['CR_PALABRAS_total_correct'] ?? 0; $current_time = $metrics_current['CR_PALABRAS_average_time'] ?? null; $global_time = $metrics_global['CR_PALABRAS_average_time'] ?? null; $diff_aciertos = $current_aciertos - $global_aciertos; $diff_tiempo = $current_time !== null && $global_time !== null ? $current_time - $global_time : null; $sign_aciertos = $diff_aciertos >= 0 ? '+' : ''; $sign_tiempo = $diff_tiempo !== null && $diff_tiempo >= 0 ? '+' : ''; $diff_display = $current_time === null ? "N/A" : "{$sign_aciertos}{$diff_aciertos} in ({$sign_tiempo}" . number_format($diff_tiempo, 3) . ")s"; @endphp @if(!is_null($perfCRPalabras) && isset($metrics_current['CR_PALABRAS_total_correct']) && isset($metrics_global['CR_PALABRAS_total_correct'])) @php $mf2_data = [ 'diff_correct' => $diff_aciertos, 'diff_time' => $current_time === null ? null : $diff_tiempo ]; $titleClass = getTitleClass('MF2', $metrics_current, $metrics_global, $metrics_performance['CR_PALABRAS'] ?? null, $is_current_game_in_first_three); $performanceClass = str_contains($titleClass, 'text-danger') ? 'negative' : getPerformancePillClass('MF2', $mf2_data); @endphp
{{ $diff_display }}
@else
N/A
@endif @endif
MF3 – RESPONSIVNESS PE
@if(isset($metrics_current['CR_FIGURAS_total_correct']) && isset($metrics_current['CR_FIGURAS_total_incorrect'])) {{ $metrics_current['CR_FIGURAS_total_correct'] }} in @if($metrics_current['CR_FIGURAS_average_time'] !== null) @if($metrics_current['CR_FIGURAS_average_time'] > 1.5)  N/A @else {{ number_format($metrics_current['CR_FIGURAS_average_time'], 3, ',', '') }}s @endif @else  N/A @endif @else N/A @endif
@if(isset($metrics_last['CR_FIGURAS_total_correct']) && isset($metrics_last['CR_FIGURAS_total_incorrect'])) {{ $metrics_last['CR_FIGURAS_total_correct'] }} in @if($metrics_last['CR_FIGURAS_average_time'] !== null) @if($metrics_last['CR_FIGURAS_average_time'] > 1.5) N/A @else {{ number_format($metrics_last['CR_FIGURAS_average_time'], 3, ',', '') }}s @endif @else N/A @endif @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['CR_FIGURAS_total_correct']) && isset($metrics_global['CR_FIGURAS_total_incorrect'])) {{ $metrics_global['CR_FIGURAS_total_correct'] }} in @if($metrics_global['CR_FIGURAS_average_time'] !== null) @if($metrics_global['CR_FIGURAS_average_time'] > 1.5) N/A @else {{ number_format($metrics_global['CR_FIGURAS_average_time'], 3, ',', '') }}s @endif @else N/A @endif @else N/A @endif
@if($is_current_game_in_first_three)
N/A
@else @php $perfCRFiguras = $metrics_performance['CR_FIGURAS'] ?? null; // Calcular diferencia absoluta para MF3 $current_aciertos = $metrics_current['CR_FIGURAS_total_correct'] ?? 0; $global_aciertos = $metrics_global['CR_FIGURAS_total_correct'] ?? 0; $current_time = $metrics_current['CR_FIGURAS_average_time'] ?? null; $global_time = $metrics_global['CR_FIGURAS_average_time'] ?? null; $diff_aciertos = $current_aciertos - $global_aciertos; $diff_tiempo = $current_time !== null && $global_time !== null ? $current_time - $global_time : null; $sign_aciertos = $diff_aciertos >= 0 ? '+' : ''; $sign_tiempo = $diff_tiempo !== null && $diff_tiempo >= 0 ? '+' : ''; $diff_display = ($current_time === null || $current_time > 1.5) ? "N/A" : "{$sign_aciertos}{$diff_aciertos} in ({$sign_tiempo}" . number_format($diff_tiempo, 3) . ")s"; @endphp @if(!is_null($perfCRFiguras) && isset($metrics_current['CR_FIGURAS_total_correct']) && isset($metrics_global['CR_FIGURAS_total_correct']) && $current_time !== null && $current_time <= 1.5) @php $mf3_data = [ 'diff_correct' => $diff_aciertos, 'diff_time' => $current_time === null ? null : $diff_tiempo ]; $titleClass = getTitleClass('MF3', $metrics_current, $metrics_global, $metrics_performance['CR_FIGURAS'] ?? null, $is_current_game_in_first_three); $performanceClass = str_contains($titleClass, 'text-danger') ? 'negative' : getPerformancePillClass('MF3', $mf3_data); @endphp
{{ $diff_display }}
@else @php $titleClass = getTitleClass('MF3', $metrics_current, $metrics_global, $metrics_performance['CR_FIGURAS'] ?? null, $is_current_game_in_first_three); $performanceClass = str_contains($titleClass, 'text-danger') ? 'negative' : ''; @endphp
@if($current_time !== null && $current_time > 1.5) N/A @else N/A @endif
@endif @endif
MF4 - ERROR
@if(isset($metrics_current['ERROR'])) {{ number_format($metrics_current['ERROR'],2) }}% @else N/A @endif
@if(isset($metrics_last['ERROR'])) {{ number_format($metrics_last['ERROR'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three) N/A @elseif(isset($metrics_global['ERROR'])) {{ number_format($metrics_global['ERROR'],2) }}% @else N/A @endif
@if($is_current_game_in_first_three)
N/A
@else @php $perf = $metrics_performance['ERROR'] ?? null; @endphp @if(!is_null($perf))
{{ number_format($perf,2) }}%
@else
N/A
@endif @endif
@if(!empty($video_result))
@if(!empty($video_result['video']))

{{ __('all.camera_view') }}

@endif
@if(!empty($video_result['images']) && !empty($video_result['images']['face']))
Face
@endif
@if(isset($video_stats)) @endif
@else

{{ __('all.no_video_data_available') }}

@endif
@php /** * colorVRtoM($key,$val): * Aplica color <70 => rojo, >=90 => verde, else => blanco * SOLO si $key está en [VRC,VRP,VPS,VPA,M]. */ function colorVRtoM($key,$val){ if(is_null($val)) return ''; if(!in_array($key,['VRC','VRP','VPS','VPA','M'])) return ''; if($val<=70) return 'bg-danger text-white'; return ''; } /** * colorPerformance($perf): * < -10 => rojo * > +10 => verde * else => sin color */ function colorPerformance($perf){ if(is_null($perf)) return ''; if($perf<=-10) return 'bg-danger text-white'; return ''; } /** * Determina si una métrica es del tipo ERROR o NOT VALUE * para los cuales la lógica de colores se invierte */ function isErrorOrNotValue($key) { return in_array(strtoupper($key), ['ERROR', 'NOT_VALUE', 'SIN_VALOR']); } /** * Determina la clase CSS para la píldora de rendimiento * según el tipo de métrica y el valor de rendimiento */ function getPerformancePillClass($key, $perf) { // Lógica específica para MF1, MF2, MF3 if ($key == 'MF1' || $key == 'MF2' || $key == 'MF3') { if (is_array($perf) && isset($perf['diff_correct']) && isset($perf['diff_time'])) { $diff_correct = $perf['diff_correct']; $diff_time = $perf['diff_time']; // Si diff_time es null (current_time era null), mostrar en rojo if ($diff_time === null) { return 'negative'; } // Rojo solo si: aciertos negativos (-) Y tiempo positivo (+) if ($diff_correct < 0 && $diff_time > 0) { return 'negative'; } return ''; } return ''; } if ($key == 'ERROR') { // Para ERROR reglas específicas - Invertido porque mayor error es malo if ($perf > 4.99) return 'negative'; if ($perf < -4.99) return ''; return ''; } else if ($key == 'SIN_VALOR') { // Para VALUELESS, umbral específico de 2.5% - Solo rojo, no verde if ($perf >= 2.5) return 'negative'; return ''; } else if (isErrorOrNotValue($key)) { // Para otros tipos NOT VALUE, la lógica se invierte (umbral 9.99%) if ($perf < -9.99) return 'negative'; if ($perf > 9.99) return ''; return ''; } else if ($key == 'V1') { // Para POSE, si current > global en más de 10% = rojo (más movimiento = peor) if ($perf > 10) return 'negative'; if ($perf < -10) return ''; return ''; } else { // Para el resto de métricas if ($perf < -9.99) return 'negative'; if ($perf > 9.99) return ''; return ''; } } // ELIMINADO: Funciones complejas - usando condiciones inline directas /** * Determina si el título de una métrica debe estar en rojo */ function getTitleClass($key, $metrics_current, $metrics_global, $perf, $is_in_first_three = false) { // NUEVA LÓGICA: Para primeros 3 tests, solo rojo si CURRENT muestra N/A o caso especial if ($is_in_first_three) { $video_result = $GLOBALS['video_result'] ?? null; $video_stats = $GLOBALS['video_stats'] ?? null; // Detectar casos donde CURRENT debe estar en rojo $shouldShowRed = false; // V1 - POSE: N/A cuando no hay video if ($key === 'V1') { $shouldShowRed = empty($video_result) || empty($video_result['images']['face'] ?? null) || !isset($video_stats['current']['static']); } // V2 - DCUE: N/A cuando no hay video o visio_bee elseif ($key === 'V2') { $shouldShowRed = empty($video_result) || empty($video_result['images']['face'] ?? null) || !isset($video_stats['current']['visio_bee']) || $video_stats['current']['visio_bee'] <= 0; } // MF1: N/A cuando no hay métricas CR o tiempo es null elseif ($key === 'MF1') { $shouldShowRed = !isset($metrics_current['CR_total_correct']) || !isset($metrics_current['CR_total_incorrect']) || $metrics_current['CR_average_time'] === null; } // MF2: N/A cuando no hay métricas CR_PALABRAS o tiempo es null elseif ($key === 'MF2') { $shouldShowRed = !isset($metrics_current['CR_PALABRAS_total_correct']) || !isset($metrics_current['CR_PALABRAS_total_incorrect']) || $metrics_current['CR_PALABRAS_average_time'] === null; } // MF3: N/A cuando tiempo > 1.5 o no hay métricas CR_FIGURAS elseif ($key === 'MF3') { $shouldShowRed = !isset($metrics_current['CR_FIGURAS_total_correct']) || !isset($metrics_current['CR_FIGURAS_total_incorrect']) || $metrics_current['CR_FIGURAS_average_time'] === null || $metrics_current['CR_FIGURAS_average_time'] > 1.5; } // Métricas básicas: N/A cuando la métrica no existe elseif (in_array($key, ['VPS', 'VRP', 'VRC', 'M', 'SIN_VALOR', 'ERROR'])) { $shouldShowRed = !isset($metrics_current[$key]); } if ($shouldShowRed) { return 'text-danger'; // CURRENT en rojo → título en rojo } else { return ''; // CURRENT normal → título normal } } if ($key == 'VPS' || $key == 'VRP' || $key == 'VRC') { // A1, A2, A3 if ($perf < -9.99) return 'text-danger'; } else if ($key == 'V1') { // ARREGLADO: V1 POSE solo rojo cuando es SUPERIOR (> 0) - misma lógica que el número $current_static = $metrics_current['static'] ?? null; $global_static = $metrics_global['static'] ?? null; if ($current_static !== null && $global_static !== null) { // Calcular diffValue igual que en la píldora de performance $current_inverted = 100 - $current_static; $global_inverted = 100 - $global_static; $diffValue = $current_inverted - $global_inverted; // Solo rojo cuando es SUPERIOR (> 0) if ($diffValue > 0) return 'text-danger'; } } else if ($key == 'V2') { // V2 DCUE - Verificar que existan ambas métricas y que sean válidas $current_vb = $metrics_current['visio_bee'] ?? null; $global_vb = $metrics_global['visio_bee'] ?? null; if ($current_vb !== null && $global_vb !== null && $current_vb > $global_vb) return 'text-danger'; } else if ($key == 'M') { // T1 - MEMORY if ($perf < -9.99) return 'text-danger'; } else if ($key == 'SIN_VALOR') { // T2 - VALUELESS: mostrar en rojo si performance >= 2.5 (más VALUELESS es peor) if ($perf >= 2.5) return 'text-danger'; } else if ($key == 'MF1' || $key == 'MF2' || $key == 'MF3') { // Mapear MF1->CR, MF2->CR_PALABRAS, MF3->CR_FIGURAS $prefix = ($key == 'MF1') ? 'CR' : (($key == 'MF2') ? 'CR_PALABRAS' : 'CR_FIGURAS'); $current_correct = $metrics_current[$prefix.'_total_correct'] ?? 0; $current_time = $metrics_current[$prefix.'_average_time'] ?? null; $global_correct = $metrics_global[$prefix.'_total_correct'] ?? 0; $global_time = $metrics_global[$prefix.'_average_time'] ?? null; // Si no hay aciertos (tiempo es null) o si el desempeño es peor que el global, mostrar en rojo if ($current_time === null || ($current_correct < $global_correct && $current_time !== null && $global_time !== null && $current_time > $global_time)) { // Log para depuración \Log::debug('MF en rojo', [ 'key' => $key, 'current_correct' => $current_correct, 'current_time' => $current_time, 'global_correct' => $global_correct, 'global_time' => $global_time, 'razon' => $current_time === null ? 'tiempo_null' : 'desempeno_inferior' ]); return 'text-danger'; } } else if ($key == 'ERROR') { // Para ERROR, si el performance es > 4.99 (peor), mostramos en rojo if ($perf > 4.99) return 'text-danger'; } return ''; } /** * Determina si un bloque debe estar en rojo */ function getBlockClass($block, $metrics_current, $metrics_global, $metrics_performance, $is_in_first_three = false) { // NUEVA LÓGICA: Para primeros 3 tests, solo rojo si algún CURRENT del bloque está coloreado if ($is_in_first_three) { $video_result = $GLOBALS['video_result'] ?? null; $video_stats = $GLOBALS['video_stats'] ?? null; $hasRedCurrent = false; if ($block == 'ATTENTION') { // Verificar si A1, A2, A3 tienen N/A en CURRENT $hasRedCurrent = !isset($metrics_current['VPS']) || !isset($metrics_current['VRP']) || !isset($metrics_current['VRC']); } elseif ($block == 'TIREDNESS') { // Verificar si T1, T2 tienen N/A en CURRENT $hasRedCurrent = !isset($metrics_current['M']) || !isset($metrics_current['SIN_VALOR']); } elseif ($block == 'MENTAL_FATIGUE') { // Verificar si MF1, MF2, MF3, MF4 tienen N/A en CURRENT $mf1_na = !isset($metrics_current['CR_total_correct']) || !isset($metrics_current['CR_total_incorrect']) || $metrics_current['CR_average_time'] === null; $mf2_na = !isset($metrics_current['CR_PALABRAS_total_correct']) || !isset($metrics_current['CR_PALABRAS_total_incorrect']) || $metrics_current['CR_PALABRAS_average_time'] === null; $mf3_na = !isset($metrics_current['CR_FIGURAS_total_correct']) || !isset($metrics_current['CR_FIGURAS_total_incorrect']) || $metrics_current['CR_FIGURAS_average_time'] === null || $metrics_current['CR_FIGURAS_average_time'] > 1.5; $mf4_na = !isset($metrics_current['ERROR']); $hasRedCurrent = $mf1_na || $mf2_na || $mf3_na || $mf4_na; } if (!$hasRedCurrent) { return ''; // No hay valores rojos en CURRENT del bloque } // Para primeros 3 tests: SOLO contar N/A, no usar performance $count_na = 0; if ($block == 'ATTENTION') { // Contar N/A en A1, A2, A3 if (!isset($metrics_current['VPS'])) $count_na++; if (!isset($metrics_current['VRP'])) $count_na++; if (!isset($metrics_current['VRC'])) $count_na++; } elseif ($block == 'TIREDNESS') { // Contar N/A en T1, T2, V2 if (!isset($metrics_current['M'])) $count_na++; if (!isset($metrics_current['SIN_VALOR'])) $count_na++; if (empty($video_result) || empty($video_result['images']['face'] ?? null) || !isset($video_stats['current']['visio_bee']) || $video_stats['current']['visio_bee'] <= 0) $count_na++; } elseif ($block == 'MENTAL_FATIGUE') { // Contar N/A en MF1, MF2, MF3, MF4 if (!isset($metrics_current['CR_total_correct']) || !isset($metrics_current['CR_total_incorrect']) || $metrics_current['CR_average_time'] === null) $count_na++; if (!isset($metrics_current['CR_PALABRAS_total_correct']) || !isset($metrics_current['CR_PALABRAS_total_incorrect']) || $metrics_current['CR_PALABRAS_average_time'] === null) $count_na++; if (!isset($metrics_current['CR_FIGURAS_total_correct']) || !isset($metrics_current['CR_FIGURAS_total_incorrect']) || $metrics_current['CR_FIGURAS_average_time'] === null || $metrics_current['CR_FIGURAS_average_time'] > 1.5) $count_na++; if (!isset($metrics_current['ERROR'])) $count_na++; } // Para primeros 3 tests: título rojo SOLO si >= 3 elementos tienen N/A return ($count_na >= 3) ? 'text-danger' : ''; } if ($block == 'ATTENTION') { // Si no hay video disponible, no mostramos en rojo // if (empty($GLOBALS['video_result']) || empty($GLOBALS['video_result']['images']['face'] ?? null)) { // return ''; // } // Contar cuántos títulos A están en rojo $count_red = 0; // Usar getTitleClass para verificar consistentemente si cada título estaría en rojo $a1_red = (getTitleClass('VPS', $metrics_current, $metrics_global, $metrics_performance['VPS'] ?? null, $is_in_first_three) == 'text-danger'); $a2_red = (getTitleClass('VRP', $metrics_current, $metrics_global, $metrics_performance['VRP'] ?? null, $is_in_first_three) == 'text-danger'); $a3_red = (getTitleClass('VRC', $metrics_current, $metrics_global, $metrics_performance['VRC'] ?? null, $is_in_first_three) == 'text-danger'); if ($a1_red) $count_red++; if ($a2_red) $count_red++; if ($a3_red) $count_red++; // Log para diagnóstico \Log::debug('Verificación de Attention en rojo', [ 'a1_red' => $a1_red, 'a2_red' => $a2_red, 'a3_red' => $a3_red, 'count_red' => $count_red ]); if ($count_red >= 3) return 'text-danger'; } else if ($block == 'TIREDNESS') { // Contar cuántos títulos T están en rojo (incluir V2) $count_red = 0; // Usar getTitleClass para verificar consistentemente si cada título estaría en rojo $t1_red = (getTitleClass('M', $metrics_current, $metrics_global, $metrics_performance['M'] ?? null, $is_in_first_three) == 'text-danger'); $t2_red = (getTitleClass('SIN_VALOR', $metrics_current, $metrics_global, $metrics_performance['SIN_VALOR'] ?? null, $is_in_first_three) == 'text-danger'); $v2_red = (getTitleClass('V2', $GLOBALS['video_stats']['current'] ?? [], $GLOBALS['video_stats']['average'] ?? [], null, $is_in_first_three) == 'text-danger'); if ($t1_red) $count_red++; if ($t2_red) $count_red++; if ($v2_red) $count_red++; if ($count_red >= 3) return 'text-danger'; } else if ($block == 'MENTAL_FATIGUE') { // Contar cuántos títulos MF están en rojo $count_red = 0; // Usar getTitleClass para verificar consistentemente si cada título estaría en rojo $mf1_red = (getTitleClass('MF1', $metrics_current, $metrics_global, $metrics_performance['CR'] ?? null, $is_in_first_three) == 'text-danger'); $mf2_red = (getTitleClass('MF2', $metrics_current, $metrics_global, $metrics_performance['CR_PALABRAS'] ?? null, $is_in_first_three) == 'text-danger'); $mf3_red = (getTitleClass('MF3', $metrics_current, $metrics_global, $metrics_performance['CR_FIGURAS'] ?? null, $is_in_first_three) == 'text-danger'); $mf4_red = (getTitleClass('ERROR', $metrics_current, $metrics_global, $metrics_performance['ERROR'] ?? null, $is_in_first_three) == 'text-danger'); if ($mf1_red) $count_red++; if ($mf2_red) $count_red++; if ($mf3_red) $count_red++; if ($mf4_red) $count_red++; if ($count_red >= 3) return 'text-danger'; } return ''; } /** * Calcula el número de bolas negras basado en el valor de darkness Z1 y Z1/Z2 * @param float $darknessZ1 Valor de darkness Z1 * @param float $z1z2 Valor de Z1/Z2 * @return int|string Número de bolas (1-6) o 'n/a' si no aplica */ function calculateDarkCircles($darknessZ1, $z1z2) { if (is_null($darknessZ1) || is_null($z1z2) || !is_numeric($darknessZ1) || !is_numeric($z1z2)) { return 'n/a'; } if ($darknessZ1 < 0) { // Para valores negativos (origen negativo) if ($z1z2 >= 0 && $z1z2 <= 9.99) return 6; if ($z1z2 >= 10 && $z1z2 <= 19.99) return 5; if ($z1z2 >= 20 && $z1z2 <= 29.99) return 4; if ($z1z2 >= 30 && $z1z2 <= 39.99) return 3; if ($z1z2 >= 40 && $z1z2 <= 49.99) return 2; if ($z1z2 >= 50) return 1; } else { // Para valores positivos (origen positivo) if ($z1z2 >= 0 && $z1z2 <= 9.99) return 1; if ($z1z2 >= 10 && $z1z2 <= 14.99) return 2; if ($z1z2 >= 15 && $z1z2 <= 19.99) return 3; if ($z1z2 >= 20 && $z1z2 <= 29.99) return 4; if ($z1z2 >= 30 && $z1z2 <= 39.99) return 5; if ($z1z2 >= 40) return 6; } return 'n/a'; } /** * Genera el HTML para mostrar las bolas negras * @param int|string $count Número de bolas a mostrar o 'n/a' * @return string HTML con las bolas */ function renderDarkCircles($count) { if ($count === 'n/a' || !is_numeric($count)) { return 'n/a'; } $html = ''; for ($i = 0; $i < 6; $i++) { if ($i < $count) { $html .= '●'; // Bola llena (negra) } else { $html .= '○'; // Bola vacía } } return $html; } @endphp @endsection