Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 901
Template6MigrationdResultGeneratorNew
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 14
49952.00
0.00% covered (danger)
0.00%
0 / 901
 __construct
n/a
0 / 0
1
n/a
0 / 0
 processData
0.00% covered (danger)
0.00%
0 / 1
306.00
0.00% covered (danger)
0.00%
0 / 104
 indexExamReport
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 27
 checkSubjectPassStatus
0.00% covered (danger)
0.00%
0 / 1
3782.00
0.00% covered (danger)
0.00%
0 / 167
 generateData
0.00% covered (danger)
0.00%
0 / 1
3906.00
0.00% covered (danger)
0.00%
0 / 248
 subjectHistoryProcess
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 73
 consolidatedSubjectProcess
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 64
 semesterHistoryProcess
0.00% covered (danger)
0.00%
0 / 1
462.00
0.00% covered (danger)
0.00%
0 / 68
 getCalculatedSubjectForMarkHistory
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 33
 calculateRegistrationWiseData
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 21
 processStudentCourseData
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 21
 getGradeByPercentage
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 8
 getStudentExamDetails
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 checkIsFailedByPassPercentCriteria
0.00% covered (danger)
0.00%
0 / 1
380.00
0.00% covered (danger)
0.00%
0 / 43
 getSemesterGradeDetials
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 9
<?php
// For SCEK
namespace com\linways\ec\core\service\MarkMigrationGenerator;
use com\linways\ec\core\service\StudentMarkListService;
use com\linways\ec\core\service\ExamRegistrationService;
use com\linways\ec\core\exception\ExamControllerException;
use com\linways\base\util\TwigRenderer;
use com\linways\core\ams\professional\util\PdfUtil;
use com\linways\ec\core\service\CommonExamService;
use com\linways\ec\core\service\MarkMigrationGenerator\MarkMigrationResultDataGenerator;
use com\linways\ec\core\service\StudentsOverAllMarkReportService;
use com\linways\ec\core\service\ExamRevaluationService;
use com\linways\ec\core\request\ConsolidatedOverAllMarkReportRequest;
use com\linways\core\ams\professional\dto\ExamType;
use com\linways\ec\core\service\GradeSchemeService;
use com\linways\core\ams\professional\constant\examcontroller\ExamSubjectTypeConstants;
use com\linways\ec\core\constant\ExamRegistrationTypeConstants;
use com\linways\ec\core\service\RuleService;
use com\linways\ec\core\request\SearchRuleRequest;
use stdClass;
class Template6MigrationdResultGeneratorNew extends MarkMigrationResultDataGenerator
{
    public function __construct(){}
    
