@extends('backend.admin_backend.admin_dashboard') @section('admin') @php /* |-------------------------------------------------------------------------- | ================================================================ | AGM SMARTSCHOOL - PROFESSIONAL RESULT ANALYSIS DASHBOARD | ================================================================ | | IMPORTANT: | We are using the Result "total" column for this analysis. | | Your Result table already stores: | CA1 + CA2 + CA3 + Exam -> Final Total | | Therefore, we DO NOT recalculate the final result here. | We simply analyze the final "total" already stored in the database. | | Since total is out of 100: | | Average Score = Percentage Performance | | Example: | Average total = 72.5 | Percentage performance = 72.5% | |-------------------------------------------------------------------------- */ use App\Models\Student; use App\Models\StudentClasses; use App\Models\Teacher; use App\Models\Subject; use App\Models\Result; use App\Models\CbtTest; use App\Models\CbtAttempt; use App\Models\Term; use App\Models\AcademicSession; use Illuminate\Support\Facades\DB; /* |-------------------------------------------------------------------------- | ================================================================ | 1. BASIC SCHOOL INFORMATION | ================================================================ |-------------------------------------------------------------------------- */ $totalstudent = Student::count(); $totalsubject = Subject::count(); $totalclass = StudentClasses::count(); $totalteachers = Teacher::count(); /* |-------------------------------------------------------------------------- | ================================================================ | 2. CURRENT TERM AND CURRENT SESSION | ================================================================ |-------------------------------------------------------------------------- | | We use the current term/session as the default values in the | Analysis Filter. | |-------------------------------------------------------------------------- */ $currentTerm = Term::where('is_current', 1)->first(); $currentSession = AcademicSession::where('is_current', 1)->first(); $currentTermName = $currentTerm ? $currentTerm->name : null; $currentSessionName = $currentSession ? $currentSession->name : null; /* |-------------------------------------------------------------------------- | ================================================================ | 3. ANALYSIS FILTER VALUES | ================================================================ |-------------------------------------------------------------------------- | | The administrator can select: | | - Academic Session | - Term | - Class | | If nothing is selected, the dashboard automatically uses: | | Current Session | Current Term | All Classes | |-------------------------------------------------------------------------- */ $analysisSession = request('analysis_session', $currentSessionName); $analysisTerm = request('analysis_term', $currentTermName); $analysisClass = request('analysis_class', 'all'); /* |-------------------------------------------------------------------------- | ================================================================ | 4. LOAD FILTER OPTIONS | ================================================================ |-------------------------------------------------------------------------- */ $analysisSessions = AcademicSession::orderByDesc('name')->get(); $analysisTerms = Term::orderBy('id')->get(); $analysisClasses = StudentClasses::orderBy('class_name')->get(); /* |-------------------------------------------------------------------------- | ================================================================ | 5. GET RESULT DATA FOR THE SELECTED FILTER | ================================================================ |-------------------------------------------------------------------------- | | We only analyze results belonging to: | | Selected Session | Selected Term | Selected Class (if selected) | |-------------------------------------------------------------------------- */ $analysisResultsQuery = Result::with([ 'student', 'subject', 'studentClass' ]) ->where('session', $analysisSession) ->where('term', $analysisTerm); /* |-------------------------------------------------------------------------- | If administrator selected a specific class, | restrict the analysis to that class. |-------------------------------------------------------------------------- */ if ($analysisClass !== 'all' && !empty($analysisClass)) { $analysisResultsQuery->where( 'student_classes_id', $analysisClass ); } /* |-------------------------------------------------------------------------- | Execute the query. |-------------------------------------------------------------------------- */ $analysisResults = $analysisResultsQuery->get(); /* |-------------------------------------------------------------------------- | ================================================================ | 6. BASIC RESULT COUNTS | ================================================================ |-------------------------------------------------------------------------- */ $totalResultRecords = $analysisResults->count(); $totalStudentsAssessed = $analysisResults ->pluck('student_id') ->unique() ->count(); $totalSubjectsAssessed = $analysisResults ->pluck('subject_id') ->unique() ->count(); /* |-------------------------------------------------------------------------- | ================================================================ | 7. ALL STUDENTS IN SELECTED CLASS | ================================================================ |-------------------------------------------------------------------------- | | This is different from "Students Assessed". | | Example: | | Class has 40 students. | Only 35 students have results. | | Total Students = 40 | Students Assessed = 35 | | This helps the administrator identify incomplete results. | |-------------------------------------------------------------------------- */ $studentsQuery = Student::query(); if ($analysisClass !== 'all' && !empty($analysisClass)) { $studentsQuery->where( 'student_classes_id', $analysisClass ); } $totalStudentsInFilter = $studentsQuery->count(); /* |-------------------------------------------------------------------------- | ================================================================ | 8. OVERALL AVERAGE SCORE | ================================================================ |-------------------------------------------------------------------------- | | We calculate the average of all final result totals. | | Example: | | 70 + 80 + 60 = 210 | | 210 / 3 = 70 | | Overall performance = 70% | |-------------------------------------------------------------------------- */ $overallAverage = $analysisResults->count() > 0 ? round($analysisResults->avg('total'), 2) : 0; /* |-------------------------------------------------------------------------- | Because final total is already out of 100, | the average itself represents percentage performance. |-------------------------------------------------------------------------- */ $overallPercentage = $overallAverage; /* |-------------------------------------------------------------------------- | ================================================================ | 9. HIGHEST AND LOWEST SCORE | ================================================================ |-------------------------------------------------------------------------- */ $highestScore = $analysisResults->count() > 0 ? round($analysisResults->max('total'), 2) : 0; $lowestScore = $analysisResults->count() > 0 ? round($analysisResults->min('total'), 2) : 0; /* |-------------------------------------------------------------------------- | ================================================================ | 10. PASS AND FAIL ANALYSIS | ================================================================ |-------------------------------------------------------------------------- | | We use 40 as the pass mark. | | You can change this later if your school uses another pass mark. | |-------------------------------------------------------------------------- */ $passMark = 40; /* |-------------------------------------------------------------------------- | Count passed result records. |-------------------------------------------------------------------------- */ $passedResultRecords = $analysisResults ->filter(function ($result) use ($passMark) { return (float) $result->total >= $passMark; }) ->count(); /* |-------------------------------------------------------------------------- | Count failed result records. |-------------------------------------------------------------------------- */ $failedResultRecords = $analysisResults ->filter(function ($result) use ($passMark) { return (float) $result->total < $passMark; }) ->count(); /* |-------------------------------------------------------------------------- | Pass percentage |-------------------------------------------------------------------------- */ $passPercentage = $totalResultRecords > 0 ? round( ($passedResultRecords / $totalResultRecords) * 100, 2 ) : 0; /* |-------------------------------------------------------------------------- | Fail percentage |-------------------------------------------------------------------------- */ $failPercentage = $totalResultRecords > 0 ? round( ($failedResultRecords / $totalResultRecords) * 100, 2 ) : 0; /* |-------------------------------------------------------------------------- | ================================================================ | 11. STUDENT OVERALL PERFORMANCE | ================================================================ |-------------------------------------------------------------------------- | | IMPORTANT: | | We do NOT simply rank individual subject scores. | | Instead, we group all subjects belonging to each student. | | Example: | | John: | Mathematics = 80 | English = 70 | Biology = 90 | | John Average: | | (80 + 70 + 90) / 3 = 80 | |-------------------------------------------------------------------------- */ $studentPerformance = $analysisResults ->groupBy('student_id') ->map(function ($studentResults) { /* |-------------------------------------------------------------------------- | Calculate student's average score across all subjects. |-------------------------------------------------------------------------- */ $average = $studentResults->avg('total'); $student = $studentResults->first()->student; $class = $studentResults->first()->studentClass; return [ 'student_id' => $studentResults->first()->student_id, 'student' => $student, 'class' => $class, 'subjects' => $studentResults->count(), 'total_score' => $studentResults->sum('total'), 'average' => round($average, 2), 'percentage' => round($average, 2), ]; }) ->sortByDesc('average') ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 12. SCHOOL/STUDENT AVERAGE | ================================================================ |-------------------------------------------------------------------------- | | This is the average of each student's overall average. | | We use this figure to determine: | | Above Average Students | Below Average Students | |-------------------------------------------------------------------------- */ $studentOverallAverage = $studentPerformance->count() > 0 ? round($studentPerformance->avg('average'), 2) : 0; /* |-------------------------------------------------------------------------- | ================================================================ | 13. STUDENTS ABOVE AVERAGE | ================================================================ |-------------------------------------------------------------------------- */ $studentsAboveAverage = $studentPerformance ->filter(function ($student) use ($studentOverallAverage) { return $student['average'] > $studentOverallAverage; }) ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 14. STUDENTS BELOW AVERAGE | ================================================================ |-------------------------------------------------------------------------- */ $studentsBelowAverage = $studentPerformance ->filter(function ($student) use ($studentOverallAverage) { return $student['average'] < $studentOverallAverage; }) ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 15. STUDENTS EXACTLY AT AVERAGE | ================================================================ |-------------------------------------------------------------------------- */ $studentsAtAverage = $studentPerformance ->filter(function ($student) use ($studentOverallAverage) { return $student['average'] == $studentOverallAverage; }) ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 16. STUDENT PASS / FAIL | ================================================================ |-------------------------------------------------------------------------- | | A student is considered to have passed if their overall average | is at least the school pass mark. | |-------------------------------------------------------------------------- */ $studentsPassed = $studentPerformance ->filter(function ($student) use ($passMark) { return $student['average'] >= $passMark; }) ->count(); $studentsFailed = $studentPerformance ->filter(function ($student) use ($passMark) { return $student['average'] < $passMark; }) ->count(); $studentPassPercentage = $totalStudentsAssessed > 0 ? round( ($studentsPassed / $totalStudentsAssessed) * 100, 2 ) : 0; /* |-------------------------------------------------------------------------- | ================================================================ | 17. TOP 10 STUDENTS | ================================================================ |-------------------------------------------------------------------------- */ $topStudents = $studentPerformance ->take(10) ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 18. STUDENTS BELOW AVERAGE | ================================================================ |-------------------------------------------------------------------------- | | We show the lowest performers first. | |-------------------------------------------------------------------------- */ $lowestStudents = $studentsBelowAverage ->sortBy('average') ->take(10) ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 19. CLASS PERFORMANCE | ================================================================ |-------------------------------------------------------------------------- | | We group results by class. | | Example: | | JSS 1 = 68% | JSS 2 = 72% | JSS 3 = 75% | |-------------------------------------------------------------------------- */ $classPerformance = $analysisResults ->groupBy('student_classes_id') ->map(function ($classResults) { $class = $classResults->first()->studentClass; return [ 'id' => $classResults->first()->student_classes_id, 'class_name' => $class ? $class->class_name : 'Unknown Class', 'average' => round( $classResults->avg('total'), 2 ), 'students' => $classResults ->pluck('student_id') ->unique() ->count(), 'results' => $classResults->count(), ]; }) ->sortByDesc('average') ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 20. SUBJECT PERFORMANCE |-------------------------------------------------------------------------- | | This allows the administrator to know: | | Which subject has high performance? | Which subject needs attention? | |-------------------------------------------------------------------------- */ $subjectPerformance = $analysisResults ->groupBy('subject_id') ->map(function ($subjectResults) { $subject = $subjectResults->first()->subject; return [ 'id' => $subjectResults->first()->subject_id, 'subject_name' => $subject ? $subject->subject_name : 'Unknown Subject', 'average' => round( $subjectResults->avg('total'), 2 ), 'highest' => round( $subjectResults->max('total'), 2 ), 'lowest' => round( $subjectResults->min('total'), 2 ), 'students' => $subjectResults ->pluck('student_id') ->unique() ->count(), ]; }) ->sortByDesc('average') ->values(); /* |-------------------------------------------------------------------------- | ================================================================ | 21. GRADE DISTRIBUTION |-------------------------------------------------------------------------- | | This uses the grade already stored inside the Result table. | | Example: | | A = 20 | B = 30 | C = 25 | D = 10 | E = 5 | F = 3 | |-------------------------------------------------------------------------- */ $gradeDistribution = $analysisResults ->groupBy(function ($result) { return strtoupper( trim($result->grade ?? 'N/A') ); }) ->map(function ($gradeResults) { return $gradeResults->count(); }) ->sortKeys(); /* |-------------------------------------------------------------------------- | ================================================================ | 22. SCORE DISTRIBUTION | ================================================================ | | This groups scores into understandable performance ranges. | | 0 - 39 = Fail | 40 - 49 = Pass | 50 - 59 | 60 - 69 | 70 - 79 | 80 - 89 | 90 - 100 | |-------------------------------------------------------------------------- */ $scoreRanges = [ '0 - 39' => 0, '40 - 49' => 0, '50 - 59' => 0, '60 - 69' => 0, '70 - 79' => 0, '80 - 89' => 0, '90 - 100' => 0, ]; foreach ($analysisResults as $result) { $score = (float) $result->total; if ($score < 40) { $scoreRanges['0 - 39']++; } elseif ($score < 50) { $scoreRanges['40 - 49']++; } elseif ($score < 60) { $scoreRanges['50 - 59']++; } elseif ($score < 70) { $scoreRanges['60 - 69']++; } elseif ($score < 80) { $scoreRanges['70 - 79']++; } elseif ($score < 90) { $scoreRanges['80 - 89']++; } else { $scoreRanges['90 - 100']++; } } /* |-------------------------------------------------------------------------- | ================================================================ | 23. RESULT COMPLETION ANALYSIS |-------------------------------------------------------------------------- | | This compares: | | Students in class | VS | Students who actually have results | |-------------------------------------------------------------------------- */ $missingResultStudents = max( 0, $totalStudentsInFilter - $totalStudentsAssessed ); /* |-------------------------------------------------------------------------- | ================================================================ | 24. CBT ANALYTICS |-------------------------------------------------------------------------- | | Keep your existing CBT dashboard analysis. |-------------------------------------------------------------------------- */ $totalTests = CbtTest::where('term', $currentTermName) ->where('session', $currentSessionName) ->count(); $totalAttempts = CbtAttempt::whereHas('test', function ($q) use ($currentTermName, $currentSessionName) { $q->where('term', $currentTermName) ->where('session', $currentSessionName); }) ->count(); $completedAttempts = CbtAttempt::where( 'status', 'completed' ) ->whereHas('test', function ($q) use ($currentTermName, $currentSessionName) { $q->where('term', $currentTermName) ->where('session', $currentSessionName); }) ->count(); $inProgressAttempts = CbtAttempt::where( 'status', 'in_progress' ) ->whereHas('test', function ($q) use ($currentTermName, $currentSessionName) { $q->where('term', $currentTermName) ->where('session', $currentSessionName); }) ->count(); $passCount = CbtAttempt::where( 'status', 'completed' ) ->whereHas('test', function ($q) use ($currentTermName, $currentSessionName) { $q->where('term', $currentTermName) ->where('session', $currentSessionName); }) ->where('score', '>=', 40) ->count(); $failCount = CbtAttempt::where( 'status', 'completed' ) ->whereHas('test', function ($q) use ($currentTermName, $currentSessionName) { $q->where('term', $currentTermName) ->where('session', $currentSessionName); }) ->where('score', '<', 40) ->count(); /* |-------------------------------------------------------------------------- | ================================================================ | 25. STUDENT GROWTH PER MONTH | ================================================================ |-------------------------------------------------------------------------- */ $monthlyStudents = []; $months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; foreach ($months as $index => $month) { $monthlyStudents[] = Student::whereYear( 'created_at', date('Y') ) ->whereMonth( 'created_at', $index + 1 ) ->count(); } /* |-------------------------------------------------------------------------- | ================================================================ | 26. SELECTED CLASS NAME FOR DISPLAY | ================================================================ |-------------------------------------------------------------------------- */ $selectedClassName = 'All Classes'; if ($analysisClass !== 'all' && !empty($analysisClass)) { $selectedClass = StudentClasses::find($analysisClass); if ($selectedClass) { $selectedClassName = $selectedClass->class_name; } } @endphp {{-- ================================================================ CUSTOM DASHBOARD CSS ================================================================ --}}
Total Students
Total Subjects
Total Classes
Total Teachers
Overall Average
Pass Rate
Above Average
Below Average
Students Assessed
Missing Results
Highest Score
Lowest Score
This represents the average final score of all result records in the selected analysis.
This is the average of the individual students' overall subject averages.
Total subject-result records included in this analysis.
| # | Student | Class | Subjects | Total Score | Average | Performance |
|---|---|---|---|---|---|---|
| {{ $index + 1 }} | {{ $student['student']->name ?? 'Unknown Student' }} | {{ $student['class']->class_name ?? 'Unknown' }} | {{ $student['subjects'] }} | {{ number_format($student['total_score'], 2) }} | {{ number_format($student['average'], 2) }}% | Above Average |
| No student result data available. | ||||||
| # | Student | Class | Subjects | Average | Difference From Average | Status |
|---|---|---|---|---|---|---|
| {{ $index + 1 }} | {{ $student['student']->name ?? 'Unknown Student' }} | {{ $student['class']->class_name ?? 'Unknown' }} | {{ $student['subjects'] }} | {{ number_format($student['average'], 2) }}% | {{ number_format($difference, 2) }}% | Below Average |
| No students are currently below average. | ||||||
| # | Subject | Students | Average | Highest | Lowest | Performance Level |
|---|---|---|---|---|---|---|
| {{ $index + 1 }} | {{ $subject['subject_name'] }} | {{ $subject['students'] }} | {{ number_format($subject['average'], 2) }}% | {{ number_format($subject['highest'], 2) }}% | {{ number_format($subject['lowest'], 2) }}% | {{ $subjectLevel }} |
| No subject result data available. | ||||||
| # | Class | Students Assessed | Result Records | Average | Performance |
|---|---|---|---|---|---|
| {{ $index + 1 }} | {{ $class['class_name'] }} | {{ $class['students'] }} | {{ $class['results'] }} | {{ number_format($class['average'], 2) }}% | @if($class['average'] >= 70) Strong @elseif($class['average'] >= 50) Moderate @else Needs Attention @endif |
| No class result data available. | |||||
CBT Tests
CBT Attempts
Completed CBT
CBT In Progress