diff --git a/app/Filament/Pages/GuardPatrolHourlyCount.php b/app/Filament/Pages/GuardPatrolHourlyCount.php index da6b125..7f2e35d 100644 --- a/app/Filament/Pages/GuardPatrolHourlyCount.php +++ b/app/Filament/Pages/GuardPatrolHourlyCount.php @@ -68,6 +68,7 @@ class GuardPatrolHourlyCount extends Page $set('time_range', null); session()->forget('selected_time'); + session()->forget('valid_sessions'); // $this->dispatch('patrolEntryChart'); }), @@ -84,6 +85,7 @@ class GuardPatrolHourlyCount extends Page session()->forget('selected_name'); $set('time_range', null); session()->forget('selected_time'); + session()->forget('valid_sessions'); // $this->dispatch('patrolEntryChart'); }), @@ -91,14 +93,16 @@ class GuardPatrolHourlyCount extends Page ->label('Guard Name') ->options(function (callable $get) { $plantId = $get('plant'); - if (!$plantId) { + $Date = $get('date'); + if (!$plantId || !$Date) { return []; } - return GuardPatrolEntry::where('guard_patrol_entries.plant_id', $plantId) - ->join('guard_names', 'guard_patrol_entries.guard_name_id', '=', 'guard_names.id') - ->select('guard_names.id', 'guard_names.name') - ->groupBy('guard_names.id', 'guard_names.name') - ->pluck('guard_names.name', 'guard_names.id') + + return GuardPatrolEntry::with('guardNames')->where('plant_id', $plantId) + ->whereDate('patrol_time', $Date)->orderBy('patrol_time','asc') + ->get() + ->unique('guard_name_id') + ->pluck('guardNames.name', 'guard_name_id') ->toArray(); }) @@ -118,176 +122,131 @@ class GuardPatrolHourlyCount extends Page // Clear the time range field and its session $set('time_range', null); session()->forget('selected_time'); + session()->forget('valid_sessions'); }), - // Select::make('time_range') - // ->label('Patrol Time Range') - // ->options(function (callable $get) { - // $plantId = $get('plant'); - // $guardName = trim($get('guard_name')); - // $date = $get('date'); + // Select::make('time_range') + // ->label('Patrol Time Range') + // ->options(function (callable $get) { + // $plantId = $get('plant'); + // $guardId = $get('guard_name'); + // $date = $get('date'); - // if (!$plantId || !$guardName || !$date) { - // session(['valid_sessions' => []]); - // return []; - // } + // if (!$plantId || !$guardId || !$date) { + // return []; + // } - // // Get all patrols for the guard, plant, and date - // $patrols = GuardPatrolEntry::where('guard_patrol_entries.plant_id', $plantId) - // ->join('guard_names', 'guard_patrol_entries.guard_name_id', '=', 'guard_names.id') - // ->where('guard_patrol_entries.guard_name_id', $guardName) - // ->whereDate('guard_patrol_entries.patrol_time', $date) - // ->orderBy('guard_patrol_entries.patrol_time') - // ->get(['guard_patrol_entries.patrol_time', 'guard_patrol_entries.check_point_name_id']); + // $patrols = GuardPatrolEntry::where('plant_id', $plantId) + // ->where('guard_name_id', $guardId) + // ->whereDate('patrol_time', $date) + // ->orderBy('patrol_time', 'asc') + // ->get(['patrol_time']); - // if ($patrols->isEmpty()) { - // session(['valid_sessions' => []]); - // return []; - // } + // if ($patrols->isEmpty()) + // { + // return []; + // } + // $chunkSize = CheckPointTime::where('plant_id', $plantId)->count()+ 1;; + // $chunks = $patrols->chunk($chunkSize); - // $firstCheckpoint = CheckPointName::where('plant_id', $plantId) - // ->orderBy('id') - // ->first(['id', 'name']); - // $lastCheckpoint = CheckPointName::where('plant_id', $plantId) - // ->orderByDesc('id') - // ->first(['id', 'name']); + // $options = []; + // foreach ($chunks as $index => $chunk) { + // $first = $chunk->first(); + // $last = $chunk->last(); + // $start = Carbon::parse($first->patrol_time)->format('H:i:s'); + // $end = Carbon::parse($last->patrol_time)->format('H:i:s'); + // $timeRange = "$start - $end"; + // $options[$timeRange] = $timeRange; + // } - // $startCheckpointId = $firstCheckpoint->id; - // $endCheckpointId = $lastCheckpoint->id; + // return $options; + // }) + // ->reactive() + // ->required() + // ->afterStateUpdated(function ($state) { + // session(['selected_time' => $state]); + // }) + Select::make('time_range') + ->label('Patrol Time Range') + ->options(function (callable $get) { + $plantId = $get('plant'); + $guardId = $get('guard_name'); + $date = $get('date'); - // $firstPatrolCheckpointId = $patrols[0]->check_point_name_id; - // $firstPatrolCheckpointName = CheckPointName::where('id', $firstPatrolCheckpointId)->value('name'); - // $firstCheckpointName = $firstCheckpoint->name; + if (!$plantId || !$guardId || !$date) { + session(['valid_sessions' => []]); + return []; + } - // $allSessionsInvalid = ($firstPatrolCheckpointName != $firstCheckpointName); + // Get patrols with checkpoints + $patrols = GuardPatrolEntry::where('plant_id', $plantId) + ->where('guard_name_id', $guardId) + ->whereDate('patrol_time', $date) + ->orderBy('patrol_time', 'asc') + ->get(['patrol_time', 'check_point_name_id']); - // $sessions = []; - // $currentSession = []; + if ($patrols->isEmpty()) { + session(['valid_sessions' => []]); + return []; + } - // foreach ($patrols as $patrol) { - // $currentSession[] = $patrol; - // if ($patrol->check_point_name_id == $endCheckpointId) { - // $sessions[] = $currentSession; - // $currentSession = []; - // } - // } + // Get checkpoint sequence + $checkPointTimes = CheckPointTime::where('plant_id', $plantId) + ->orderBy('sequence_number') + ->get(['check_point1_id', 'check_point2_id']); - // if (!empty($currentSession)) { - // $sessions[] = $currentSession; - // } + // Build expected sequence + $expectedSequence = []; + foreach ($checkPointTimes as $row) { + $expectedSequence[] = $row->check_point1_id; + } + if ($checkPointTimes->isNotEmpty()) { + $expectedSequence[] = $checkPointTimes->last()->check_point2_id; + } - // $options = []; - // $validSessions = []; + $chunkSize = $checkPointTimes->count() + 1; + $chunks = $patrols->chunk($chunkSize); - // foreach ($sessions as $session) { - // $start = Carbon::parse($session[0]->patrol_time)->format('H:i:s'); - // $end = Carbon::parse(end($session)->patrol_time)->format('H:i:s'); - // $timeRange = "$start - $end"; - // $options[$timeRange] = $timeRange; + $options = []; + $validSessions = []; - // // Check if session is valid - // $isValid = !$allSessionsInvalid && - // ($session[0]->check_point_name_id == $startCheckpointId) && - // (end($session)->check_point_name_id == $endCheckpointId); - // $validSessions[$timeRange] = $isValid; - // } + foreach ($chunks as $index => $chunk) { + $first = $chunk->first(); + $last = $chunk->last(); + $start = Carbon::parse($first->patrol_time)->format('H:i:s'); + $end = Carbon::parse($last->patrol_time)->format('H:i:s'); + $timeRange = "$start - $end"; - // // Store validSessions in session - // session(['valid_sessions' => $validSessions]); + // Validate sequence for this chunk + $currentSeqIndex = 0; + $isValid = true; + $anyMatch = false; - // return $options; - // }) - // ->reactive() - // ->required() - // ->afterStateUpdated(function ($state) { - // session(['selected_time' => $state]); - // }), - Select::make('time_range') - ->label('Patrol Time Range') - ->options(function (callable $get) { - $plantId = $get('plant'); - $guardName = trim($get('guard_name')); - $date = $get('date'); - - if (!$plantId || !$guardName || !$date) { - session(['valid_sessions' => []]); - return []; + foreach ($chunk as $patrol) { + if ($currentSeqIndex < count($expectedSequence) && + $patrol->check_point_name_id == $expectedSequence[$currentSeqIndex]) { + $currentSeqIndex++; + $anyMatch = true; + } else { + $isValid = false; } + } - // Get all patrols for the guard, plant, and date - $patrols = GuardPatrolEntry::where('guard_patrol_entries.plant_id', $plantId) - ->join('guard_names', 'guard_patrol_entries.guard_name_id', '=', 'guard_names.id') - ->where('guard_patrol_entries.guard_name_id', $guardName) - ->whereDate('guard_patrol_entries.patrol_time', $date) - ->orderBy('guard_patrol_entries.patrol_time') - ->get(['guard_patrol_entries.patrol_time', 'guard_patrol_entries.check_point_name_id']); + // Consider valid only if at least one checkpoint matches + $isValid = $isValid && $anyMatch; + $validSessions[$timeRange] = $isValid; + $options[$timeRange] = $timeRange; + } - if ($patrols->isEmpty()) { - session(['valid_sessions' => []]); - return []; - } - - // Get the first and last sequence for the plant - $firstSequence = CheckPointTime::where('plant_id', $plantId) - ->orderBy('sequence_number') - ->first(['check_point1_id', 'check_point2_id']); - $lastSequence = CheckPointTime::where('plant_id', $plantId) - ->orderByDesc('sequence_number') - ->first(['check_point1_id', 'check_point2_id']); - - - $startCheckpointId = $firstSequence ? $firstSequence->check_point1_id : null; - - $endCheckpointId = $lastSequence ? $lastSequence->check_point2_id : null; - - $firstCheckpointName = $startCheckpointId ? CheckPointName::where('id', $startCheckpointId)->value('name') : null; - $lastCheckpointName = $endCheckpointId ? CheckPointName::where('id', $endCheckpointId)->value('name') : null; - - $firstPatrolCheckpointId = $patrols[0]->check_point_name_id; - $firstPatrolCheckpointName = CheckPointName::where('id', $firstPatrolCheckpointId)->value('name'); - - $allSessionsInvalid = ($firstPatrolCheckpointName != $firstCheckpointName); - - $sessions = []; - $currentSession = []; - - foreach ($patrols as $patrol) { - $currentSession[] = $patrol; - if ($patrol->check_point_name_id == $endCheckpointId) { - $sessions[] = $currentSession; - $currentSession = []; - } - } - - if (!empty($currentSession)) { - $sessions[] = $currentSession; - } - - $options = []; - $validSessions = []; - - foreach ($sessions as $session) { - $start = Carbon::parse($session[0]->patrol_time)->format('H:i:s'); - $end = Carbon::parse(end($session)->patrol_time)->format('H:i:s'); - $timeRange = "$start - $end"; - $options[$timeRange] = $timeRange; - - $isValid = !$allSessionsInvalid && - ($session[0]->check_point_name_id == $startCheckpointId) && - (end($session)->check_point_name_id == $endCheckpointId); - $validSessions[$timeRange] = $isValid; - } - - session(['valid_sessions' => $validSessions]); - - return $options; - }) - ->reactive() - ->required() - ->afterStateUpdated(function ($state) { - session(['selected_time' => $state]); - }), + session(['valid_sessions' => $validSessions]); + return $options; + }) + ->reactive() + ->required() + ->afterStateUpdated(function ($state) { + session(['selected_time' => $state]); + }) ]) ->columns(4); diff --git a/app/Filament/Widgets/GuardPatrolHourlyChart.php b/app/Filament/Widgets/GuardPatrolHourlyChart.php index 5aeb1f9..42787a1 100644 --- a/app/Filament/Widgets/GuardPatrolHourlyChart.php +++ b/app/Filament/Widgets/GuardPatrolHourlyChart.php @@ -18,6 +18,7 @@ class GuardPatrolHourlyChart extends ChartWidget protected int|string|array $columnSpan = 12; + // protected function getData(): array // { // $selectedPlant = session('selected_plant'); @@ -26,69 +27,96 @@ class GuardPatrolHourlyChart extends ChartWidget // $selectedTime = session('selected_time'); // $validSessions = session('valid_sessions', []); - // if (empty($selectedTime) || !isset($validSessions[$selectedTime]) || !$validSessions[$selectedTime]) { + // // if (empty($selectedTime) || !isset($validSessions[$selectedTime]) || !$validSessions[$selectedTime]) { + // // return []; + // // } + + // if (!$selectedPlant || !$selectedDate || !$selectedGuardName || empty($selectedTime)) { // return []; // } - // if (!$selectedPlant || !$selectedDate || !$selectedGuardName || empty($selectedTime)) { - // return []; - // } + // if (empty($selectedTime) || !isset($validSessions[$selectedTime]) || !$validSessions[$selectedTime]) + // { + // return $this->getInvalidSessionChartData(); + // } - // $query = GuardPatrolEntry::where('guard_patrol_entries.plant_id', $selectedPlant) - // ->where('guard_patrol_entries.guard_name_id', $selectedGuardName) - // ->whereDate('guard_patrol_entries.patrol_time', $selectedDate); - // if (!empty($selectedTime)) - // { - // [$startTime, $endTime] = explode(' - ', $selectedTime); - // $startDateTime = Carbon::parse($selectedDate . ' ' . $startTime); - // $endDateTime = Carbon::parse($selectedDate . ' ' . $endTime); - // $query->whereBetween('guard_patrol_entries.patrol_time', [$startDateTime, $endDateTime]); - // } - // $patrols = $query->orderBy('guard_patrol_entries.patrol_time')->get(); + // $query = GuardPatrolEntry::where('plant_id', $selectedPlant) + // ->where('guard_name_id', $selectedGuardName) + // ->whereDate('patrol_time', $selectedDate); - // if ($patrols->count() < 2) - // { - // return []; - // } - // $checkpointNames = CheckPointName::where('plant_id', $selectedPlant) - // ->whereIn('id', $patrols->pluck('check_point_name_id')->unique()) - // ->orderBy('id') // or another column - // ->pluck('name', 'id'); - // $nameToSequence = []; - // $sequence = 1; - // foreach ($checkpointNames as $id => $name) - // { - // $nameToSequence[$name] = $sequence++; - // } + // if (!empty($selectedTime)) { + // [$startTime, $endTime] = explode(' - ', $selectedTime); + // $startDateTime = Carbon::parse($selectedDate . ' ' . $startTime); + // $endDateTime = Carbon::parse($selectedDate . ' ' . $endTime); + // $query->whereBetween('guard_patrol_entries.patrol_time', [$startDateTime, $endDateTime]); + // } - // $sequenceNumbers = array_values($nameToSequence); + // // $patrols = $query->orderBy('guard_patrol_entries.patrol_time')->get(); + // $patrols = $query->orderBy('patrol_time')->get(); - // $cushioningData = CheckPointTime::where('plant_id', $selectedPlant) - // ->whereIn('sequence_number', $sequenceNumbers) - // ->get(['sequence_number', 'min_cushioning', 'max_cushioning']) + // if ($patrols->count() < 2) { + // return []; + // } + + // // Get all CheckPointTime records for the plant + // $cushioningData = CheckPointTime::where('plant_id', $selectedPlant) + // ->orderBy('sequence_number') + // ->get(['sequence_number', 'min_cushioning', 'max_cushioning', 'check_point1_id', 'check_point2_id']) // ->keyBy('sequence_number'); - // $numSequences = count($cushioningData); + // // Get all unique checkpoint IDs from CheckPointTime + // $checkPointIds = collect($cushioningData) + // ->flatMap(function ($item) { + // return [$item->check_point1_id, $item->check_point2_id]; + // }) + // ->unique(); - // $intervals = []; - // $labels = []; - // $colors = []; + // $checkPointNames = CheckPointName::whereIn('id', $checkPointIds) + // ->pluck('name', 'id'); + + // $sequenceToName = []; + // //$sequenceNumbers = []; + // foreach ($cushioningData as $sequenceNumber => $data) + // { + // $lastNameId = $data->check_point2_id; + // $name = $checkPointNames[$lastNameId] ?? null; + // if ($name) + // { + // $sequenceToName[$sequenceNumber] = $name; + // //$sequenceNumbers[] = $sequenceNumber; + // } + // } + + // $numSequences = count($sequenceToName); + + // // Prepare chart data + // $intervals = []; + // $labels = []; + // $colors = []; // for ($i = 0; $i < $patrols->count() - 1; $i++) // { - // // Calculate interval // $current = Carbon::parse($patrols[$i]->patrol_time); // $next = Carbon::parse($patrols[$i+1]->patrol_time); // $interval = $next->diffInMinutes($current, true); // $intervals[] = $interval; - // $labels[] = "Seq " . ($i + 1); - // $sequenceNumber = ($i % $numSequences) + 1; - // $cushioning = $cushioningData[$sequenceNumber] ?? null; + // // if ($next < $current) + // // { + // // $colors[] = '#ff4c4c'; // Red for out-of-order + // // // $intervals[] = $interval; + // // $intervals[] = 0; + // // $labels[] = "Seq " . ($i + 1); + // // continue; + // // } + // $sequenceNumber = ($i % $numSequences) + 1; + // $labels[] = "Seq " . ($i + 1); + + // $cushioning = $cushioningData[$sequenceNumber] ?? null; // if (!$cushioning) { // $colors[] = '#cccccc'; // continue; @@ -97,11 +125,9 @@ class GuardPatrolHourlyChart extends ChartWidget // $min = $cushioning->min_cushioning; // $max = $cushioning->max_cushioning; - // if ($interval < $min) - // { + // if ($interval < $min) { // $colors[] = '#ffd700'; - // } - // elseif ($interval <= $max) { + // } elseif ($interval <= $max) { // $colors[] = '#4caf50'; // } else { // $colors[] = '#ff4c4c'; @@ -122,156 +148,515 @@ class GuardPatrolHourlyChart extends ChartWidget // ]; // } - protected function getData(): array - { - $selectedPlant = session('selected_plant'); - $selectedDate = session('selected_date'); - $selectedGuardName = session('selected_name'); - $selectedTime = session('selected_time'); - $validSessions = session('valid_sessions', []); + // protected function getData(): array + // { + // $selectedPlant = session('selected_plant'); + // $selectedDate = session('selected_date'); + // $selectedGuardName = session('selected_name'); + // $selectedTime = session('selected_time'); - // if (empty($selectedTime) || !isset($validSessions[$selectedTime]) || !$validSessions[$selectedTime]) { - // return []; - // } - if (!$selectedPlant || !$selectedDate || !$selectedGuardName || empty($selectedTime)) { - return []; - } + // if (!$selectedPlant || !$selectedDate || !$selectedGuardName || empty($selectedTime)) { + // return []; + // } - if (empty($selectedTime) || !isset($validSessions[$selectedTime]) || !$validSessions[$selectedTime]) + // $query = GuardPatrolEntry::where('plant_id', $selectedPlant) + // ->where('guard_name_id', $selectedGuardName) + // ->whereDate('patrol_time', $selectedDate); + + // if (!empty($selectedTime)) { + // [$startTime, $endTime] = explode(' - ', $selectedTime); + // $startDateTime = Carbon::parse($selectedDate . ' ' . $startTime); + // $endDateTime = Carbon::parse($selectedDate . ' ' . $endTime); + // $query->whereBetween('guard_patrol_entries.patrol_time', [$startDateTime, $endDateTime]); + // } + + // $patrols = $query->orderBy('patrol_time')->get(); + + // if ($patrols->count() < 2) { + // return []; + // } + + // // Get all CheckPointTime records for the plant + // $checkPointTimes = CheckPointTime::where('plant_id', $selectedPlant) + // ->orderBy('sequence_number') + // ->get(['sequence_number', 'min_cushioning', 'max_cushioning', 'check_point1_id', 'check_point2_id']); + + // // Build the expected sequence + // $expectedSequence = []; + // foreach ($checkPointTimes as $row) { + // $expectedSequence[] = $row->check_point1_id; + // } + // if ($checkPointTimes->isNotEmpty()) { + // $expectedSequence[] = $checkPointTimes->last()->check_point2_id; + // } + + // $intervals = []; + // $labels = []; + // $colors = []; + + // $cushioningData = $checkPointTimes->keyBy('sequence_number'); + + // for ($i = 0; $i < $patrols->count() - 1; $i++) { + // $current = Carbon::parse($patrols[$i]->patrol_time); + // $next = Carbon::parse($patrols[$i+1]->patrol_time); + // $interval = $next->diffInMinutes($current, true); + // $intervals[] = $interval; + + // $labels[] = "Seq " . ($i + 1); + + // if ($i < count($expectedSequence)) { + // $expectedCheckpoint = $expectedSequence[$i]; + // $actualCheckpoint = $patrols[$i]->check_point_name_id; + // if ($expectedCheckpoint != $actualCheckpoint) { + // $colors[] = '#ff4c4c'; + // continue; + // } + // } else { + // $colors[] = '#ff4c4c'; + // continue; + // } + + // $sequenceNumber = ($i % $checkPointTimes->count()) + 1; + // $cushioning = $cushioningData[$sequenceNumber] ?? null; + // if (!$cushioning) { + // $colors[] = '#cccccc'; + // continue; + // } + + // $min = $cushioning->min_cushioning; + // $max = $cushioning->max_cushioning; + + // if ($interval < $min) { + // $colors[] = '#ffd700'; // Yellow for too fast + // } elseif ($interval <= $max) { + // $colors[] = '#4caf50'; // Green for good + // } else { + // $colors[] = '#ff4c4c'; // Red for too slow + // } + // } + + // return [ + // 'labels' => $labels, + // 'datasets' => [ + // [ + // 'label' => 'Interval (minutes)', + // 'data' => $intervals, + // 'backgroundColor' => $colors, + // 'borderColor' => '#333', + // 'borderWidth' => 1, + // ], + // ], + // ]; + // } + + // protected function getData(): array + // { + // $selectedPlant = session('selected_plant'); // Or get from request/argument + // $selectedDate = session('selected_date'); // Or get from request/argument + // $selectedGuardName = session('selected_name'); // Or get from request/argument + // $selectedTime = session('selected_time'); // Or get from request/argument + + // // Optional: If you want to avoid sessions entirely, pass these as arguments to the function. + // // For now, we'll keep them as session for minimal change. + + // if (!$selectedPlant || !$selectedDate || !$selectedGuardName || empty($selectedTime)) { + // return []; + // } + + // $query = GuardPatrolEntry::where('plant_id', $selectedPlant) + // ->where('guard_name_id', $selectedGuardName) + // ->whereDate('patrol_time', $selectedDate); + + // if (!empty($selectedTime)) { + // [$startTime, $endTime] = explode(' - ', $selectedTime); + // $startDateTime = Carbon::parse($selectedDate . ' ' . $startTime); + // $endDateTime = Carbon::parse($selectedDate . ' ' . $endTime); + // $query->whereBetween('guard_patrol_entries.patrol_time', [$startDateTime, $endDateTime]); + // } + + // $patrols = $query->orderBy('patrol_time')->get(); + + // if ($patrols->count() < 2) { + // return []; + // } + + // // Get all CheckPointTime records for the plant + // $checkPointTimes = CheckPointTime::where('plant_id', $selectedPlant) + // ->orderBy('sequence_number') + // ->get(['sequence_number', 'min_cushioning', 'max_cushioning', 'check_point1_id', 'check_point2_id']); + + // // Build the expected sequence + // $expectedSequence = []; + // foreach ($checkPointTimes as $row) { + // $expectedSequence[] = $row->check_point1_id; + // } + // if ($checkPointTimes->isNotEmpty()) { + // $expectedSequence[] = $checkPointTimes->last()->check_point2_id; + // } + + // // Prepare chart data + // $intervals = []; + // $labels = []; + // $colors = []; + + // // Key cushioning data by sequence_number + // $cushioningData = $checkPointTimes->keyBy('sequence_number'); + + // // Track if any sequence matches + // $anySequenceMatches = false; + + // // For each interval (between patrols) + // for ($i = 0; $i < $patrols->count() - 1; $i++) { + // // Check if the current checkpoint matches the expected sequence + // if ($i < count($expectedSequence)) { + // $expectedCheckpoint = $expectedSequence[$i]; + // $actualCheckpoint = $patrols[$i]->check_point_name_id; + // if ($expectedCheckpoint == $actualCheckpoint) { + // $anySequenceMatches = true; + // } + // } + // } + + // // If no sequence matches at all, show only "X" + // if (!$anySequenceMatches) { + // return [ + // 'labels' => ['X'], + // 'datasets' => [ + // [ + // 'label' => 'Interval (minutes)', + // 'data' => [0], + // 'backgroundColor' => ['#ff4c4c'], + // 'borderColor' => '#333', + // 'borderWidth' => 1, + // ], + // ], + // ]; + // } + + // // Otherwise, show the intervals as before + // for ($i = 0; $i < $patrols->count() - 1; $i++) { + // $current = Carbon::parse($patrols[$i]->patrol_time); + // $next = Carbon::parse($patrols[$i+1]->patrol_time); + // $interval = $next->diffInMinutes($current, true); + // $intervals[] = $interval; + + // $labels[] = "Seq " . ($i + 1); + + // // Check if the current checkpoint matches the expected sequence + // if ($i < count($expectedSequence)) { + // $expectedCheckpoint = $expectedSequence[$i]; + // $actualCheckpoint = $patrols[$i]->check_point_name_id; + // if ($expectedCheckpoint != $actualCheckpoint) { + // $colors[] = '#ff4c4c'; + // continue; + // } + // } else { + // $colors[] = '#ff4c4c'; + // continue; + // } + + // // If sequence is correct, apply cushioning logic + // $sequenceNumber = ($i % $checkPointTimes->count()) + 1; + // $cushioning = $cushioningData[$sequenceNumber] ?? null; + // if (!$cushioning) { + // $colors[] = '#cccccc'; + // continue; + // } + + // $min = $cushioning->min_cushioning; + // $max = $cushioning->max_cushioning; + + // if ($interval < $min) { + // $colors[] = '#ffd700'; + // } elseif ($interval <= $max) { + // $colors[] = '#4caf50'; + // } else { + // $colors[] = '#ff4c4c'; + // } + // } + + // return [ + // 'labels' => $labels, + // 'datasets' => [ + // [ + // 'label' => 'Interval (minutes)', + // 'data' => $intervals, + // 'backgroundColor' => $colors, + // 'borderColor' => '#333', + // 'borderWidth' => 1, + // ], + // ], + // ]; + // } + +// protected function getData(): array +// { +// $selectedPlant = session('selected_plant'); +// $selectedDate = session('selected_date'); +// $selectedGuardName = session('selected_name'); +// $selectedTime = session('selected_time'); + +// if (!$selectedPlant || !$selectedDate || !$selectedGuardName || empty($selectedTime)) { +// return []; +// } + +// $query = GuardPatrolEntry::where('plant_id', $selectedPlant) +// ->where('guard_name_id', $selectedGuardName) +// ->whereDate('patrol_time', $selectedDate); + +// if (!empty($selectedTime)) { +// [$startTime, $endTime] = explode(' - ', $selectedTime); +// $startDateTime = Carbon::parse($selectedDate . ' ' . $startTime); +// $endDateTime = Carbon::parse($selectedDate . ' ' . $endTime); +// $query->whereBetween('guard_patrol_entries.patrol_time', [$startDateTime, $endDateTime]); +// } + +// $patrols = $query->orderBy('patrol_time')->get(); + +// if ($patrols->count() < 2) { +// return []; +// } + +// // Get all CheckPointTime records for the plant +// $checkPointTimes = CheckPointTime::where('plant_id', $selectedPlant) +// ->orderBy('sequence_number') +// ->get(['sequence_number', 'min_cushioning', 'max_cushioning', 'check_point1_id', 'check_point2_id']); + +// // Build the expected sequence +// $expectedSequence = []; +// foreach ($checkPointTimes as $row) { +// $expectedSequence[] = $row->check_point1_id; +// } +// if ($checkPointTimes->isNotEmpty()) { +// $expectedSequence[] = $checkPointTimes->last()->check_point2_id; +// } + +// // Prepare chart data +// $intervals = []; +// $labels = []; +// $colors = []; +// $cushioningData = $checkPointTimes->keyBy('sequence_number'); + +// // Track the current position in the expected sequence +// $currentSeqIndex = 0; +// $anySequenceMatches = false; + +// for ($i = 0; $i < $patrols->count() - 1; $i++) { +// $current = Carbon::parse($patrols[$i]->patrol_time); +// $next = Carbon::parse($patrols[$i+1]->patrol_time); +// $interval = $next->diffInMinutes($current, true); +// $intervals[] = $interval; + +// $labels[] = "Seq " . ($i + 1); + +// // Check if current patrol's checkpoint matches the next expected +// if ($currentSeqIndex < count($expectedSequence) && $patrols[$i]->check_point_name_id == $expectedSequence[$currentSeqIndex]) { +// $currentSeqIndex++; +// $anySequenceMatches = true; +// // Apply cushioning logic for valid sequence +// $sequenceNumber = ($currentSeqIndex - 1) % $checkPointTimes->count() + 1; +// $cushioning = $cushioningData[$sequenceNumber] ?? null; +// if (!$cushioning) { +// $colors[] = '#cccccc'; +// continue; +// } +// $min = $cushioning->min_cushioning; +// $max = $cushioning->max_cushioning; +// if ($interval < $min) { +// $colors[] = '#ffd700'; +// } elseif ($interval <= $max) { +// $colors[] = '#4caf50'; +// } else { +// $colors[] = '#ff4c4c'; +// } +// } else { +// // Out of order: mark as red +// $colors[] = '#ff4c4c'; +// } +// } + +// // If no sequence matches at all, show only "X" +// if (!$anySequenceMatches) { +// return [ +// 'labels' => ['X'], +// 'datasets' => [ +// [ +// 'label' => 'Interval (minutes)', +// 'data' => [0], +// 'backgroundColor' => ['#ff4c4c'], +// 'borderColor' => '#333', +// 'borderWidth' => 1, +// ], +// ], +// ]; +// } + +// return [ +// 'labels' => $labels, +// 'datasets' => [ +// [ +// 'label' => 'Interval (minutes)', +// 'data' => $intervals, +// 'backgroundColor' => $colors, +// 'borderColor' => '#333', +// 'borderWidth' => 1, +// ], +// ], +// ]; +// } + + protected function getData(): array { - return $this->getInvalidSessionChartData(); - } + $selectedPlant = session('selected_plant'); + $selectedDate = session('selected_date'); + $selectedGuardName = session('selected_name'); + $selectedTime = session('selected_time'); + if (!$selectedPlant || !$selectedDate || !$selectedGuardName || empty($selectedTime)) { + return []; + } - $query = GuardPatrolEntry::where('plant_id', $selectedPlant) + $validSessions = session('valid_sessions', []); + $isValid = $validSessions[$selectedTime] ?? false; + + if (!$isValid) { + return $this->getInvalidSessionChartData(); + } + + $query = GuardPatrolEntry::where('plant_id', $selectedPlant) ->where('guard_name_id', $selectedGuardName) ->whereDate('patrol_time', $selectedDate); - - if (!empty($selectedTime)) { - [$startTime, $endTime] = explode(' - ', $selectedTime); - $startDateTime = Carbon::parse($selectedDate . ' ' . $startTime); - $endDateTime = Carbon::parse($selectedDate . ' ' . $endTime); - $query->whereBetween('guard_patrol_entries.patrol_time', [$startDateTime, $endDateTime]); - } - - // $patrols = $query->orderBy('guard_patrol_entries.patrol_time')->get(); - $patrols = $query->orderBy('patrol_time')->get(); - - if ($patrols->count() < 2) { - return []; - } - - // Get all CheckPointTime records for the plant - $cushioningData = CheckPointTime::where('plant_id', $selectedPlant) - ->orderBy('sequence_number') - ->get(['sequence_number', 'min_cushioning', 'max_cushioning', 'check_point1_id', 'check_point2_id']) - ->keyBy('sequence_number'); - - // Get all unique checkpoint IDs from CheckPointTime - $checkPointIds = collect($cushioningData) - ->flatMap(function ($item) { - return [$item->check_point1_id, $item->check_point2_id]; - }) - ->unique(); - - - $checkPointNames = CheckPointName::whereIn('id', $checkPointIds) - ->pluck('name', 'id'); - - $sequenceToName = []; - //$sequenceNumbers = []; - foreach ($cushioningData as $sequenceNumber => $data) - { - $lastNameId = $data->check_point2_id; - $name = $checkPointNames[$lastNameId] ?? null; - if ($name) - { - $sequenceToName[$sequenceNumber] = $name; - //$sequenceNumbers[] = $sequenceNumber; - } - } - - $numSequences = count($sequenceToName); - - // Prepare chart data - $intervals = []; - $labels = []; - $colors = []; - - for ($i = 0; $i < $patrols->count() - 1; $i++) - { - $current = Carbon::parse($patrols[$i]->patrol_time); - $next = Carbon::parse($patrols[$i+1]->patrol_time); - $interval = $next->diffInMinutes($current, true); - $intervals[] = $interval; - - // if ($next < $current) - // { - // $colors[] = '#ff4c4c'; // Red for out-of-order - // // $intervals[] = $interval; - // $intervals[] = "X"; - // $labels[] = "Seq " . ($i + 1); - // continue; - // } - - $sequenceNumber = ($i % $numSequences) + 1; - $labels[] = "Seq " . ($i + 1); - - $cushioning = $cushioningData[$sequenceNumber] ?? null; - if (!$cushioning) { - $colors[] = '#cccccc'; - continue; + if (!empty($selectedTime)) { + [$startTime, $endTime] = explode(' - ', $selectedTime); + $startDateTime = Carbon::parse($selectedDate . ' ' . $startTime); + $endDateTime = Carbon::parse($selectedDate . ' ' . $endTime); + $query->whereBetween('guard_patrol_entries.patrol_time', [$startDateTime, $endDateTime]); } - $min = $cushioning->min_cushioning; - $max = $cushioning->max_cushioning; + $patrols = $query->orderBy('patrol_time')->get(); - if ($interval < $min) { - $colors[] = '#ffd700'; - } elseif ($interval <= $max) { - $colors[] = '#4caf50'; - } else { - $colors[] = '#ff4c4c'; + if ($patrols->count() < 2) { + return []; } - } - return [ - 'labels' => $labels, - 'datasets' => [ - [ - 'label' => 'Interval (minutes)', - 'data' => $intervals, - 'backgroundColor' => $colors, - 'borderColor' => '#333', - 'borderWidth' => 1, + // Get all CheckPointTime records for the plant + $checkPointTimes = CheckPointTime::where('plant_id', $selectedPlant) + ->orderBy('sequence_number') + ->get(['sequence_number', 'min_cushioning', 'max_cushioning', 'check_point1_id', 'check_point2_id']); + + // Build the expected sequence + $expectedSequence = []; + foreach ($checkPointTimes as $row) { + $expectedSequence[] = $row->check_point1_id; + } + if ($checkPointTimes->isNotEmpty()) { + $expectedSequence[] = $checkPointTimes->last()->check_point2_id; + } + + // Prepare chart data + $intervals = []; + $labels = []; + $colors = []; + $cushioningData = $checkPointTimes->keyBy('sequence_number'); + + // Track the current position in the expected sequence + $currentSeqIndex = 0; + + for ($i = 0; $i < $patrols->count() - 1; $i++) { + $current = Carbon::parse($patrols[$i]->patrol_time); + $next = Carbon::parse($patrols[$i+1]->patrol_time); + $interval = $next->diffInMinutes($current, true); + $intervals[] = $interval; + + $labels[] = "Seq " . ($i + 1); + + // Check if current patrol's checkpoint matches the next expected + if ($currentSeqIndex < count($expectedSequence) && $patrols[$i]->check_point_name_id == $expectedSequence[$currentSeqIndex]) { + $currentSeqIndex++; + // Apply cushioning logic for valid sequence + $sequenceNumber = ($currentSeqIndex - 1) % $checkPointTimes->count() + 1; + $cushioning = $cushioningData[$sequenceNumber] ?? null; + if (!$cushioning) { + $colors[] = '#cccccc'; + continue; + } + $min = $cushioning->min_cushioning; + $max = $cushioning->max_cushioning; + if ($interval < $min) { + $colors[] = '#ffd700'; + } elseif ($interval <= $max) { + $colors[] = '#4caf50'; + } else { + $colors[] = '#ff4c4c'; + } + } else { + // Out of order: mark as red + $colors[] = '#ff4c4c'; + } + } + + return [ + 'labels' => $labels, + 'datasets' => [ + [ + 'label' => 'Interval (minutes)', + 'data' => $intervals, + 'backgroundColor' => $colors, + 'borderColor' => '#333', + 'borderWidth' => 1, + ], ], - ], - ]; - } - - protected function getInvalidSessionChartData(): array - { - $labels = []; - for ($i = 1; $i <= 9; $i++) { - $labels[] = "Seq " . $i; + ]; } - return [ - 'labels' => $labels, - 'datasets' => [ - [ - 'label' => 'Interval (X)', - 'data' => array_fill(0, 9, 0), // <-- Changed to 100 - 'backgroundColor' => array_fill(0, 9, '#ff4c4c'), - 'borderColor' => '#333', - 'borderWidth' => 1, + + protected function getInvalidSessionChartData(): array + { + return [ + 'labels' => ['X'], + 'datasets' => [ + [ + 'label' => 'Interval (minutes)', + 'data' => [0], + 'backgroundColor' => ['#ff4c4c'], + 'borderColor' => '#333', + 'borderWidth' => 1, + ], ], - ], - ]; - } + ]; + } + protected function getOptions(): array + { + return [ + 'scales' => [ + 'y' => [ + 'beginAtZero' => true, //Start Y-axis from 0 + 'ticks' => [ + 'stepSize' => 5, + ], + ], + ], + ]; + } + // protected function getOptions(): array + // { + // return [ + // 'plugins' => [ + // 'datalabels' => [ + // 'anchor' => 'end', + // 'align' => 'top', + // 'color' => '#000', + // 'font' => [ + // 'weight' => 'bold', + // ], + // 'formatter' => \Illuminate\Support\Js::from("function(value) { return value + ' min'; }"), + // ], + // ], + // ]; + // } protected function getType(): string {