     /**
     * Process Student data college base
     * @param $request
     */
    protected function processData($searchReq){
        $request = new ConsolidatedOverAllMarkReportRequest();
        $request->groupId = $searchReq->groupId;
        $request->isConsolidatedRequest = TRUE;
        $request->examRegistrationType = "REGULAR";
        $request->fetchMarkHistory = 1;
        $request->isRoundOff = 1;
        $request->considerSupplyImproveCombined = 1;
        // $request->academicTermId = 3;
        $request->studentId = $searchReq->studentId;
        // $request->studentId = 1905;
        $request->staffId = $searchReq->staffId;
        $request->skipMapper = 1;
        $searchRuleRequest = new SearchRuleRequest;
        $searchRuleRequest->name = "IMPORT_MARK_RULES";
        $ruleSettings = reset(RuleService::getInstance()->searchRule($searchRuleRequest))->rule;
        $request->considerOverallReportForGraceMark = 1;
        if ($ruleSettings){
            $request->considerOverallReportForGraceMark = $ruleSettings->considerOverallReportForGraceMark;
        }
        
        $pulishedSupplyRegId = StudentsOverAllMarkReportService::getInstance()->getPublishedSupplyExamRegistrationByStudentId($request);
        $request->supplyRegIdArray = $pulishedSupplyRegId;
        $request->considerFeStudents = 1;
        $studentRegularExamDetails = StudentsOverAllMarkReportService::getInstance()->getStudentExamMarkDetails($request);
        $request->considerFeStudents = false;
        if(empty($studentRegularExamDetails)){
            return;
            // throw new ExamControllerException(ExamControllerException::NO_DETAILS_FOUND,"No Details Found");
        }
        $searchRequest = new \stdClass();
        $searchRequest->academicPaperSubjectId = array_column($studentRegularExamDetails, 'academicPaperSubjectId');
        $request->subjectGradeSchemeArray = GradeSchemeService::getInstance()->getGradeSchemesByRequest($searchRequest);
        $searchRuleRequest = new SearchRuleRequest;
        $searchRuleRequest->name = "SPECIAL_CONSIDERATION_FOR_EXTERNAL_MARK";
        $request->markRuleSetting = reset(RuleService::getInstance()->searchRule($searchRuleRequest))->rule;
        $schemeType = "PERCENTAGE";
        $request->passCriteriaArray = GradeSchemeService::getInstance()->getSubjectPassCriteriaByRequest($searchRequest, $schemeType);
        
        $studentArray = [];
        $studentArray = $this->indexExamReport($request, $studentRegularExamDetails, $studentArray , 'REGULAR');
        
        $request->studentRegularExamDetails = $studentRegularExamDetails;
        $sampleDataForSemester = reset($studentArray);
        $semGradeBatchArray = [];
        foreach( $sampleDataForSemester->semester as $key => $sampleData){
            $semGradeBatchArray[$sampleData->examAttendedGroupId]->semesterId[$key] = $key;
        }
        $smesterSchemeReq = new \stdClass();
        $smesterSchemeReq->semGradeBatchArray = $semGradeBatchArray;
        $smesterSchemeReq->requestType = "SEMESTER";
        $request->semesterGradeSchemeArray = GradeSchemeService::getInstance()->getAllSemGradeSchemesByRequest($smesterSchemeReq);
        if ( $request->considerImprovement ) {
            $request->examRegistrationType = ExamRegistrationTypeConstants::SUPPLEMENTARY;
            $request->subjectRegistrationType = ExamRegistrationTypeConstants::IMPROVEMENT;
            $improvementExamDetails = StudentsOverAllMarkReportService::getInstance()->getStudentExamMarkDetails($request);
            $request->subjectRegistrationType = "";
            if( $improvementExamDetails ){
                $studentArray = $this->indexExamReport($request, $improvementExamDetails, $studentArray , 'IMPROVEMENT');
            }
        }
        if ( $request->considerSupplementary ) {
            $request->examRegistrationType = ExamRegistrationTypeConstants::SUPPLEMENTARY;
            $request->subjectRegistrationType = ExamRegistrationTypeConstants::SUPPLEMENTARY;
            $supplyExamDetails = StudentsOverAllMarkReportService::getInstance()->getStudentExamMarkDetails($request);
            $request->subjectRegistrationType = "";
            if( $supplyExamDetails ){
                $studentArray = $this->indexExamReport($request, $supplyExamDetails, $studentArray , 'SUPPLEMENTARY');
            }
        }
        if ( $request->considerRevaluation) {
            $revalRequest = new \stdClass();
            $revalRequest->studentId = $request->studentId;
            $revalRequest->orderByHighestMark = 1;
            $studentRevaluationDetails = StudentsOverAllMarkReportService::getInstance()->getStudentFinalizedRevaluationMark($revalRequest);
            if( $studentRevaluationDetails ){
                $studentArray = $this->indexExamReport($request, $studentRevaluationDetails, $studentArray , 'REVALUATION');
            }
        }
        if ( $request->considerModerationMark ) {
            $request->examRegistrationType = "";
            $request->requestType = "MODERATION";
            $moderationMarkDetails = StudentsOverAllMarkReportService::getInstance()->getStudentExamMarkDetails($request);
            if( $moderationMarkDetails ){
                $studentArray = $this->indexExamReport($request, $moderationMarkDetails, $studentArray , 'MODERATION');
            }
        }
        if ( $request->considerGraceMark ) {
            $request->examRegistrationType = "";
            $request->requestType = "GRACEMARK";
            $graceMarkDetails = StudentsOverAllMarkReportService::getInstance()->getStudentExamMarkDetails($request);
            if( $moderationMarkDetails ){
                $studentArray = $this->indexExamReport($request, $graceMarkDetails, $studentArray , 'GRACEMARK');
            }
        }
        $consolidatedMarkDetails = reset($this->generateData($request, $studentArray));
        // $consolidatedMarkDetails = reset($this->markListProcessing($request, $studentDetails, $studentRegularExamDetails));
        if (!empty($consolidatedMarkDetails)) {
            StudentsOverAllMarkReportService::getInstance()->updateStudentSubjectActiveStatus($request);
            foreach ($consolidatedMarkDetails->semester as $semester) {
                foreach ($semester->subject as $subject) {
                    $subject->finalConsolidated->staffId = $request->staffId;
                    StudentsOverAllMarkReportService::getInstance()->insertStudentSubjectConsolidatedMarkDetails($subject->finalConsolidated);
                }
                $semester->staffId = $request->staffId;
                StudentsOverAllMarkReportService::getInstance()->insertStudentSemesterConsolidatedMarkDetails($semester);
            }
            $consolidatedMarkDetails->staffId = $request->staffId;
            StudentsOverAllMarkReportService::getInstance()->insertStudentCourseConsolidatedMarkDetails($consolidatedMarkDetails);
            StudentsOverAllMarkReportService::getInstance()->deleteStudentEditstatus($request);
        }
    }
    protected function indexExamReport($request, $examDetails, $studentArray , $markType){
        foreach($examDetails as $studentExam){
            if ( $markType == "REGULAR" || $markType == "SUPPLEMENTARY" || $markType == "REVALUATION" ){
                if ( $markType == "REVALUATION" ){
                    $studentExamTemp = $studentArray[$studentExam->studentId]->semester[$studentExam->academicTermId]->subject[$studentExam->academicPaperSubjectId]->markType[$studentExam->parentExamRegistrationType]->exam[$studentExam->parentExamRegistrationId];
                    $studentExamTemp->externalMark = $studentExam->revaluationMark;
                    $studentExam = $studentExamTemp;
                }
                //--------normalize external marks with special consideration-------------
                if ($studentExam && $studentExam->externalMark) {
                    $markRuleSetting = $request->markRuleSetting;
                    if ($markRuleSetting) {
                        // $markRuleSetting = json_decode($markRuleSetting);
                        if(($markRuleSetting->isTheory && $studentExam->isTheory) || ($markRuleSetting->isPractical && !$studentExam->isTheory)){
                            $marRuleRegIds = $markRuleSetting->examregIds;
                            if (in_array($studentExam->examRegistrationId, $marRuleRegIds)) {
                                $studentExam->externalMark = (($studentExam->externalMark * $markRuleSetting->markRule) > $studentExam->externalMaxMark) ? $studentExam->externalMaxMark : $studentExam->externalMark * $markRuleSetting->markRule;
                                $studentExam->externalMark = round($studentExam->externalMark,2);
                            }
                        }
                    }
                }
                //-------END normalize external marks with special consideration-------------
                $studentExam = $this->checkSubjectPassStatus($request, $studentExam);
                
            }
            $studentArray[$studentExam->studentId]->semester[$studentExam->academicTermId]->examAttendedGroupId = $studentExam->groupId;
            $studentArray[$studentExam->studentId]->batchStartYear = $studentExam->batchStartYear;
            $studentArray[$studentExam->studentId]->semester[$studentExam->academicTermId]->subject[$studentExam->academicPaperSubjectId]->markType[$markType]->exam[$studentExam->examRegistrationId] = $studentExam;
        }
        return $studentArray;
    }
    protected function checkSubjectPassStatus($request, $studentExam){
        $studentExamTotal = $examTotal = $isFailed = $studentExternalMark = $isInternalFailed = $creditGradePoint = $markNeededToPass = $passMark = $markNeededToPassExternal = $markNeededToPassOverAll = $isExternalFailed = $isInternalFailed = $examTotal = $studentExternalMark = $studentExamTotal = $overallPercent = $internalPercent = $externalPercent = 0;
        $moderationMark = null;
        $studentExam->credit = $studentExam->subjectCredit;
        $courseTypeMethod = $studentExam->courseType;
        $academicPaperSubjectId = $studentExam->academicPaperSubjectId;
        $academicTermId = $studentExam->academicTermId;
        $gradeDetails = $request->subjectGradeSchemeArray[$academicPaperSubjectId]->grades;
        $maxGradePercent = $gradeDetails[0]->rangeTo;
        $maxGradePoint = max(array_column($gradeDetails,"gradePoint"));
        $externalGrade = $grade = $internalGrade = "";
        $internalPassCriteria = $externalPassCriteria = $overallPassCriteria = $aggregatePassCriteria = null;
        $internalPassCriteria = $request->passCriteriaArray[$academicPaperSubjectId]->internalPassCriteria;
        $externalPassCriteria = $request->passCriteriaArray[$academicPaperSubjectId]->externalPassCriteria;
        $overallPassCriteria = $request->passCriteriaArray[$academicPaperSubjectId]->overallPassCriteria;
        $considerOverallPassCriteriaOnly = 0;
        if ( $studentExam->subjectType == ExamSubjectTypeConstants::OPEN_ELECTIVE ||
            $studentExam->subjectType == ExamSubjectTypeConstants::FOUNDATION_COURSE ||
            $studentExam->subjectType == ExamSubjectTypeConstants::TERM_PAPER ) {
            $considerOverallPassCriteriaOnly = 1;
        }
        if ($studentExam->isInternal) {
            $studentExam->internalMark = ceil($studentExam->internalMark);
            $studentExamTotal = round($studentExam->internalMark);
            $examTotal = $studentExam->internalMaxMark;
            $internalPercent = $studentExam->internalMaxMark ? (100 * $studentExam->internalMark/ $studentExam->internalMaxMark) : 0;
            if (!empty ($internalPassCriteria)) {
                if ( $considerOverallPassCriteriaOnly == 0 ) {
                    $isFailed = $internalPassCriteria <= $internalPercent ? $isFailed : 1;
                    $isInternalFailed = $internalPassCriteria <= $internalPercent ? 0 : 1;
                }
            }
            $internalGrade = $this->getGradeByPercentage($internalPercent, $gradeDetails);
        }
        $markNeededToPass = $markNeededToPassExternal = $passMark = 0;
        if ($studentExam->isExternal) {
            $studentExternalMark = ceil($studentExam->externalMark);
            $studentExam->externalMark = ceil($studentExam->externalMark);
            if(!$studentExam->excludeModeration){
                //get moderation mark
                $studentRequest = new \stdClass();
                $studentRequest->externalPassMark = round($externalPassCriteria * ($studentExam->externalMaxMark / 100), 2);
                $studentRequest->overallPassMark  = round($overallPassCriteria * (($studentExam->externalMaxMark + $studentExam->internalMaxMark) / 100), 2);
                if ( $request->considerModerationMark ) {
                    $studentModerationMark = $studentExam->moderationMark;
                    if($studentModerationMark){
                        $moderationMark +=  $studentExam->moderationMark;
                    }
                }
                if ($moderationMark && $studentExam->isRegularRevaluationMark) {
                    if (!empty($externalPassCriteria)) {
                        $studentRequest->maxModerationMarkAllowed = $studentRequest->maxModerationMarkAllowedExt = $studentRequest->externalPassMark - $studentExternalMark;
                    }
                    if (!empty($overallPassCriteria)) {
                        $studentRequest->maxModerationMarkAllowed = $studentRequest->overallPassMark - ($studentExternalMark + $studentExam->internalMark);
                    }
                    $studentRequest->maxModerationMarkAllowed = ($studentRequest->maxModerationMarkAllowed > $studentRequest->maxModerationMarkAllowedExt) ? $studentRequest->maxModerationMarkAllowed : $studentRequest->maxModerationMarkAllowedExt;
                    $studentRequest->maxModerationMarkAllowed = ($studentRequest->maxModerationMarkAllowed > 0) ? $studentRequest->maxModerationMarkAllowed : 0;
                    $moderationMark = ($moderationMark > $studentRequest->maxModerationMarkAllowed) ? $studentRequest->maxModerationMarkAllowed : $moderationMark;
                }
                if((($studentExternalMark + $moderationMark) >= $studentRequest->externalPassMark) && (($studentExternalMark + $moderationMark + $studentExam->internalMark) >= $studentRequest->overallPassMark)){
                    $studentExternalMark = ($moderationMark) ? ((($studentExternalMark + $moderationMark) > $studentRequest->externalPassMark) ? ($studentExternalMark + $moderationMark) : ($studentExternalMark + $moderationMark)) : $studentExternalMark;
                }
                $studentExternalMark = ceil($studentExternalMark);
                //end
            }
            $studentExamTotal += round($studentExternalMark);
            $examTotal += $studentExam->externalMaxMark;
            if($request->isRoundOff){
                $externalPercent = $studentExam->externalMaxMark ? (100 * round($studentExternalMark) / $studentExam->externalMaxMark) : 0;
            }else{
                $externalPercent = $studentExam->externalMaxMark ? (100 * $studentExternalMark / $studentExam->externalMaxMark) : 0;
            }
            if (!empty ($externalPassCriteria)) {
                $externalPassMark = $studentExam->externalMaxMark * ($externalPassCriteria /100);
                if ( $considerOverallPassCriteriaOnly == 0 ) {
                    $isFailed = $externalPassCriteria <= $externalPercent ? $isFailed : 1;
                    $isExternalFailed = $externalPassCriteria <= $externalPercent ? 0 : 1;
                }
                $markNeededToPass = $markNeededToPassExternal  = $isFailed ? ($externalPassMark - $studentExternalMark ): 0;
            }
            $externalGrade = $this->getGradeByPercentage($externalPercent, $gradeDetails);
        }
        else{
            $studentExternalMark = 0;
        }
        $overallPercent = $examTotal ? 100 * $studentExamTotal / $examTotal : 0;
        if (!empty ($overallPassCriteria)) {
            $isFailed = $overallPassCriteria <= $overallPercent ? $isFailed : 1;
            $overallPassMark = round($overallPassCriteria * ($examTotal / 100),2);
            $markNeededToPassOverAll  = $isFailed ? ($overallPassMark - $studentExamTotal) : 0;
            if ($markNeededToPassOverAll > $markNeededToPassExternal) {
                $markNeededToPass = $markNeededToPassOverAll;
                $passMark = $overallPassMark;
            }
        }
        /**
         * $maxGradePercent is used so that, we get the percentage in 'out of' the values in the db 
         * ie, 6, 10 or 100, different values for different colleges for different colleges...
         */
        if ( $isFailed ) {
            $percentageObtained = 0;
            $semesterGradePercentObtained = 0;
        }
        else {
            $percentageObtained = $maxGradePercent * $studentExamTotal / $examTotal;
            $percentageObtained = round($percentageObtained, 2);
        
            // $semesterGradePercentObtained = $maxSemesterGradePercent * $studentExamTotal / $examTotal;
            // $semesterGradePercentObtained = round($semesterGradePercentObtained, 2);
        }
        $grade = $this->getGradeByPercentage($percentageObtained, $gradeDetails);
        if (!empty ($grade)) {
            $creditGradePoint = ($studentExam->credit * $grade->gradePoint);
            if ($grade->failStatus == 1) {
                $isFailed = 1;
            }
        }
        //normalize internal marks
        if(!$isFailed && $studentExam->isInternal && $studentExam->isExternal && ($courseTypeMethod != 'MTECH') && !(($studentExam->batchStartYear <= 2020) && ($academicTermId <=1) && !$studentExam->isTheory)){
        $externalPercent = $studentExam->externalMaxMark ? round((100 * $studentExternalMark / $studentExam->externalMaxMark),2) : 0;
        $internalPercent = $studentExam->internalMaxMark ? round((100 * $studentExam->internalMark / $studentExam->internalMaxMark),2) : 0;
            if($externalPercent && $internalPercent && ($internalPercent > $externalPercent) && (($internalPercent - $externalPercent) > 30)){
                $normalizedInternalPercent = $externalPercent + 30;
                $normalizedInternalMark = round(($normalizedInternalPercent / 100) * $studentExam->internalMaxMark,2);
                $normalizedInternalMark = ceil($normalizedInternalMark);
                $studentExamTotal = round(($studentExternalMark + $normalizedInternalMark),2);
                $percentageObtained = $maxGradePercent * $studentExamTotal / $examTotal;
                $percentageObtained = round($percentageObtained, 2);
                $overallPercent = $examTotal ? 100 * $studentExamTotal / $examTotal : 0;
                if (!empty($overallPassCriteria)) {
                    $isFailed = $overallPassCriteria <= $overallPercent ? $isFailed : 1;
                }
                $grade = $this->getGradeByPercentage($percentageObtained, $gradeDetails);
                if (!empty ($grade)) {
                    $creditGradePoint = ($studentExam->credit * $grade->gradePoint);
                    if ($grade->failStatus == 1) {
                        $isFailed = 1;
                    }
                }
                $studentExam->internalMark = $normalizedInternalMark;
                unset($normalizedInternalPercent);
                unset($normalizedInternalMark);
            }
        }
        //End normalize internal marks
    
        if($studentExam->internalAttendanceStatus == "ABSENT"){
            $isFailed = 1;
            $isInternalFailed = 1;
        }
        $studentExam->isPG = 0;
        if ($courseTypeMethod == 'PG') {
            $studentExam->isPG = 1;
        }
        $studentExam->isFailed = $isFailed;
        $studentExam->isInternalFailed = $isInternalFailed;
        $studentExam->grade = $grade;
        $studentExam->externalGrade = $externalGrade;
        $studentExam->internalGrade = $internalGrade;
        $studentExam->creditGradePoint = $creditGradePoint;
        $studentExam->markNeededToPass = $markNeededToPass;
        $studentExam->passMark = $passMark;
        $studentExam->markNeededToPassExternal = $markNeededToPassExternal;
        $studentExam->markNeededToPassOverAll = $markNeededToPassOverAll;
        $studentExam->isExternalFailed = $isExternalFailed;
        $studentExam->isInternalFailed = $isInternalFailed;
        $studentExam->examTotal = $examTotal;
        $studentExam->studentExternalMark = $studentExternalMark;
        $studentExam->totalMarkObtained = $studentExamTotal;
        $studentExam->internalPercent = $internalPercent;
        $studentExam->externalPercent = $externalPercent;
        $studentExam->overallPercent = $overallPercent;
        
        $studentExam->internalPassPercentage = $internalPassCriteria;
        $studentExam->externalPassPercentage = $externalPassCriteria;
        $studentExam->aggregatePassPercentage = $overallPassCriteria;
        $studentExam->maxGradePoint = $maxGradePoint;
        $studentExam->maxGradePercentage = $maxGradePercent;
        return $studentExam;
    }
         
