Fix Laravel Pint formatting
This commit is contained in:
@@ -14,8 +14,7 @@ class AttendanceCalculator implements ScoreCalculatorInterface
|
||||
private AttendanceRecord $attendanceModel,
|
||||
private Configuration $configModel,
|
||||
private CalendarEvent $calendarModel
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
public function calculate(int $studentId, string $semester, string $schoolYear, ?int $classSectionId = null): array
|
||||
{
|
||||
@@ -30,7 +29,7 @@ class AttendanceCalculator implements ScoreCalculatorInterface
|
||||
$events = CalendarEvent::getEventsBySchoolYearAndSemester($schoolYear, $normSemester);
|
||||
$noSchoolSundays = 0;
|
||||
foreach ($events as $event) {
|
||||
if (!empty($event['no_school'])) {
|
||||
if (! empty($event['no_school'])) {
|
||||
$date = new \DateTime($event['date']);
|
||||
if ($date->format('N') == 7) {
|
||||
if ($date->format('Y-m-d') >= $semRange[0] && $date->format('Y-m-d') <= $semRange[1]) {
|
||||
@@ -75,16 +74,21 @@ class AttendanceCalculator implements ScoreCalculatorInterface
|
||||
protected function normalizeSemester(?string $input): string
|
||||
{
|
||||
$s = strtolower(trim((string) $input));
|
||||
if ($s === 'fall' || str_contains($s, '1')) return 'fall';
|
||||
if ($s === 'spring' || str_contains($s, '2')) return 'spring';
|
||||
if ($s === 'fall' || str_contains($s, '1')) {
|
||||
return 'fall';
|
||||
}
|
||||
if ($s === 'spring' || str_contains($s, '2')) {
|
||||
return 'spring';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function getSemesterRange(string $schoolYear, string $semester): ?array
|
||||
{
|
||||
$norm = $this->normalizeSemester($semester);
|
||||
if ($norm === '' || !preg_match('/^(\d{4})-(\d{4})$/', trim($schoolYear), $m)) {
|
||||
if ($norm === '' || !preg_match('/^(\d{4})/', trim($schoolYear), $m)) {
|
||||
if ($norm === '' || ! preg_match('/^(\d{4})-(\d{4})$/', trim($schoolYear), $m)) {
|
||||
if ($norm === '' || ! preg_match('/^(\d{4})/', trim($schoolYear), $m)) {
|
||||
return null;
|
||||
}
|
||||
$y1 = (int) $m[1];
|
||||
@@ -102,12 +106,14 @@ class AttendanceCalculator implements ScoreCalculatorInterface
|
||||
if ($norm === 'fall') {
|
||||
$start = ($fallStartCfg !== '') ? sprintf('%04d-%s', $y1, date('m-d', strtotime($fallStartCfg))) : "{$y1}-09-01";
|
||||
$end = ($fallEndCfg !== '') ? sprintf('%04d-%s', $y2, date('m-d', strtotime($fallEndCfg))) : "{$y2}-01-15";
|
||||
|
||||
return [$start, $end];
|
||||
}
|
||||
|
||||
if ($norm === 'spring') {
|
||||
$start = ($springStartCfg !== '') ? sprintf('%04d-%s', $y2, date('m-d', strtotime($springStartCfg))) : "{$y2}-01-16";
|
||||
$end = ($springEndCfg !== '') ? sprintf('%04d-%s', $y2, date('m-d', strtotime($springEndCfg))) : "{$y2}-06-30";
|
||||
|
||||
return [$start, $end];
|
||||
}
|
||||
|
||||
@@ -127,6 +133,7 @@ class AttendanceCalculator implements ScoreCalculatorInterface
|
||||
$sundays++;
|
||||
}
|
||||
}
|
||||
|
||||
return $sundays;
|
||||
}
|
||||
|
||||
@@ -139,11 +146,12 @@ class AttendanceCalculator implements ScoreCalculatorInterface
|
||||
|
||||
$configKey = $norm === 'fall' ? 'total_semester1_days' : 'total_semester2_days';
|
||||
$value = Configuration::getConfig($configKey);
|
||||
if (!is_numeric($value)) {
|
||||
if (! is_numeric($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$length = (int) $value;
|
||||
|
||||
return $length > 0 ? $length : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,17 @@
|
||||
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\MissingScoreOverride;
|
||||
use App\Models\Student;
|
||||
use App\Models\TeacherClass;
|
||||
use App\Models\ClassSection;
|
||||
use App\Services\Grading\Validation\ScoreValueValidator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ExamScoreService
|
||||
{
|
||||
public function __construct(private ScoreTermService $term)
|
||||
{
|
||||
}
|
||||
public function __construct(private ScoreTermService $term) {}
|
||||
|
||||
public function resolveClassSectionIdForTeacher(int $teacherId, ?int $requestedClassSectionId, ?string $schoolYearInput): ?int
|
||||
{
|
||||
@@ -72,7 +70,7 @@ class ExamScoreService
|
||||
->where('sc.school_year', '=', $schoolYear);
|
||||
})
|
||||
->leftJoinSub($latestSub, 'latest', 'latest.student_id', '=', 's.id')
|
||||
->leftJoin($table . ' as ex', 'ex.id', '=', 'latest.max_id')
|
||||
->leftJoin($table.' as ex', 'ex.id', '=', 'latest.max_id')
|
||||
->orderBy('s.lastname')
|
||||
->orderBy('s.firstname')
|
||||
->get()
|
||||
@@ -125,17 +123,17 @@ class ExamScoreService
|
||||
$count = 0;
|
||||
|
||||
foreach ($scores as $studentId => $data) {
|
||||
if (!is_numeric($studentId)) {
|
||||
if (! is_numeric($studentId)) {
|
||||
continue;
|
||||
}
|
||||
$student = Student::query()->find((int) $studentId);
|
||||
if (!$student) {
|
||||
if (! $student) {
|
||||
continue;
|
||||
}
|
||||
$rawScore = is_array($data) ? ($data['score'] ?? null) : $data;
|
||||
$validator = new ScoreValueValidator();
|
||||
$validator = new ScoreValueValidator;
|
||||
$normalizedScore = $validator->normalizeNullable($rawScore, ScoreValueValidator::DEFAULT_MAX_POINTS, 'Exam score');
|
||||
$missingAllowed = !empty($missingOk[$studentId]);
|
||||
$missingAllowed = ! empty($missingOk[$studentId]);
|
||||
|
||||
$existing = $builder
|
||||
->where('student_id', $studentId)
|
||||
@@ -178,7 +176,7 @@ class ExamScoreService
|
||||
$schoolYearVariants = [$schoolYear];
|
||||
}
|
||||
|
||||
$rows = DB::table($table . ' as ex')
|
||||
$rows = DB::table($table.' as ex')
|
||||
->select([
|
||||
'ex.*',
|
||||
's.firstname as student_firstname',
|
||||
|
||||
@@ -7,13 +7,12 @@ use App\Models\Homework;
|
||||
|
||||
class HomeworkCalculator implements ScoreCalculatorInterface
|
||||
{
|
||||
public function __construct(private Homework $homeworkModel)
|
||||
{
|
||||
}
|
||||
public function __construct(private Homework $homeworkModel) {}
|
||||
|
||||
public function calculate(int $studentId, string $semester, string $schoolYear, ?int $classSectionId = null): array
|
||||
{
|
||||
$average = Homework::getAverageHomeworkScore($studentId, $semester, $schoolYear, $classSectionId);
|
||||
|
||||
return ['homework_avg' => $average !== null ? (float) $average : null];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\Homework;
|
||||
use App\Models\MissingScoreOverride;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\TeacherClass;
|
||||
use App\Models\ClassSection;
|
||||
use App\Services\Grading\Validation\ScoreValueValidator;
|
||||
|
||||
class HomeworkScoreService
|
||||
{
|
||||
public function __construct(private ScoreTermService $term)
|
||||
{
|
||||
}
|
||||
public function __construct(private ScoreTermService $term) {}
|
||||
|
||||
/**
|
||||
* When the client omits class_section_id (legacy teacher portal), use the teacher's assignment
|
||||
@@ -174,6 +172,7 @@ class HomeworkScoreService
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -181,10 +180,11 @@ class HomeworkScoreService
|
||||
{
|
||||
foreach ($schoolYearVariants as $year) {
|
||||
$map = MissingScoreOverride::getOverridesMap($classSectionId, $semester, $year, 'homework');
|
||||
if (!empty($map)) {
|
||||
if (! empty($map)) {
|
||||
return $map;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ class HomeworkScoreService
|
||||
$studentIds = array_keys($scores);
|
||||
$indexSet = [];
|
||||
foreach ($scores as $hwData) {
|
||||
if (!is_array($hwData)) {
|
||||
if (! is_array($hwData)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($hwData as $index => $_) {
|
||||
@@ -209,11 +209,11 @@ class HomeworkScoreService
|
||||
|
||||
$checkedItems = [];
|
||||
foreach ($missingOk as $studentId => $indexes) {
|
||||
if (!is_array($indexes)) {
|
||||
if (! is_array($indexes)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($indexes as $index => $flag) {
|
||||
if (!is_numeric($index)) {
|
||||
if (! is_numeric($index)) {
|
||||
continue;
|
||||
}
|
||||
$checkedItems[] = [
|
||||
@@ -236,22 +236,22 @@ class HomeworkScoreService
|
||||
|
||||
$count = 0;
|
||||
foreach ($scores as $studentId => $hwData) {
|
||||
if (!is_numeric($studentId) || !is_array($hwData)) {
|
||||
if (! is_numeric($studentId) || ! is_array($hwData)) {
|
||||
continue;
|
||||
}
|
||||
$student = Student::query()->find((int) $studentId);
|
||||
if (!$student) {
|
||||
if (! $student) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($hwData as $index => $score) {
|
||||
if (!is_numeric($index)) {
|
||||
if (! is_numeric($index)) {
|
||||
continue;
|
||||
}
|
||||
$rawScore = $score ?? null;
|
||||
$validator = new ScoreValueValidator();
|
||||
$validator = new ScoreValueValidator;
|
||||
$normalizedScore = $validator->normalizeNullable($rawScore, ScoreValueValidator::DEFAULT_MAX_POINTS, 'Homework score');
|
||||
$missingAllowed = !empty($missingOk[$studentId][$index]);
|
||||
$missingAllowed = ! empty($missingOk[$studentId][$index]);
|
||||
|
||||
$existing = Homework::query()
|
||||
->where('student_id', $studentId)
|
||||
@@ -306,7 +306,7 @@ class HomeworkScoreService
|
||||
|
||||
foreach ($students as $student) {
|
||||
$studentRow = Student::query()->find((int) $student->student_id);
|
||||
if (!$studentRow) {
|
||||
if (! $studentRow) {
|
||||
continue;
|
||||
}
|
||||
$exists = Homework::query()
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\ClassSection;
|
||||
use App\Services\Grading\Validation\ScoreValueValidator;
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\MissingScoreOverride;
|
||||
use App\Models\Participation;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\TeacherClass;
|
||||
use App\Services\Grading\Validation\ScoreValueValidator;
|
||||
|
||||
class ParticipationScoreService
|
||||
{
|
||||
public function __construct(private ScoreTermService $term)
|
||||
{
|
||||
}
|
||||
public function __construct(private ScoreTermService $term) {}
|
||||
|
||||
public function resolveClassSectionIdForTeacher(int $teacherId, ?int $requestedClassSectionId, ?string $schoolYearInput): ?int
|
||||
{
|
||||
@@ -173,22 +171,22 @@ class ParticipationScoreService
|
||||
|
||||
$count = 0;
|
||||
foreach ($scores as $studentId => $data) {
|
||||
if (!is_numeric($studentId)) {
|
||||
if (! is_numeric($studentId)) {
|
||||
continue;
|
||||
}
|
||||
if (!is_array($data)) {
|
||||
if (! is_array($data)) {
|
||||
$data = ['score' => $data];
|
||||
}
|
||||
|
||||
$student = Student::query()->find((int) $studentId);
|
||||
if (!$student) {
|
||||
if (! $student) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rawScore = $data['score'] ?? null;
|
||||
$validator = new ScoreValueValidator();
|
||||
$validator = new ScoreValueValidator;
|
||||
$normalizedScore = $validator->normalizeNullable($rawScore, ScoreValueValidator::DEFAULT_MAX_POINTS, 'Participation score');
|
||||
$missingAllowed = !empty($missingOk[$studentId]);
|
||||
$missingAllowed = ! empty($missingOk[$studentId]);
|
||||
|
||||
$existing = Participation::query()
|
||||
->where('student_id', $studentId)
|
||||
|
||||
@@ -7,13 +7,12 @@ use App\Models\Project;
|
||||
|
||||
class ProjectCalculator implements ScoreCalculatorInterface
|
||||
{
|
||||
public function __construct(private Project $projectModel)
|
||||
{
|
||||
}
|
||||
public function __construct(private Project $projectModel) {}
|
||||
|
||||
public function calculate(int $studentId, string $semester, string $schoolYear, ?int $classSectionId = null): array
|
||||
{
|
||||
$average = Project::averageScore($studentId, $semester, $schoolYear, $classSectionId);
|
||||
|
||||
return ['project_avg' => $average !== null ? (float) $average : null];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,18 @@
|
||||
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\MissingScoreOverride;
|
||||
use App\Models\Project;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\TeacherClass;
|
||||
use App\Models\ClassSection;
|
||||
use App\Services\Grading\Validation\ScoreValueValidator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ProjectScoreService
|
||||
{
|
||||
public function __construct(private ScoreTermService $term)
|
||||
{
|
||||
}
|
||||
public function __construct(private ScoreTermService $term) {}
|
||||
|
||||
public function resolveClassSectionIdForTeacher(int $teacherId, ?int $requestedClassSectionId, ?string $schoolYearInput): ?int
|
||||
{
|
||||
@@ -168,7 +165,7 @@ class ProjectScoreService
|
||||
$studentIds = array_keys($scores);
|
||||
$indexSet = [];
|
||||
foreach ($scores as $projects) {
|
||||
if (!is_array($projects)) {
|
||||
if (! is_array($projects)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($projects as $index => $_) {
|
||||
@@ -180,11 +177,11 @@ class ProjectScoreService
|
||||
|
||||
$checkedItems = [];
|
||||
foreach ($missingOk as $studentId => $indexes) {
|
||||
if (!is_array($indexes)) {
|
||||
if (! is_array($indexes)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($indexes as $index => $flag) {
|
||||
if (!is_numeric($index)) {
|
||||
if (! is_numeric($index)) {
|
||||
continue;
|
||||
}
|
||||
$checkedItems[] = [
|
||||
@@ -207,21 +204,21 @@ class ProjectScoreService
|
||||
|
||||
$count = 0;
|
||||
foreach ($scores as $studentId => $projects) {
|
||||
if (!is_numeric($studentId) || !is_array($projects)) {
|
||||
if (! is_numeric($studentId) || ! is_array($projects)) {
|
||||
continue;
|
||||
}
|
||||
$student = Student::query()->find((int) $studentId);
|
||||
if (!$student) {
|
||||
if (! $student) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($projects as $index => $score) {
|
||||
if (!is_numeric($index)) {
|
||||
if (! is_numeric($index)) {
|
||||
continue;
|
||||
}
|
||||
$validator = new ScoreValueValidator();
|
||||
$validator = new ScoreValueValidator;
|
||||
$normalizedScore = $validator->normalizeNullable($score, ScoreValueValidator::DEFAULT_MAX_POINTS, 'Project score');
|
||||
$missingAllowed = !empty($missingOk[$studentId][$index]);
|
||||
$missingAllowed = ! empty($missingOk[$studentId][$index]);
|
||||
|
||||
$existing = Project::query()
|
||||
->where('student_id', $studentId)
|
||||
@@ -275,7 +272,7 @@ class ProjectScoreService
|
||||
|
||||
foreach ($students as $student) {
|
||||
$studentRow = Student::query()->find((int) $student->student_id);
|
||||
if (!$studentRow) {
|
||||
if (! $studentRow) {
|
||||
continue;
|
||||
}
|
||||
$exists = Project::query()
|
||||
|
||||
@@ -24,7 +24,7 @@ class QuizCalculator implements ScoreCalculatorInterface
|
||||
$count = 0;
|
||||
foreach ($rows as $row) {
|
||||
$score = $row->score ?? null;
|
||||
if ($score === null || $score === '' || !is_numeric($score)) {
|
||||
if ($score === null || $score === '' || ! is_numeric($score)) {
|
||||
continue;
|
||||
}
|
||||
$total += (float) $score;
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\MissingScoreOverride;
|
||||
use App\Models\Quiz;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\TeacherClass;
|
||||
use App\Models\ClassSection;
|
||||
use App\Services\Grading\Validation\ScoreValueValidator;
|
||||
|
||||
class QuizScoreService
|
||||
{
|
||||
public function __construct(private ScoreTermService $term)
|
||||
{
|
||||
}
|
||||
public function __construct(private ScoreTermService $term) {}
|
||||
|
||||
public function resolveClassSectionIdForTeacher(int $teacherId, ?int $requestedClassSectionId, ?string $schoolYearInput): ?int
|
||||
{
|
||||
@@ -167,7 +165,7 @@ class QuizScoreService
|
||||
$studentIds = array_keys($scores);
|
||||
$indexSet = [];
|
||||
foreach ($scores as $quizData) {
|
||||
if (!is_array($quizData)) {
|
||||
if (! is_array($quizData)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($quizData as $index => $_) {
|
||||
@@ -179,11 +177,11 @@ class QuizScoreService
|
||||
|
||||
$checkedItems = [];
|
||||
foreach ($missingOk as $studentId => $indexes) {
|
||||
if (!is_array($indexes)) {
|
||||
if (! is_array($indexes)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($indexes as $index => $flag) {
|
||||
if (!is_numeric($index)) {
|
||||
if (! is_numeric($index)) {
|
||||
continue;
|
||||
}
|
||||
$checkedItems[] = [
|
||||
@@ -206,23 +204,23 @@ class QuizScoreService
|
||||
|
||||
$count = 0;
|
||||
foreach ($scores as $studentId => $quizData) {
|
||||
if (!is_numeric($studentId)) {
|
||||
if (! is_numeric($studentId)) {
|
||||
continue;
|
||||
}
|
||||
if (!is_array($quizData)) {
|
||||
if (! is_array($quizData)) {
|
||||
$quizData = [1 => $quizData];
|
||||
}
|
||||
$student = Student::query()->find((int) $studentId);
|
||||
if (!$student) {
|
||||
if (! $student) {
|
||||
continue;
|
||||
}
|
||||
foreach ($quizData as $quizNumber => $score) {
|
||||
if (!is_numeric($quizNumber)) {
|
||||
if (! is_numeric($quizNumber)) {
|
||||
continue;
|
||||
}
|
||||
$validator = new ScoreValueValidator();
|
||||
$validator = new ScoreValueValidator;
|
||||
$normalizedScore = $validator->normalizeNullable($score, ScoreValueValidator::DEFAULT_MAX_POINTS, 'Quiz score');
|
||||
$missingAllowed = !empty($missingOk[$studentId][$quizNumber]);
|
||||
$missingAllowed = ! empty($missingOk[$studentId][$quizNumber]);
|
||||
|
||||
$existing = Quiz::query()
|
||||
->where('student_id', $studentId)
|
||||
@@ -276,7 +274,7 @@ class QuizScoreService
|
||||
|
||||
foreach ($students as $student) {
|
||||
$studentRow = Student::query()->find((int) $student->student_id);
|
||||
if (!$studentRow) {
|
||||
if (! $studentRow) {
|
||||
continue;
|
||||
}
|
||||
$exists = Quiz::query()
|
||||
|
||||
@@ -2,21 +2,18 @@
|
||||
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Models\Configuration;
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\MissingScoreOverride;
|
||||
use App\Models\ScoreComment;
|
||||
use App\Models\SemesterScore;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ScoreCommentService
|
||||
{
|
||||
public function __construct(private ScoreTermService $term)
|
||||
{
|
||||
}
|
||||
public function __construct(private ScoreTermService $term) {}
|
||||
|
||||
public function list(?string $classSectionId, ?string $semester, ?string $schoolYear): array
|
||||
{
|
||||
@@ -33,24 +30,24 @@ class ScoreCommentService
|
||||
->orderBy('s.firstname')
|
||||
->distinct();
|
||||
|
||||
if (!$isAllSections && $classSectionInt) {
|
||||
if (! $isAllSections && $classSectionInt) {
|
||||
$builder->where('sc.class_section_id', $classSectionInt);
|
||||
}
|
||||
|
||||
$students = $builder->get()->map(fn ($row) => (array) $row)->all();
|
||||
|
||||
$comments = [];
|
||||
if (!empty($students)) {
|
||||
if (! empty($students)) {
|
||||
$studentIds = array_map(static fn ($r) => (int) $r['student_id'], $students);
|
||||
$rawComments = ScoreComment::query()
|
||||
->whereIn('student_id', $studentIds)
|
||||
->whereIn('score_type', ['midterm', 'final', 'ptap', 'attendance'])
|
||||
->where('semester', $activeSemester)
|
||||
->where('school_year', $schoolYear)
|
||||
->when(!$isAllSections && $classSectionInt, function ($q) use ($classSectionInt) {
|
||||
->when(! $isAllSections && $classSectionInt, function ($q) use ($classSectionInt) {
|
||||
$q->where(function ($w) use ($classSectionInt) {
|
||||
$w->where('class_section_id', $classSectionInt)
|
||||
->orWhereNull('class_section_id');
|
||||
->orWhereNull('class_section_id');
|
||||
});
|
||||
})
|
||||
->get();
|
||||
@@ -87,7 +84,7 @@ class ScoreCommentService
|
||||
if ($hasComment) {
|
||||
continue;
|
||||
}
|
||||
if (!function_exists('attendance_comment_from_score')) {
|
||||
if (! function_exists('attendance_comment_from_score')) {
|
||||
continue;
|
||||
}
|
||||
$score = $attendanceScores[$sid] ?? null;
|
||||
@@ -112,10 +109,10 @@ class ScoreCommentService
|
||||
'semester' => $activeSemester,
|
||||
'schoolYear' => $schoolYear,
|
||||
'classSectionId' => $isAllSections ? 'allsections' : $classSectionInt,
|
||||
'classSectionName' => (!$isAllSections && $classSectionInt)
|
||||
'classSectionName' => (! $isAllSections && $classSectionInt)
|
||||
? (string) (ClassSection::query()->where('class_section_id', $classSectionInt)->value('class_section_name') ?? '')
|
||||
: '',
|
||||
'scoresLocked' => (!$isAllSections && $classSectionInt)
|
||||
'scoresLocked' => (! $isAllSections && $classSectionInt)
|
||||
? GradingLock::isLocked($classSectionInt, $activeSemester, $schoolYear)
|
||||
: false,
|
||||
];
|
||||
@@ -143,7 +140,7 @@ class ScoreCommentService
|
||||
foreach ($commentTypes as $type) {
|
||||
$checkedItems = [];
|
||||
foreach ($missingOk as $studentId => $types) {
|
||||
if (!is_array($types) || empty($types[$type])) {
|
||||
if (! is_array($types) || empty($types[$type])) {
|
||||
continue;
|
||||
}
|
||||
$checkedItems[] = [
|
||||
@@ -175,6 +172,7 @@ class ScoreCommentService
|
||||
$validationError = $this->validateComment($trimmedComment, (int) $studentId, $normalizedScoreType, $studentNames);
|
||||
if ($validationError !== null) {
|
||||
$errors[] = $validationError;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -185,7 +183,7 @@ class ScoreCommentService
|
||||
->where('school_year', $schoolYear)
|
||||
->where(function ($q) use ($classSectionId) {
|
||||
$q->where('class_section_id', $classSectionId)
|
||||
->orWhereNull('class_section_id');
|
||||
->orWhereNull('class_section_id');
|
||||
})
|
||||
->first();
|
||||
|
||||
@@ -239,6 +237,7 @@ class ScoreCommentService
|
||||
$validationError = $this->validateComment($commentText, (int) $studentId, $normalizedScoreType, $studentNames);
|
||||
if ($validationError !== null) {
|
||||
$errors[] = $validationError;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -250,7 +249,7 @@ class ScoreCommentService
|
||||
->where('school_year', $schoolYear)
|
||||
->where(function ($q) use ($classSectionId) {
|
||||
$q->where('class_section_id', $classSectionId)
|
||||
->orWhereNull('class_section_id');
|
||||
->orWhereNull('class_section_id');
|
||||
})
|
||||
->first();
|
||||
|
||||
@@ -322,8 +321,8 @@ class ScoreCommentService
|
||||
return "{$firstName}'s {$scoreType} comment must be at most 400 characters.";
|
||||
}
|
||||
|
||||
$pattern = '/^' . preg_quote($firstName, '/') . '\\b/i';
|
||||
if (!preg_match($pattern, $trimmed)) {
|
||||
$pattern = '/^'.preg_quote($firstName, '/').'\\b/i';
|
||||
if (! preg_match($pattern, $trimmed)) {
|
||||
return "{$firstName}'s {$scoreType} comment must start with the student's first name.";
|
||||
}
|
||||
|
||||
@@ -333,7 +332,7 @@ class ScoreCommentService
|
||||
private function isReviewer(): bool
|
||||
{
|
||||
$user = auth()->user();
|
||||
if (!$user) {
|
||||
if (! $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -354,6 +353,6 @@ class ScoreCommentService
|
||||
explode(',', $reviewerRoles)
|
||||
);
|
||||
|
||||
return !empty(array_intersect($currentUserRoles, $allowedRoles));
|
||||
return ! empty(array_intersect($currentUserRoles, $allowedRoles));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\GradingLock;
|
||||
use App\Models\MissingScoreOverride;
|
||||
use App\Models\ScoreComment;
|
||||
@@ -15,16 +14,14 @@ use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ScoreDashboardService
|
||||
{
|
||||
public function __construct(private ScoreTermService $term)
|
||||
{
|
||||
}
|
||||
public function __construct(private ScoreTermService $term) {}
|
||||
|
||||
public function overview(int $teacherId, ?int $classSectionId, ?string $semester, ?string $schoolYear): array
|
||||
{
|
||||
$schoolYear = $this->term->schoolYear($schoolYear);
|
||||
$semesterLabel = $this->term->semesterLabel($semester, $semester);
|
||||
|
||||
if ($teacherId <= 0 && !empty($classSectionId)) {
|
||||
if ($teacherId <= 0 && ! empty($classSectionId)) {
|
||||
$allowedIds = [(int) $classSectionId];
|
||||
} else {
|
||||
$allowedIds = TeacherClass::query()
|
||||
@@ -45,7 +42,7 @@ class ScoreDashboardService
|
||||
|
||||
$studentQuery = StudentClass::query();
|
||||
if (DB::connection()->getDriverName() === 'sqlite') {
|
||||
$studentQuery->whereRaw('class_section_id = ' . (int) $classSectionId);
|
||||
$studentQuery->whereRaw('class_section_id = '.(int) $classSectionId);
|
||||
if ($schoolYear !== '') {
|
||||
$quoted = DB::connection()->getPdo()->quote($schoolYear);
|
||||
$studentQuery->whereRaw("school_year = {$quoted}");
|
||||
@@ -62,9 +59,9 @@ class ScoreDashboardService
|
||||
->map(fn ($v) => (int) $v)
|
||||
->all();
|
||||
if (empty($studentIds) && DB::connection()->getDriverName() === 'sqlite') {
|
||||
$schoolYearClause = $schoolYear !== '' ? " and school_year = " . DB::connection()->getPdo()->quote($schoolYear) : '';
|
||||
$schoolYearClause = $schoolYear !== '' ? ' and school_year = '.DB::connection()->getPdo()->quote($schoolYear) : '';
|
||||
$rows = DB::select(
|
||||
"select student_id from student_class where class_section_id = " . (int) $classSectionId . $schoolYearClause
|
||||
'select student_id from student_class where class_section_id = '.(int) $classSectionId.$schoolYearClause
|
||||
);
|
||||
$studentIds = array_values(array_filter(array_map(
|
||||
static fn ($row) => isset($row->student_id) ? (int) $row->student_id : 0,
|
||||
@@ -173,7 +170,7 @@ class ScoreDashboardService
|
||||
foreach ($commentTypes as $type) {
|
||||
$checkedItems = [];
|
||||
foreach ($missingOk as $studentId => $types) {
|
||||
if (!is_array($types) || empty($types[$type])) {
|
||||
if (! is_array($types) || empty($types[$type])) {
|
||||
continue;
|
||||
}
|
||||
$checkedItems[] = [
|
||||
@@ -229,7 +226,7 @@ class ScoreDashboardService
|
||||
->all();
|
||||
|
||||
$scores = [];
|
||||
if (!empty($students)) {
|
||||
if (! empty($students)) {
|
||||
$studentIdList = array_column($students, 'id');
|
||||
$semesterScores = DB::table('semester_scores')
|
||||
->whereIn('student_id', $studentIdList)
|
||||
|
||||
@@ -56,7 +56,7 @@ class ScorePredictorDataService
|
||||
->orWhere('cs.class_section_name', 'not like', 'KG%');
|
||||
});
|
||||
|
||||
if (!empty($classSectionId)) {
|
||||
if (! empty($classSectionId)) {
|
||||
$builder->where('sc.class_section_id', $classSectionId);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class ScorePredictorDataService
|
||||
->orWhere('cs.class_section_name', 'not like', 'KG%');
|
||||
});
|
||||
|
||||
if (!empty($classSectionId)) {
|
||||
if (! empty($classSectionId)) {
|
||||
$builder->where('student_class.class_section_id', $classSectionId);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ class ScorePredictorRiskService
|
||||
$a5 = 1.061405429;
|
||||
$erf = 1 - ((((($a5 * $t + $a4) * $t + $a3) * $t + $a2) * $t + $a1) * $t) * exp(-$z * $z);
|
||||
$sign = $z < 0 ? -1 : 1;
|
||||
|
||||
return 0.5 * (1 + $sign * $erf);
|
||||
}
|
||||
|
||||
@@ -26,7 +27,7 @@ class ScorePredictorRiskService
|
||||
$springScore = is_numeric($student['spring_score'] ?? null) ? (float) $student['spring_score'] : null;
|
||||
|
||||
$scoreParts = array_values(array_filter([$fallScore, $springScore], static fn ($v) => $v !== null));
|
||||
$finalAvg = !empty($scoreParts) ? round(array_sum($scoreParts) / count($scoreParts), 1) : null;
|
||||
$finalAvg = ! empty($scoreParts) ? round(array_sum($scoreParts) / count($scoreParts), 1) : null;
|
||||
|
||||
$waitingForSpring = ($fallScore !== null && $springScore === null);
|
||||
|
||||
@@ -40,8 +41,8 @@ class ScorePredictorRiskService
|
||||
$probLow = $zLow !== null ? $this->normalCdf($zLow) : null;
|
||||
|
||||
$riskHigh = match (true) {
|
||||
$finalAvg !== null && !$waitingForSpring && $finalAvg >= $trophyThreshold => 'Achieved Trophy',
|
||||
$finalAvg !== null && !$waitingForSpring => 'Unreachable',
|
||||
$finalAvg !== null && ! $waitingForSpring && $finalAvg >= $trophyThreshold => 'Achieved Trophy',
|
||||
$finalAvg !== null && ! $waitingForSpring => 'Unreachable',
|
||||
$requiredHigh !== null && $requiredHigh > 100 => 'Unreachable',
|
||||
is_null($probHigh) => 'New student',
|
||||
$probHigh >= 0.66 => 'Low',
|
||||
@@ -50,8 +51,8 @@ class ScorePredictorRiskService
|
||||
};
|
||||
|
||||
$riskLow = match (true) {
|
||||
$finalAvg !== null && !$waitingForSpring && $finalAvg < $targetLow => 'High',
|
||||
$finalAvg !== null && !$waitingForSpring => 'Low',
|
||||
$finalAvg !== null && ! $waitingForSpring && $finalAvg < $targetLow => 'High',
|
||||
$finalAvg !== null && ! $waitingForSpring => 'Low',
|
||||
$requiredLow !== null && $requiredLow > 100 => 'Unlikely to pass',
|
||||
is_null($probLow) => 'New student',
|
||||
$probLow >= 0.66 => 'High',
|
||||
@@ -103,19 +104,23 @@ class ScorePredictorRiskService
|
||||
}
|
||||
|
||||
foreach ($bySection as $cid => $indices) {
|
||||
if (!empty($hasThresholdTrophy[$cid])) {
|
||||
if (! empty($hasThresholdTrophy[$cid])) {
|
||||
continue;
|
||||
}
|
||||
$candidates = [];
|
||||
foreach ($indices as $idx) {
|
||||
$val = $results[$idx]['final_average'] ?? null;
|
||||
if (!is_numeric($val)) {
|
||||
if (! is_numeric($val)) {
|
||||
$fall = $results[$idx]['fall_score'] ?? null;
|
||||
$spring = $results[$idx]['spring_score'] ?? null;
|
||||
$parts = [];
|
||||
if (is_numeric($fall)) $parts[] = (float) $fall;
|
||||
if (is_numeric($spring)) $parts[] = (float) $spring;
|
||||
if (!empty($parts)) {
|
||||
if (is_numeric($fall)) {
|
||||
$parts[] = (float) $fall;
|
||||
}
|
||||
if (is_numeric($spring)) {
|
||||
$parts[] = (float) $spring;
|
||||
}
|
||||
if (! empty($parts)) {
|
||||
$val = array_sum($parts) / count($parts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@ class ScorePredictorService
|
||||
public function __construct(
|
||||
private ScorePredictorDataService $dataService,
|
||||
private ScorePredictorRiskService $riskService
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
public function report(?string $schoolYear, ?int $classSectionId = null): array
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ class ScoreTermService
|
||||
if ($value === 'spring' || str_contains($value, '2')) {
|
||||
return 'spring';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
@@ -3,21 +3,17 @@
|
||||
namespace App\Services\Scores;
|
||||
|
||||
use App\Interfaces\ScoreCalculatorInterface;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\FinalExam;
|
||||
use App\Models\MidtermExam;
|
||||
use App\Models\Participation;
|
||||
use App\Models\SemesterScore;
|
||||
use App\Services\Scores\AttendanceCalculator;
|
||||
use App\Services\Scores\HomeworkCalculator;
|
||||
use App\Services\Scores\ProjectCalculator;
|
||||
use App\Services\Scores\QuizCalculator;
|
||||
use App\Models\AttendanceRecord;
|
||||
use App\Models\CalendarEvent;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\FinalExam;
|
||||
use App\Models\Homework;
|
||||
use App\Models\MidtermExam;
|
||||
use App\Models\Participation;
|
||||
use App\Models\Project;
|
||||
use RuntimeException;
|
||||
use App\Models\SemesterScore;
|
||||
use App\Services\Grading\Policy\GradingPolicyResolver;
|
||||
use RuntimeException;
|
||||
|
||||
class SemesterScoreService
|
||||
{
|
||||
@@ -25,8 +21,11 @@ class SemesterScoreService
|
||||
private array $scoreCalculators = [];
|
||||
|
||||
private string $semester;
|
||||
|
||||
private string $schoolYear;
|
||||
|
||||
private ?int $actorId;
|
||||
|
||||
private GradingPolicyResolver $policyResolver;
|
||||
|
||||
public function __construct(
|
||||
@@ -38,16 +37,16 @@ class SemesterScoreService
|
||||
$this->semester = (string) (Configuration::getConfig('semester') ?? '');
|
||||
$this->schoolYear = (string) (Configuration::getConfig('school_year') ?? '');
|
||||
$this->actorId = (int) (auth()->id() ?? 0) ?: null;
|
||||
$this->policyResolver = new GradingPolicyResolver();
|
||||
$this->policyResolver = new GradingPolicyResolver;
|
||||
|
||||
$attendanceCalculator = $attendanceCalculator ?? new AttendanceCalculator(
|
||||
new AttendanceRecord(),
|
||||
new Configuration(),
|
||||
new CalendarEvent()
|
||||
new AttendanceRecord,
|
||||
new Configuration,
|
||||
new CalendarEvent
|
||||
);
|
||||
$homeworkCalculator = $homeworkCalculator ?? new HomeworkCalculator(new Homework());
|
||||
$quizCalculator = $quizCalculator ?? new QuizCalculator();
|
||||
$projectCalculator = $projectCalculator ?? new ProjectCalculator(new Project());
|
||||
$homeworkCalculator = $homeworkCalculator ?? new HomeworkCalculator(new Homework);
|
||||
$quizCalculator = $quizCalculator ?? new QuizCalculator;
|
||||
$projectCalculator = $projectCalculator ?? new ProjectCalculator(new Project);
|
||||
|
||||
$this->scoreCalculators = [
|
||||
AttendanceCalculator::class => $attendanceCalculator,
|
||||
@@ -70,7 +69,7 @@ class SemesterScoreService
|
||||
public function updateStudentScores(array $student, string $semester, string $schoolYear): void
|
||||
{
|
||||
foreach (['student_id', 'school_id', 'class_section_id'] as $field) {
|
||||
if (!isset($student[$field])) {
|
||||
if (! isset($student[$field])) {
|
||||
throw new RuntimeException("Missing required student field: {$field}");
|
||||
}
|
||||
}
|
||||
@@ -114,7 +113,7 @@ class SemesterScoreService
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($scoreData['participation_score'])) {
|
||||
if (! isset($scoreData['participation_score'])) {
|
||||
$participationScore = Participation::getParticipationScore($studentId, $semester, $schoolYear, $classSectionId);
|
||||
$scoreData['participation_score'] = $participationScore !== null ? (float) $participationScore : null;
|
||||
}
|
||||
@@ -140,24 +139,27 @@ class SemesterScoreService
|
||||
$hasTests = $avgQuiz !== null;
|
||||
$hasProjects = $avgProject !== null;
|
||||
|
||||
if (!$hasTests && !$hasProjects) {
|
||||
if (! $hasTests && ! $hasProjects) {
|
||||
if ($avgHomework === null || $avgParticipation === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return round(($avgHomework * 0.5) + ($avgParticipation * 0.5), 1);
|
||||
}
|
||||
|
||||
if (!$hasProjects) {
|
||||
if (! $hasProjects) {
|
||||
if ($avgHomework === null || $avgParticipation === null || $avgQuiz === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return round(($avgHomework * 0.4) + ($avgParticipation * 0.4) + ($avgQuiz * 0.2), 1);
|
||||
}
|
||||
|
||||
if (!$hasTests) {
|
||||
if (! $hasTests) {
|
||||
if ($avgHomework === null || $avgParticipation === null || $avgProject === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return round(($avgHomework * 0.34) + ($avgParticipation * 0.33) + ($avgProject * 0.33), 1);
|
||||
}
|
||||
|
||||
@@ -188,6 +190,7 @@ class SemesterScoreService
|
||||
if ($ptap !== null && $attendance !== null && $out['midterm_score'] !== null) {
|
||||
$out['semester_score'] = round(($attendance * 0.2) + ($ptap * 0.2) + ($out['midterm_score'] * 0.6), 1);
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -197,6 +200,7 @@ class SemesterScoreService
|
||||
if ($ptap !== null && $attendance !== null && $out['final_score'] !== null) {
|
||||
$out['semester_score'] = round(($attendance * 0.2) + ($ptap * 0.2) + ($out['final_score'] * 0.6), 1);
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user