    protected function generateData($request, $studentArray){
        
        $student = [];
        foreach ($studentArray as $studentId => $studentData) {
            $lastExamYear = $lastExamMonth = 0;
            foreach ($studentData->semester as $academicTermId => $semester) {
                $distinctExamRegistration = [];
                foreach ($semester->subject as $subject) {
                    foreach ($subject->markType as $markHistory => $markType) {
                        if ( $markHistory != "REGULAR" && $markHistory != "SUPPLEMENTARY"){
                            continue;
                        }
                        $subjectData = reset( $markType->exam);
                        $hasChangeInExistingMark = 0;
                        $moderationMark = 0;
                        $markObtainedInExam = $subjectData->externalMark;
                        $writternHistory = new \stdClass();
                        $writternHistory->grade = $subjectData->grade->letterGrade;
                        $writternHistory->gradePoint = $subjectData->grade->gradePoint;
                        $writternHistory->creditGradePoint = $subjectData->creditGradePoint;
                        $writternHistory->isFailed = $subjectData->isFailed;
                        $writternHistory->mark = $subjectData->externalMark;
                        $distinctExamRegistration[$subjectData->examRegistrationId]->examRegistrationId = $subjectData->examRegistrationId;
                        $distinctExamRegistration[$subjectData->examRegistrationId]->examMonth = $subjectData->examMonth;
                        $distinctExamRegistration[$subjectData->examRegistrationId]->examYear = $subjectData->examYear;
                        $distinctExamRegistration[$subjectData->examRegistrationId]->markHistory = $markHistory;
        
                        $revaluationHistory = new \stdClass();
                        $moderationHistory = new \stdClass();
                        if ( $subject->markType["REVALUATION"]->markType[$markType]->exam[$subjectData->examRegistrationId]){
                            $subjectData = $subject->markType["REVALUATION"]->markType[$markType]->exam[$subjectData->examRegistrationId];
                            $subjectData->isRegularRevaluationMark =  $markHistory == "REGULAR" ? true : false;
                            // $subjectData->excludeModeration = false;;; need to handle for supply mod;;
                            $revaluationHistory->grade = $subjectData->grade->letterGrade;
                            $revaluationHistory->gradePoint = $subjectData->grade->gradePoint;
                            $revaluationHistory->creditGradePoint = $subjectData->creditGradePoint;
                            $revaluationHistory->isFailed = $subjectData->isFailed;
                            $moderationHistory->mark = $subjectData->externalMark;
                        }
                        if ( $subject->markType["MODERATION"]->markType[$markType]->exam[$subjectData->examRegistrationId]){
                            $moderationMark = $subject->markType["MODERATION"]->markType[$markType]->exam[$subjectData->examRegistrationId];
                            $hasChangeInExistingMark = 1;
                            $subjectData->moderationMark = $moderationMark;
                            $subjectMarkType = new \stdClass();
                            $subjectMarkType->mark += $markObtainedInExam + $moderationMark;
                            $subjectData = $this->checkSubjectPassStatus($request, $subjectData);
                            $markHistoryStatus = $this->getCalculatedSubjectForMarkHistory($request, $subjectData, $academicTermId, $subjectMarkType);
                            $moderationHistory->mark = $moderationMark;
                            $moderationHistory->grade = $markHistoryStatus->letterGrade;
                            $moderationHistory->gradePoint = $markHistoryStatus->gradePoint;
                            $moderationHistory->creditGradePoint = $markHistoryStatus->creditGradePoint;
                            $moderationHistory->isFailed = $markHistoryStatus->isFailed;
                        }
                        if( $hasChangeInExistingMark ){
                            $subjectData = $this->checkSubjectPassStatus($request, $subjectData);
                        }
                        $subjectData->writternHistory = $writternHistory;
                        $subjectData->revaluationHistory = $revaluationHistory;
                        $subjectData->moderationHistory = $moderationHistory;
                        $subjectData->markObtainedInExam = $markObtainedInExam;
                        $subjectmarkHistoryObj = $this->subjectHistoryProcess($subjectData, $request);
                        if ( $subjectmarkHistoryObj ){
                            $semester->history[] = $subjectmarkHistoryObj;
                            $subject->finalConsolidated->markHistory[] = $subjectmarkHistoryObj;
                            $semester->examRegistration[$subjectmarkHistoryObj->examRegistrationId]->subject = $subjectmarkHistoryObj;
                            if ( $subject->consolidated[$subjectmarkHistoryObj->paperSubjectId] ){
                                if($subject->consolidated[$subjectmarkHistoryObj->paperSubjectId]->internalMark != $subjectmarkHistoryObj->internalMark ){
                                    $subject->hasSupplyInternal = 1;
                                }
                                if ( $subject->consolidated[$subjectmarkHistoryObj->paperSubjectId]->externalMark < $subjectmarkHistoryObj->externalMark){
                                    $subject->consolidated[$subjectmarkHistoryObj->academicPaperSubjectId] = $subjectmarkHistoryObj;
                                }
                                if ( $subject->internalMark < $subjectmarkHistoryObj->internalMark){
                                    $subject->internalMark = $subjectmarkHistoryObj->internalMark;
                                }
                            }
                            else{
                                $subject->consolidated[$subjectmarkHistoryObj->academicPaperSubjectId] = $subjectmarkHistoryObj;
                                $subject->internalMark = $subjectmarkHistoryObj->internalMark;
                            }
                        }
                      
                    }
                    foreach( $subject->consolidated as $consolidatedSubject ){
                        $regularExamDataFetched = reset($subject->markType["REGULAR"]->exam);
                        if( $subject->hasSupplyInternal ){
                            $regularExamData = json_decode(json_encode($regularExamDataFetched));
                            $regularExamData->internalMark = $subject->internalMark;
                            $regularExamData->externalMark = $consolidatedSubject->externalMark;
                            $regularExamData = $this->checkSubjectPassStatus($request, $regularExamData);
                            $consolidatedSubject = $this->subjectHistoryProcess($subjectData, $request);
                        }
                        $subjectMarkDetails = $this->consolidatedSubjectProcess($consolidatedSubject, $regularExamDataFetched); 
                        $subject->finalConsolidated->markDetails = $subjectMarkDetails;
                        $subject->finalConsolidated->groupId = $subjectMarkDetails->groupId;
                        $subject->finalConsolidated->id = $subjectMarkDetails->academicPaperSubjectId;
                        $subject->finalConsolidated->studentId = $studentId;
                        $subject->finalConsolidated->noOfChancesTaken = 0;
                        $subject->finalConsolidated->totalMarks = $subjectMarkDetails->markObtained;
                        $subject->finalConsolidated->percentage = $subjectMarkDetails->percentage;
                        $subject->finalConsolidated->grade = $subjectMarkDetails->grade;
                        $subject->finalConsolidated->class = $subjectMarkDetails->class;
                        $subject->finalConsolidated->status = $subjectMarkDetails->resultStatus;
                        
                        if ( $subjectMarkDetails->isFailed ){
                            $semester->arrears++;
                            $semester->totalArrears++;
                        }
                        if ( !$studentData->lastExamYear || $studentData->lastExamYear < $subjectMarkDetails->examYear ) {
                            $studentData->lastExamYear = $subjectMarkDetails->examYear;
                            $studentData->lastExamMonth = $subjectMarkDetails->examMonth;
                            $studentData->lastExamReg = $consolidatedSubject->examMarkType;
                        } else if ( $studentData->lastExamYear == $subjectMarkDetails->examYear && 
                        $studentData->lastExamMonth < $subjectMarkDetails->examMonth ) {
                            $studentData->lastExamMonth = $subjectMarkDetails->examMonth;;
                            $studentData->lastExamReg = $consolidatedSubject->examMarkType;
                        }
                        if ( !$semester->lastExamYear || $semester->lastExamYear < $subjectMarkDetails->examYear ) {
                            $semester->lastExamYear = $subjectMarkDetails->examYear;
                            $semester->lastExamMonth = $subjectMarkDetails->examMonth;
                            $semester->lastExamReg = $consolidatedSubject->examMarkType;
                        } else if ( $semester->lastSubjectExamYear == $subjectMarkDetails->examYear && 
                        $semester->lastExamMonth < $subjectMarkDetails->examMonth ) {
                            $semester->lastExamMonth = $subjectMarkDetails->examMonth;
                            $semester->lastExamReg = $consolidatedSubject->examMarkType;
                        }
                        $studentData->allCredit += $consolidatedSubject->credit;
                        if( !$consolidatedSubject->excludeSubjectFromTotal ){
                            $semester->credit += $consolidatedSubject->credit;
                            $semester->creditGradePoint += $consolidatedSubject->creditGradePoint;
                            $studentData->credit += $consolidatedSubject->credit;
                            $studentData->creditGradePoint += $consolidatedSubject->creditGradePoint;
                        }
                        $studentData->isPG = $regularExamDataFetched->isPG;
                        if ($regularExamDataFetched->isPG == 0 && (
                            $regularExamDataFetched->subjectType == ExamSubjectTypeConstants::FOUNDATION_COURSE ||
                            $regularExamDataFetched->subjectType == ExamSubjectTypeConstants::OPEN_ELECTIVE ||
                            $regularExamDataFetched->subjectType == ExamSubjectTypeConstants::TERM_PAPER)) {
                        continue;
                        } else if ($regularExamDataFetched->isPG == 0 && $regularExamDataFetched->excludeSubjectFromTotal == 1) {
                            continue;
                        } else if ($regularExamDataFetched->isPG == 1 && (
                            $regularExamDataFetched->subjectType == ExamSubjectTypeConstants::OPEN_ELECTIVE ||
                            $regularExamDataFetched->subjectType == ExamSubjectTypeConstants::IGNITORS )) {
                            continue;
                        }
                        $studentData->totalMarkObtained += $consolidatedSubject->markObtained;
                        $studentData->totalMark += $consolidatedSubject->totalMark;
                        $semester->totalMarks += $consolidatedSubject->markObtained;
                        $semester->examTotalMarks += $consolidatedSubject->totalMark;
                    }
                }
                $semesterGradeDetails = $request->semesterGradeSchemeArray[$academicTermId]->grade;
                $maxPercent = $semesterGradeDetails[0]->rangeTo; 
                $semester->academicTermId = $academicTermId;
                $aggregatePassCriteria = null;
                if ( $semester->arrears ) {
                    $semester->sgpa = "0"; // Please don't update "-"
                    $semMarkGrade = $this->getGradeByPercentage(0, $semesterGradeDetails);
                    $semester->isFailed = true;
                } else {
                    /**
                     * Semester wise aggregate percentage criteria check
                     */
                    $semesterPercentage = round ( ( $semester->examTotalMarks ? 100 * $semester->totalMarks / $semester->examTotalMarks : 0) , 2);
                    if ( $studentData->isPG == 1 && $semesterPercentage < $aggregatePassCriteria ) {
                        // $studentObj->isFailed = true;
                        $semester->isFailed = true;
                    }
                    /** codeEnds **/
                    if ( !$semester->isFailed ) {
                        $semester->sgpa = $semester->credit ? round($semester->creditGradePoint / $semester->credit, 2) : 0;
                        $semesterGrade = $this->getGradeByPercentage($semester->sgpa, $semesterGradeDetails);
                    }
                }
                $semester->grade = $semMarkGrade->letterGrade;
                $semester->class = $semMarkGrade->className;
                // $totalEarnedCredits += $semMark->earnedCredit;
                // $semMark->totalEarnedCredits += $totalEarnedCredits; 
                // $semester->isFailed = $semIsFailed;
                $semCreditxMark = array_sum(array_column($semester->subject->finalConsolidated, "creditxMark"));
                $semester->WAS = $semester->credit ? ($semCreditxMark / $semester->credit) : 0;
                $semester->percentage = ($semester->totalMarks / $semester->examTotalMarks) * 100;
                $semester->rawSgpa = $semester->credit ? ($semester->creditGradePoint / $semester->credit) : 0;
                $studentData->studentCredits += $semester->credit; 
                $studentData->studentCreditGradePoint += $semester->creditGradePoint; 
                $semester->semesterCgpa = $studentData->studentCredits ? round($studentData->studentCreditGradePoint/ $studentData->studentCredits, 2) : 0;
                if ($studentData->totalArrears > 0) {
                    $studentData->isFailed = true;
                }
                $semConsolidated = $this->calculateRegistrationWiseData( $semester);
                $semester->groupId = $subjectMarkDetails->groupId;
                $semester->studentId = $studentId;
                $studentData->groupId = $subjectMarkDetails->groupId;
                $studentData->studentId = $studentId;
                $semester->markDetails = $semConsolidated;
                $semester->supplyAttemptCount = 0;
                $studentData->supplyAttemptCount = 0;
                
                foreach( $distinctExamRegistration as $distinctExam ){
                    foreach ($semester->history as $subjectHistory ){
                        if ( $distinctExam->examYear >= $subjectHistory->examYear && $distinctExam->examMonth >=  $subjectHistory->examMonth) {
                            if ($semester->examRegistration[$distinctExam->examRegistrationId]->subjectHistory[$subjectHistory->academicPaperSubjectId]){
                                $currentSubject = $semester->examRegistration[$distinctExam->examRegistrationId]->subjectHistory[$subjectHistory->academicPaperSubjectId];
                                if ($currentSubject->externalMark < $subjectHistory->externalMark){
                                    $semester->examRegistration[$distinctExam->examRegistrationId]->subjectHistory[$subjectHistory->academicPaperSubjectId] = $subjectHistory;
                                }
                                if ( $subjectHistory->examMarkType != "REGULAR"){
                                    $regularExamDataFetched = reset($subject->markType["REGULAR"]->exam);
                                    if ( $regularExamDataFetched->internalMark != $subjectHistory->internalMark){
                                        $maxInternalObtained = max($regularExamDataFetched->internalMark,$subjectHistory->internalMark);
                                        $regularExamData = json_decode(json_encode($regularExamDataFetched));
                                        $regularExamData->internalMark = $maxInternalObtained;
                                        $regularExamData->externalMark = $subjectHistory->externalMark;
                                        $regularExamData = $this->checkSubjectPassStatus($request, $regularExamData);
                                        $subjectHistory = $this->subjectHistoryProcess($subjectData, $request);
                                        $semester->examRegistration[$distinctExam->examRegistrationId]->subjectHistory[$subjectHistory->academicPaperSubjectId] = $subjectHistory;
                                    }
                                }
                                // need to handle internal case
                            }
                            else{
                                $semester->examRegistration[$distinctExam->examRegistrationId]->subjectHistory[$subjectHistory->academicPaperSubjectId] = $subjectHistory;
                            }
                            
                        }
                    }
                    $semExtraDetails = new \stdClass();
                    $semExtraDetails->academicTermId = $semester->academicTermId;
                    $semExtraDetails->isPG = $semester->isPG;
                    $semExtraDetails->examAttendedGroupId = $semester->examAttendedGroupId;
                    $semExtraDetails->markHistory = $distinctExam->markHistory;
                    $semExtraDetails->examMonth = $distinctExam->examMonth;
                    $semExtraDetails->examYear = $distinctExam->examYear;
                    $semExtraDetails->isPg = $studentData->isPg;
                    $semExtraDetails->examRegistrationId = $distinctExam->examRegistrationId;
                    $semHistory =  $this->semesterHistoryProcess($semester->examRegistration[$subjectHistory->examRegistrationId]->subjectHistory, $semExtraDetails, $request);
                    $semester->markHistory[] = $semHistory;
                }
            }
            /**
             * In 'semesterGradeDetails' the percentage cannot be always in 100.
             * So inorder to handle that '$maxPercent' is used.
             */
            $studentData->percentage = $studentData->totalMark ? ( $maxPercent * $studentData->totalMarkObtained / $studentData->totalMark) : 0;
            $studentData->percentage = round($studentData->percentage, 2);
            $schemeType = current($semesterGradeDetails)->schemeType;
            if ($studentData->credit) {
                $studentData->cgpa = $studentData->creditGradePoint / $studentData->credit;
                if($request->considerRoundingOffCgpa){
                    $studentData->cgpa = $studentData->cgpa ? round($studentData->cgpa,$request->roundingOffCgpaUpto) : $studentData->cgpa;
                }
                // if ($studentData->totalArrears > 0 || $studentData->isFailed ) {
                //     $percentageGrade = $this->getGradeByPercentage(0, $semesterGradeDetails);
                // } else {
                    if ( $schemeType == "CREDIT") {
                        $percentageGrade = $this->getGradeByPercentage($studentData->cgpa, $semesterGradeDetails);
                    }
                    else {
                        $percentageGrade = $this->getGradeByPercentage($studentData->percentage, $semesterGradeDetails);
                    }
                // }
                if (!empty ($percentageGrade)) {
                    $studentData->grade = $percentageGrade->letterGrade;
                    $studentData->class = $percentageGrade->className;
                }
            }
            $studentData->rawCgpa = $studentData->cgpa;
            $studentData->cgpa = $studentData->batchStartYear > 2018 ? round($studentData->cgpa, 3) : round($studentData->cgpa, 2);
            $studentData->markDetails = $this->processStudentCourseData($studentData);
        }
        return $studentArray;
    }
    protected function subjectHistoryProcess($subjectData, $request){
        $subjectmarkHistoryObj = new \stdClass();
        $markHistoryType = $subjectData->examRegType;
        $subjectmarkHistoryObj->code = $subjectData->subjectName;
        $subjectmarkHistoryObj->examMarkType = $markHistoryType;
        $subjectmarkHistoryObj->examRegistrationId = $subjectData->examRegistrationId;
        $subjectmarkHistoryObj->assessmentId = $subjectData->assessmentId;
        $subjectmarkHistoryObj->oeExamId = $subjectData->oeExamId;
        $subjectmarkHistoryObj->studentAttendanceStatus = $subjectData->externalAttendanceStatus;
        $subjectmarkHistoryObj->academicPaperSubjectId = $subjectData->academicPaperSubjectId;
        $subjectmarkHistoryObj->groupId = $subjectData->groupId;
        $subjectmarkHistoryObj->academicTermId = $subjectData->academicTermId;
        $subjectmarkHistoryObj->credit = $subjectData->credit;
        $subjectmarkHistoryObj->externalMark = $subjectData->externalMark;
        $subjectmarkHistoryObj->externalMarkObtainedInExam = $subjectData->markObtainedInExam;
        $subjectmarkHistoryObj->externalMaxMark = $subjectData->externalMaxMark;
        $subjectmarkHistoryObj->externalGrade = $subjectData->externalGrade->letterGrade;
        $subjectmarkHistoryObj->externalGradePoint = $subjectData->externalGrade->gradePoint ?? 0;
        $subjectmarkHistoryObj->isExternalFailed = $subjectData->isExternalFailed;
        $subjectmarkHistoryObj->markObtained = $subjectData->totalMarkObtained;
        $subjectmarkHistoryObj->totalMark = $subjectData->internalMaxMark + $subjectData->externalMaxMark;
        $subjectmarkHistoryObj->percentage = $subjectData->overallPercent;
        $subjectmarkHistoryObj->internalMark = $subjectData->internalMark;
        $subjectmarkHistoryObj->internalMaxMark = $subjectData->internalMaxMark;
        // $subjectmarkHistoryObj->isInternalNull = $subjectData->isInternalNull;
        $subjectmarkHistoryObj->internalAttendanceStatus = $subjectData->internalAttendanceStatus;
        $subjectmarkHistoryObj->internalGrade = $subjectData->internalGrade->letterGrade;
        $subjectmarkHistoryObj->internalGradePoint = $subjectData->internalGrade->gradePoint;
        $subjectmarkHistoryObj->isInternalFailed = $subjectData->isInternalFailed;
        
        $subjectmarkHistoryObj->creditxMark = $subjectData->credit * $subjectmarkHistoryObj->markObtained;
        $subjectmarkHistoryObj->grade = $subjectData->grade->letterGrade;
        $subjectmarkHistoryObj->class = $subjectData->grade->className;
        $subjectmarkHistoryObj->percentageObtainedExternal = $subjectData->externalPercent;
        $subjectmarkHistoryObj->percentageObtainedInternal = $subjectData->internalPercent;
        $subjectmarkHistoryObj->gradePoint = $subjectData->grade->gradePoint ?? 0;
        $subjectmarkHistoryObj->creditGradePoint = $subjectData->creditGradePoint;
        $subjectmarkHistoryObj->examMonth = $subjectData->examMonth;
        $subjectmarkHistoryObj->examYear = $subjectData->examYear;
        $subjectmarkHistoryObj->attendanceStatus = $subjectData->externalAttendanceStatus;
        $subjectmarkHistoryObj->externalAttendanceStatus = $subjectData->externalAttendanceStatus;
        $subjectmarkHistoryObj->resultStatus = $subjectData->isFailed ? "FAILED" : "PASSED";
        $subjectmarkHistoryObj->isFailed = $subjectData->isFailed;
        $subjectmarkHistoryObj->markNeededToPass = $subjectData->isFailed ? $subjectData->markNeededToPass : 0;
        $subjectmarkHistoryObj->markNeededToPassExternal = $subjectData->isExternalFailed ? $subjectData->markNeededToPassExternal : 0;
        $subjectmarkHistoryObj->markNeededToPassOverAll = $subjectData->isFailed ? $subjectData->markNeededToPassOverAll : 0;
        $subjectmarkHistoryObj->isInternal = $subjectData->isInternal;
        $subjectmarkHistoryObj->excludeSubjectFromTotal = $subjectData->excludeSubjectFromTotal;
        $subjectmarkHistoryObj->isExternal = $subjectData->isExternal;        
        
        $subjectmarkHistoryObj->examName = trim($subjectData->subjectCode);
        if( !empty($subjectData->writternHistory) ){
            $writternHistory = $subjectData->writternHistory;
            $subjectmarkHistoryObj->externalMarkObtainedInExamMark = $writternHistory->mark;
            $subjectmarkHistoryObj->externalMarkObtainedInExamGrade = $writternHistory->grade;
            $subjectmarkHistoryObj->externalMarkObtainedInExamGradePoint = $writternHistory->gradePoint;
            $subjectmarkHistoryObj->externalMarkObtainedInExamCreditGradePoint = $writternHistory->creditGradePoint;
            $subjectmarkHistoryObj->externalMarkObtainedInExamIsFailed = $writternHistory->isFailed;
        }
        if( !empty($subjectData->revaluationHistory) ){
            $revaluationHistory = $subjectData->revaluationHistory;
            $subjectmarkHistoryObj->revaluationMark = $revaluationHistory->mark;
            $subjectmarkHistoryObj->revaluationGrade = $revaluationHistory->grade;
            $subjectmarkHistoryObj->revaluationGradePoint = $revaluationHistory->gradePoint;
            $subjectmarkHistoryObj->revaluationCreditGradePoint = $revaluationHistory->creditGradePoint;
            $subjectmarkHistoryObj->revaluationIsFailed = $revaluationHistory->isFailed;
        }
        if( !empty($subjectData->moderationHistory) ){
            $moderationHistory = $subjectData->moderationHistory;
            $subjectmarkHistoryObj->moderationMark = $moderationHistory->mark;
            $subjectmarkHistoryObj->moderationGrade = $moderationHistory->grade;
            $subjectmarkHistoryObj->moderationGradePoint = $moderationHistory->gradePoint;
            $subjectmarkHistoryObj->moderationCreditGradePoint = $moderationHistory->creditGradePoint;
            $subjectmarkHistoryObj->moderationIsFailed = $moderationHistory->isFailed;
        }
        return $subjectmarkHistoryObj;
    }
    protected function consolidatedSubjectProcess($subjectData, $regularExamDataFetched){
        $subjectMarkDetails = new \stdClass();
        $subjectMarkDetails->code = $regularExamDataFetched->subjectName;
        $subjectMarkDetails->syllabusCode = $regularExamDataFetched->syllabusCode;
        $subjectMarkDetails->priority = $regularExamDataFetched->subjectPriority;
        $subjectMarkDetails->categoryId = $regularExamDataFetched->subjectCatId;
        $subjectMarkDetails->categoryName = $regularExamDataFetched->subjectCatName;
        $subjectMarkDetails->categoryCode = $regularExamDataFetched->subjectCatCode;
        $subjectMarkDetails->academicPaperSubjectId = $subjectData->academicPaperSubjectId;
        $subjectMarkDetails->groupId = $subjectData->groupId;
        $subjectMarkDetails->isInternal = $subjectData->isInternal;
        $subjectMarkDetails->excludeSubjectFromTotal = $subjectData->excludeSubjectFromTotal;
        $subjectMarkDetails->internalMark = $subjectData->internalMark;
        $subjectMarkDetails->isInternalNull = $subjectData->isInternalNull;
        $subjectMarkDetails->internalAttendanceStatus = $subjectData->internalAttendanceStatus;
        $subjectMarkDetails->internalMaxMark = $subjectData->internalMaxMark;
        $subjectMarkDetails->academicTermId = $subjectData->academicTermId;
        // $subjectMarkDetails->graceMark = $subjectData->graceMark;
        $subjectMarkDetails->internalGrade = $subjectData->internalGrade;
        $subjectMarkDetails->internalGradePoint = $subjectData->internalGradePoint;
        $subjectMarkDetails->isInternalFailed = $subjectData->isInternalFailed;
        $subjectMarkDetails->internalAttendance = $subjectData->internalAttendanceStatus;
        $subjectMarkDetails->isExternal = $subjectData->isExternal;
        $subjectMarkDetails->externalMark = $subjectData->externalMark;
        $subjectMarkDetails->externalMaxMark = $subjectData->externalMaxMark;
        $subjectMarkDetails->externalGrade = $subjectData->externalGrade;
        $subjectMarkDetails->externalGradePoint = $subjectData->externalGradePoint;
        $monthYearOfPassing = date ( "M Y", strtotime ( $subjectData->examYear . "-" . $subjectData->examMonth . "-01"));
        $subjectMarkDetails->isExternalFailed = $subjectData->isExternalFailed;
        $subjectMarkDetails->maxGradePercent = $regularExamDataFetched->maxGradePercent;
        $subjectMarkDetails->maxGradePoint = $regularExamDataFetched->maxGradePoint;
        $subjectMarkDetails->examMonth = $subjectData->examMonth;
        $subjectMarkDetails->examYear = $subjectData->examYear;
        $subjectMarkDetails->monthYearOfPassing = $monthYearOfPassing;
        $subjectMarkDetails->isTheory = $regularExamDataFetched->isTheory;
        // $subjectMarkDetails->supplyAttemptCount = $subjectData->supplyAttemptCount;
        $subjectMarkDetails->credit = $subjectData->credit;
        $subjectMarkDetails->creditGradePoint = $subjectData->creditGradePoint;
        $subjectMarkDetails->markNeededToPass = abs($subjectData->markNeededToPass);
        $subjectMarkDetails->gradePoint = $subjectData->gradePoint;
        $subjectMarkDetails->grade = $subjectData->grade;
        $subjectMarkDetails->class = $subjectData->class ? $subjectData->class : "";
        $subjectMarkDetails->creditxMark = $subjectData->creditxMark;
        $subjectMarkDetails->markObtained = $subjectData->markObtained;
        $subjectMarkDetails->totalMarks = $subjectData->totalMark;
        $subjectMarkDetails->isFailed = $subjectData->isFailed;
        $subjectMarkDetails->percentageObtainedExternal = $subjectData->percentageObtainedExternal;
        $subjectMarkDetails->percentageObtainedInternal = $subjectData->percentageObtainedInternal;
        $subjectMarkDetails->internalPassPercentage = $regularExamDataFetched->internalPassPercentage;
        $subjectMarkDetails->externalPassPercentage = $regularExamDataFetched->externalPassPercentage;
        $subjectMarkDetails->aggregatePassPercentage = $regularExamDataFetched->aggregatePassPercentage;
        $subjectMarkDetails->attendance = $subjectData->externalAttendanceStatus;
        $subjectMarkDetails->latestExamYear = date("Y",strtotime("01 $monthYearOfPassing"));
        $subjectMarkDetails->latestExamMonth = date("m",strtotime("01 $monthYearOfPassing"));
        $subjectMarkDetails->latestExamType = $subjectData->examMarkType;
        $subjectMarkDetails->attendanceStatus = $subjectData->externalAttendanceStatus;
        $subjectMarkDetails->internalMark = $subjectData->internalMark;
        $subjectMarkDetails->internalMaxMark = $subjectData->internalMaxMark;
        $subjectMarkDetails->internalResultStatus = $subjectData->isInternalFailed ? "FAILED" : "PASSED";
        $subjectMarkDetails->externalMark = $subjectData->externalMark;
        $subjectMarkDetails->externalMaxMark = $subjectData->externalMaxMark;
        $subjectMarkDetails->externalResultStatus = $subjectData->isExternalFailed ? "FAILED" : "PASSED";
        $subjectMarkDetails->maxGradePoint = $regularExamDataFetched->maxGradePoint;
        $subjectMarkDetails->maxGradePercentage = $regularExamDataFetched->maxGradePercent;
        $subjectMarkDetails->resultStatus = $subjectData->isFailed ? "FAILED" : "PASSED";
        return $subjectMarkDetails;
    }
    protected function semesterHistoryProcess($subjects, $semExtraDetails, $request){
        $semObject = new \stdClass();
        $examSampleData = reset($subjects);
        foreach($subjects as $subjectData ){
            if( !$subjectData->excludeSubjectFromTotal ){
                $semObject->credit += $subjectData->credit;
                $semObject->creditGradePoint += $subjectData->creditGradePoint;
            }
            if ($subjectData->isPG == 0 && (
                $subjectData->subjectType == ExamSubjectTypeConstants::FOUNDATION_COURSE ||
                $subjectData->subjectType == ExamSubjectTypeConstants::OPEN_ELECTIVE ||
                $subjectData->subjectType == ExamSubjectTypeConstants::TERM_PAPER)) {
            continue;
            } else if ($subjectData->isPG == 0 && $subjectData->excludeSubjectFromTotal == 1) {
                continue;
            } else if ($subjectData->isPG == 1 && (
                $subjectData->subjectType == ExamSubjectTypeConstants::OPEN_ELECTIVE ||
                $subjectData->subjectType == ExamSubjectTypeConstants::IGNITORS )) {
                continue;
            }
            $semObject->totalMarks += $subjectData->markObtained;
            $semObject->examTotalMarks += $subjectData->totalMark;
            if ( $subjectData->isFailed ){
                $semObject->arrears++;
            }
        }
        $semesterGradeDetails = $request->semesterGradeSchemeArray[$semExtraDetails->academicTermId]->grade;
        if ( $semObject->arrears ) {
            $semObject->sgpa = "0"; // Please don't update "-"
            $semMarkGrade = $this->getGradeByPercentage(0, $semesterGradeDetails);
            $semObject->isFailed = true;
        } else {
            /**
             * Semester wise aggregate percentage criteria check
             */
            $semesterPercentage = round ( ( $semObject->examTotalMarks ? 100 * $semObject->totalMarks / $semObject->examTotalMarks : 0) , 2);
            if ( $semExtraDetails->isPG == 1 && $semesterPercentage < $request->aggregatePassCriteria ) {
                // $studentObj->isFailed = true;
                $semObject->isFailed = true;
            }
            /** codeEnds **/
            if ( !$semObject->isFailed ) {
                $semObject->sgpa = $semObject->credit ? round($semObject->creditGradePoint / $semObject->credit, 2) : 0;
                $semesterGrade = $this->getGradeByPercentage($semObject->sgpa, $semesterGradeDetails);
            }
        }
        $semObject->grade = $semMarkGrade->letterGrade;
        $semObject->class = $semMarkGrade->className;
        // $semCreditxMark = array_sum(array_column($semester->subject->finalConsolidated, "creditxMark"));
        // $semester->WAS = $semester->credit ? ($semCreditxMark / $semester->credit) : 0;
        $semObject->percentage = ($semObject->totalMarks / $semObject->examTotalMarks) * 100;
        $semObject->rawSgpa = $semObject->credit ? ($semObject->creditGradePoint / $semObject->credit) : 0;
     
        $semHistory = new \stdClass();
        // $semHistory->wgp = $semMarkHis->wgp; 
        $semHistory->creditGradePoint = $semObject->creditGradePoint; 
        $semHistory->groupId = $semExtraDetails->examAttendedGroupId;
        $semHistory->academicTermId = $semExtraDetails->academicTermId;
        $semHistory->examRegistrationId = $semExtraDetails->examRegistrationId;
        $semHistory->rawSgpa = $semObject->rawSgpa; 
        $semHistory->sgpa = $semObject->sgpa; 
        $semHistory->semesterCgpa = $semObject->semesterCgpa; 
        $semHistory->wgpa = $semObject->wgpa ?? 0; 
        $semHistory->class = $semObject->class; 
        $semHistory->grade = $semObject->grade; 
        $semHistory->examYear = $semExtraDetails->examYear;
        $semHistory->examMonth = $semExtraDetails->examMonth;
        $semHistory->isFailed = $semObject->isFailed;
        $semHistory->totalMark = $semObject->examTotalMarks;
        $semHistory->gradePoint = $semObject->gradePoint ?? 0;
        $semHistory->markObtained = $semObject->totalMarks; 
        $semHistory->totalMarks = $semObject->examTotalMarks; 
        // $semHistory->totalEarnedCredits = $semObject->totalEarnedCredits;
        // $semHistory->earnedCredit = $semObject->earnedCredit;
        $semHistory->percentage = ($semHistory->markObtained / $semHistory->totalMarks) * 100; 
        $semHistory->creditxMark = $semObject->creditxMark; 
        $semHistory->failedStatus = $semObject->isFailed ? "FAILED" : "PASSED"; 
        $semHistory->historyType = $semExtraDetails->markHistory;
        return $semHistory;
    }
    protected function getCalculatedSubjectForMarkHistory($request, $subject, $semId, $markHistory)
    {
        $searchRequest = new \stdClass();
        // $searchRequest->groupId = $request->groupId;
        $searchRequest->academicTermId = $semId;
        $searchRequest->academicPaperSubjectId = $subject->academicPaperSubjectId;
        $gradeDetails =  $request->subjectGradeSchemeArray[$subject->academicPaperSubjectId]->grades;
        $maxGradePercent = $gradeDetails[0]->rangeTo;
        $checkPassPercentCriteria = new \stdClass(); 
        $checkPassPercentCriteria->isInternal = $subject->isInternal;
        $checkPassPercentCriteria->internalMaxMark = $subject->internalMaxMark;
        
        $checkPassPercentCriteria->isExternal = $subject->isExternal;
        $checkPassPercentCriteria->externalMaxMark = $subject->externalMaxMark;
        $checkPassPercentCriteria->internalMark = round($subject->internalMark);
        // $checkPassPercentCriteria->considerOverallPassCriteriaOnly = $considerOverallPassCriteriaOnly;
        $checkPassPercentCriteria->passPercentConfig = $request->passCriteriaArray[$subject->academicPaperSubjectId];
        $checkPassPercentCriteria->externalMark = $markHistory->mark;
        $isFailedForTheSubject = $this->checkIsFailedByPassPercentCriteria ( $checkPassPercentCriteria );
        if ( $isFailedForTheSubject ) {
            $percentageObtained = 0;
            // $semesterGradePercentObtained = 0;
        }
        else {
            $percentageObtained = $maxGradePercent * (round($subject->internalMark) + $markHistory->mark) / ($subject->externalMaxMark + $subject->internalMaxMark);
            $percentageObtained = round($percentageObtained, 2);
           
            // $semesterGradePercentObtained = $maxSemesterGradePercent * $studentExamTotal / $examTotal;
            // $semesterGradePercentObtained = round($semesterGradePercentObtained, 2);
        }
        $grade = $this->getGradeByPercentage($percentageObtained, $gradeDetails);
        if (!empty ($grade)) {
            $creditGradePoint = ($subject->credit * $grade->gradePoint);
            if ($grade->failStatus == 1) {
                $isFailedForTheSubject = 1;
            }
        }
        $grade->isFailed = $isFailedForTheSubject;
        $grade->creditGradePoint = $creditGradePoint;
        return $grade;
    }
    protected function calculateRegistrationWiseData($semester){
        $semMarkDetails = new \stdClass();
        // $semMarkDetails->noOfChancesTaken = max(array_column(array_column($semMarkDetails->subject,"consolidated"),"noOfChancesTaken"));
        // $semMarkDetails->totalEarnedCredits = $semMarkDetails->totalEarnedCredits;
        $semMarkDetails->id = $semester->academicTermId;
        $semMarkDetails->name = $semester->semName;
        $semMarkDetails->credit = $semester->credit;
        $semMarkDetails->creditGradePoint = $semester->creditGradePoint;
        $semMarkDetails->latestExamMonth = $semester->lastExamMonth;
        $semMarkDetails->latestExamYear = $semester->lastExamYear;
        $semMarkDetails->latestExamType = $semester->lastExamReg;
        // $semMarkDetails->arrearCount = $semester->consolidated->noOfArrears;/
        // $semMarkDetails->supplyAttemptCount = $semester->consolidated->supplyAttemptCount;
        $semMarkDetails->sgpa = $semester->sgpa;
        $semMarkDetails->rawSgpa = $semester->rawSgpa;
        $semMarkDetails->semesterCgpa = $semester->semesterCgpa;
        // $semMarkDetails->wgpa = $semester->consolidated->wgpa ?? 0;
        $semMarkDetails->gradePoint = $semester->gradePoint;
        $semMarkDetails->grade = $semester->grade;
        $semMarkDetails->class = $semester->class;
        $semMarkDetails->percentage = $semester->percentage;
        $semMarkDetails->creditxMark = $semester->creditxMark;
        $semMarkDetails->markObtained = $semester->totalMarks;
        $semMarkDetails->totalMarks = $semester->examTotalMarks;
        // $semMarkDetails->passPercentage = $student->aggregatePassCriteria;
        $semMarkDetails->isFailed = $semester->isFailed;
        return $semMarkDetails;
    }
    protected function processStudentCourseData($student){
        $studentMarkDetails = new \stdClass();
        // $studentMarkDetails->noOfChancesTaken = max(array_column(array_column(array_column($student->semMarks,"consolidated"),"markDetails"),"noOfChancesTaken"));
        $studentMarkDetails->credit = $student->credit;
        $studentMarkDetails->creditGradePoint = $student->creditGradePoint;
        $studentMarkDetails->latestExamYear = $student->lastExamYear;
        $studentMarkDetails->latestExamMonth = $student->lastExamMonth;
        $studentMarkDetails->latestExamType = $student->lastExamReg;
        $studentMarkDetails->totalMaxMark = $student->totalMark;
        // $studentMarkDetails->arrearCount = $student->totalArrears;
        // $studentMarkDetails->supplyAttemptCount = $student->supplyAttemptCount;
        $studentMarkDetails->credit = $student->credit;
        $studentMarkDetails->creditGradePoint = $student->creditGradePoint;
        $studentMarkDetails->markObtained = $student->totalMarkObtained;
        $studentMarkDetails->totalMarks = $student->totalMark;
        $studentMarkDetails->isFailed = $student->isFailed;
        $studentMarkDetails->cgpa = $student->cgpa;
        $studentMarkDetails->rawCgpa = $student->rawCgpa;
        // $studentMarkDetails->cgpaWithoutGracemark = $studentDetailsWithoutGracemark->cgpa;
        // $studentMarkDetails->rawCgpaWithoutGracemark = $studentDetailsWithoutGracemark->rawCgpa;
        // $studentMarkDetails->wgp = $student->wgp;
        $studentMarkDetails->wgpa = $student->wgpa ?? 0;
        $studentMarkDetails->gradePoint = $student->gradePoint;
        $studentMarkDetails->creditxMark = $student->creditxMark;
        $studentMarkDetails->grade = $student->grade;
        $studentMarkDetails->class = $student->class;
        // $studentMarkDetails->creditxMark = $student->creditxMark;
        // $studentMarkDetails->passingYear = $student->passingYear;
        // $studentMarkDetails->passingMonth = $student->passingMonth;
        // $studentMarkDetails->hasCompletedAcademicYear = $student->hasCompletedAcademicYear;
        
        // if( !$student->isFailed && !$student->hasPassYearUpdated && $student->hasCompletedAcademicYear ){
        //     if ( $student->finalRegularExamYear < $student->lastSupplyYear ) {
        //         $studentMarkDetails->passingYear = $student->lastSupplyYear;
        //         $studentMarkDetails->passingMonth = $student->lastSupplyMonth;
        //     } else if  ($student->finalRegularExamYear == $student->lastSupplyYear && $student->finalRegularExamMonth < $student->lastSupplyMonth) {
        //         $studentMarkDetails->passingYear = $student->lastSupplyYear;
        //         $studentMarkDetails->passingMonth = $student->lastSupplyMonth;
        //     }
        //     else{
        //         $studentMarkDetails->passingYear = $student->finalRegularExamYear;
        //         $studentMarkDetails->passingMonth = $student->finalRegularExamMonth;
        //     }
        // }
        return $studentMarkDetails;
    }
    protected function getGradeByPercentage($percentage, $gradeDetails)
    {
        foreach ($gradeDetails as $grade) {
            if ($grade->rangeFrom <= $percentage && $grade->rangeTo >= $percentage) {
                return $grade;
            }
        }
        return null;
    }
    protected function getStudentExamDetails($assessmentId, $studentId, $examDetails)
    {
        $examMark = null;
        $exam = reset(array_filter($examDetails,function($exam)use($assessmentId){
            return $exam->assessmentId == $assessmentId;
        }));
        if($exam){
            $examObject = reset(array_filter($exam->studentMarks,function($studentMarks)use($studentId){
                return $studentMarks->student->studentId == $studentId;
            }));
            if($examObject){
                $examMark = $examObject;
                $examMark->assessmentId = $exam->assessmentId;
                $examMark->examRegistrations = $exam->examRegistrations;
            }
        }
        return $examMark;
    }
    public function checkIsFailedByPassPercentCriteria ( $checkPassPercentCriteria ) {
        $studentExamTotal = 0;
        $examTotal = 0;
        $isFailed = 0;
        $internalPassCriteria = $externalPassCriteria = $overallPassCriteria  = null;
        if ($checkPassPercentCriteria->passPercentConfig->internalPassCriteria) {
            $internalPassCriteria = (float) $checkPassPercentCriteria->passPercentConfig->internalPassCriteria;
        }
        if ($checkPassPercentCriteria->passPercentConfig->externalPassCriteria) {
            $externalPassCriteria = (float) $checkPassPercentCriteria->passPercentConfig->externalPassCriteria;
        }
        if ($checkPassPercentCriteria->passPercentConfig->overallPassCriteria) {
            $overallPassCriteria = (float) $checkPassPercentCriteria->passPercentConfig->overallPassCriteria;
        }
        
        if ($checkPassPercentCriteria->isInternal) {
            $studentExamTotal = round($checkPassPercentCriteria->internalMark);
            $examTotal = $checkPassPercentCriteria->internalMaxMark;
            if (!empty ($internalPassCriteria)) {
                $internalPercent = $checkPassPercentCriteria->internalMaxMark ? (100 * $checkPassPercentCriteria->internalMark / $checkPassPercentCriteria->internalMaxMark) : 0;
                if ( $checkPassPercentCriteria->considerOverallPassCriteriaOnly == 0 ) {
                    $isFailed = $internalPassCriteria <= $internalPercent ? $isFailed : 1;
                }
            }
        }
        if ($checkPassPercentCriteria->isExternal) {
            $studentExamTotal += round($checkPassPercentCriteria->externalMark);
            $examTotal += $checkPassPercentCriteria->externalMaxMark;
            if (!empty ($externalPassCriteria)) {
                $externalPercent = $checkPassPercentCriteria->externalMaxMark ? (100 * 
                    $checkPassPercentCriteria->externalMark / $checkPassPercentCriteria->externalMaxMark) : 0;
                if ( $checkPassPercentCriteria->considerOverallPassCriteriaOnly == 0 ) {
                    $isFailed = $externalPassCriteria <= $externalPercent ? $isFailed : 1;
                }
            }
        }
        if (!empty ($overallPassCriteria)) {
            if (empty($checkPassPercentCriteria->studentExamTotal))
                $overallPercent = $examTotal ? 100 * $studentExamTotal / $examTotal : 0;
            else
                $overallPercent = $checkPassPercentCriteria->totalMaxMark ? 100 * $checkPassPercentCriteria->studentExamTotal / $checkPassPercentCriteria->totalMaxMark : 0;
            $isFailed = $overallPassCriteria <= $overallPercent ? $isFailed : 1;
        }
        
        return $isFailed;
    }
    public function getSemesterGradeDetials($searchReq, $sgpa)
    {
        $searchRequest = new \stdClass();
        $searchRequest->groupId = $searchReq->groupId;
        $searchRequest->academicTermId = $searchReq->academicTermId;
        $searchRequest->requestType = "SEMESTER";
        $semesterGradeDetails = reset(GradeSchemeService::getInstance()->getAllSubjectGradeSchemesByRequest($searchRequest))->grades;
        $semMarkGrade =  $this->getGradeByPercentage($sgpa, $semesterGradeDetails);
        return $semMarkGrade;
    }
   
}