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 / 1309
Template22MigrationdResultGenerator
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 14
83810.00
0.00% covered (danger)
0.00%
0 / 1309
 __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 / 113
 indexExamReport
0.00% covered (danger)
0.00%
0 / 1
506.00
0.00% covered (danger)
0.00%
0 / 43
 checkSubjectPassStatus
0.00% covered (danger)
0.00%
0 / 1
3192.00
0.00% covered (danger)
0.00%
0 / 192
 generateData
0.00% covered (danger)
0.00%
0 / 1
10920.00
0.00% covered (danger)
0.00%
0 / 517
 subjectHistoryProcess
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 100
 consolidatedSubjectProcess
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 69
 semesterHistoryProcess
0.00% covered (danger)
0.00%
0 / 1
650.00
0.00% covered (danger)
0.00%
0 / 89
 getCalculatedSubjectForMarkHistory
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 62
 calculateRegistrationWiseData
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 25
 processStudentCourseData
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 24
 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
506.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 STCP template ----> Template`22` (new rule)
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;
use TCPDFBarcode;
use com\linways\core\ams\professional\util\CommonUtil;
use com\linways\academics\core\request\attendance\AttendanceTermWiseReport;
use com\linways\academics\core\service\attendance\AttendanceService;
class Template22MigrationdResultGenerator 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 = 2;
        $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;
        }
        
        $request->subCourseSubjects = StudentsOverAllMarkReportService::getInstance()->getSubCourseRelationBystudent($request);
        $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;
        $searchRuleRequest = new SearchRuleRequest;
        $searchRuleRequest->name = "EXCLUDE_SUBJECTS_SETTINGS";
        $request->excludeSubjectsSettings = 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);
        
        $cgpaSearchRequest = new \stdClass();
        $cgpaSearchRequest->groupId = $request->groupId;
        $cgpaSearchRequest->requestType = "CURRICULAM";
        $request->cgpaGradeSchemeArray = GradeSchemeService::getInstance()->getAllSubjectGradeSchemesByRequest($cgpaSearchRequest);
        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;
            $revalRequest->skipMapper = 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( $graceMarkDetails ){
                $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" || $markType == "IMPROVEMENT" ){
                if ( $markType == "REVALUATION" ){
                    $studentExamTemp = json_decode(json_encode( $studentArray[$studentExam->studentId]->semester[$studentExam->academicTermId]->subject[$studentExam->academicPaperSubjectId]->markType[$studentExam->parentExamRegistrationType]->exam[$studentExam->parentExamRegistrationId]));
                    $studentExamTemp->externalMark = $studentExam->revaluationMark;
                    $studentExamTemp->revaluationId = $studentExam->revaluationId;
                    $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-------------
                if ( $markType == "SUPPLEMENTARY" || $markType == "IMPROVEMENT" ){
                    if(  $studentExam->improvedInternalMark  || $studentExam->improvedInternalAttendanceStatus){
                        $studentExam->internalMark =  $studentExam->improvedInternalMark;
                        $studentExam->internalAttendanceStatus = $studentExam->improvedInternalAttendanceStatus;
                    }
                }
                $studentExam->credit = $studentExam->subjectCredit;
                if ( !$studentExam->isInternal ){
                    $studentExam->internalMark = null;
                    $studentExam->internalMaxMark = null;
                }
                if ( !$studentExam->isExternal ){
                    $studentExam->externalMark = null;
                    $studentExam->externalMaxMark = null;
                }
                $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) {
            if ($request->subCourseSubjects[$studentExam->amsSubjectId] && $studentExam->classType == "PRACTICAL") {
                $studentExam->internalMark = $studentExam->internalMark / 2;
                $studentExam->internalMaxMark = $studentExam->internalMaxMark / 2;
            }
            else{
                $studentExam->internalMark = $courseTypeMethod == "PG"? round($studentExam->internalMark, 2) : round($studentExam->internalMark) ;
            }
            $studentExamTotal =$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) {
            if ( $request->considerModerationMark ) {
                $studentModerationMark = $studentExam->moderationMark;
                if($studentModerationMark){
                    $studentExam->externalMark +=  $studentExam->moderationMark;
                }
            }
            if ( $request->considerGraceMark ) {
                $graceMark = $studentExam->graceMark;
                if($graceMark){
                    $studentExam->externalMark +=  $studentExam->graceMark;
                }
            }
            if ($courseTypeMethod == "PG" && ( round($studentExam->externalMaxMark, 2) == round( $maxGradePercent, 2))) {
                $studentExternalMark = round($studentExam->externalMark, 2);
                $studentExam->externalMark = round($studentExam->externalMark, 2);
            }
            else{
                $studentExternalMark = round($studentExam->externalMark);
                $studentExam->externalMark = round($studentExam->externalMark);
            }
            if ($request->subCourseSubjects[$studentExam->amsSubjectId] && $studentExam->classType == "PRACTICAL") {
                $studentExternalMark = $studentExam->externalMark = $studentExam->externalMark / 2;
                $studentExam->externalMaxMark = $studentExam->externalMaxMark / 2;
                $studentExamTotal += $studentExternalMark;
                $examTotal += $studentExam->externalMaxMark;
            }
            else{
                $studentExamTotal += $studentExternalMark;
                $examTotal += $studentExam->externalMaxMark;
            }
            $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);
        $x = 1;
        $studentExam->internalPercent = $internalPercent;
        $studentExam->externalPercent = $externalPercent;
        if ($courseTypeMethod == "PG") {
            $studentExam->externalMaxMark = $studentExam->externalMaxMark? $studentExam->externalMaxMark : 0;
            $internalMarkPer = $externalMarkPer = 0;
            $x = 1;
            // $isFailed = 0;
            // $studentExternalMark = round($studentExternalMark);
            if ($studentExam->isInternal) {
                $internalMarkPer = round($maxGradePercent * $studentExam->internalMark / $studentExam->internalMaxMark, 2); 
                $internalGrade = $this->getGradeByPercentage($internalMarkPer, $gradeDetails);
            }
            if ($studentExam->isExternal) {
                $externalMarkPer = round($maxGradePercent * $studentExternalMark / $studentExam->externalMaxMark, 2); 
                $externalGrade = $this->getGradeByPercentage($externalMarkPer, $gradeDetails);
            }
            if ($studentExam->isInternal && $studentExam->isExternal) {
                $gradePoint = round(($internalMarkPer + ( 3 * $externalMarkPer ) ) / 4, 2);
            }
            else {
                $gradePoint = $internalMarkPer + $externalMarkPer;
            }
            $overallPercentPG = 100 * $gradePoint / $maxGradePercent ?? 0;
            if (!empty ($overallPassCriteria)) {
                $isFailed = $overallPassCriteria <= $overallPercentPG ? $isFailed : 1;
            }
            if ($isFailed) {
                $gradePoint = 0;
            }
            $grade = $this->getGradeByPercentage($gradePoint, $gradeDetails);
            $grade = json_decode(json_encode($grade));
            $grade->gradePoint = $gradePoint ? $gradePoint : 0;
            $studentExam->wgpa = $grade->gradePoint;
            $isFailed = $grade->failStatus ? 1 : $isFailed;
            $studentExam->externalPercent = $externalMarkPer;
            $studentExam->internalPercent = $internalMarkPer;
            $externalGrade->gradePoint = $externalMarkPer;
            $internalGrade->gradePoint = $internalMarkPer;
        }
        if (!empty ($grade)) {
            $creditGradePoint = ($studentExam->credit * $grade->gradePoint);
            if ($grade->failStatus == 1) {
                $isFailed = 1;
            }
        }
    
        if($studentExam->internalAttendanceStatus == "ABSENT"){
            $isFailed = 1;
            $isInternalFailed = 1;
        }
        $studentExam->isPG = 0;
        if ($courseTypeMethod == 'PG') {
            $studentExam->isPG = 1;
        }
        //check subject attendance percentage for exclude subjects to set pass/fail status for the subject
        if($studentExam->excludeSubjectFromTotal == "1" && $request->excludeSubjectsSettings->evaluationCriteria == "ATTENDANCE" && $request->excludeSubjectsSettings->minimumAttendance && in_array($studentExam->courseType, $request->excludeSubjectsSettings->courseTypesApplicableForEvaluationByAttendance)){
            $attendanceTermWiseReportRequest = new AttendanceTermWiseReport();
            $attendanceTermWiseReportRequest->studentId = $studentExam->studentId;
            $attendanceTermWiseReportRequest->termId = $studentExam->academicTermId;
            $attendanceTermWiseReportRequest->paperSubjectId = $studentExam->academicPaperSubjectId;
            $attendanceTermWiseReportRequest->attendanceClosingDate = $studentExam->attendanceClosingDate;
            $attendanceDetails = reset(AttendanceService::getInstance()->getTermWiseStudentAttendanceConfirmedReport($attendanceTermWiseReportRequest));
            $attendanceDetails->attendancePercentage = $attendanceDetails->attendancePercentage ?: 0;
            $studentExam->isShortageAttendance  = ($request->excludeSubjectsSettings->minimumAttendance > $attendanceDetails->attendancePercentage) ? true : false;
            $attendanceDetails = null;
            //set pass/fail status based on attendance percentage
            $isFailed = $studentExam->isShortageAttendance ? 1 : 0;
        }
        $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->overallPercent = $overallPercent;
        $studentExam->internalGradePoint = $internalMarkPer;
        $studentExam->externalGradePoint = $externalMarkPer;
        $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 = [];
                $distinctRevaluations = [];
                $mergedSubjectHistory = [];
                foreach ($semester->subject as $semSubjectkey => $subject) {
                    foreach ($subject->markType as $markHistory => $markType) {
                        if ( $markHistory != "REGULAR" && $markHistory != "SUPPLEMENTARY" && $markHistory != "IMPROVEMENT"){
                            continue;
                        }
                        foreach ( $markType->exam as $subjectData) {
                            $hasChangeInExistingMark = 0;
                            $moderationMark = 0;
                            $markObtainedInExam = $subjectData->externalMark;
                            $studentExternalMark = $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();
                            $graceMarkHistory = new \stdClass();
                            $withoutRevaluationMark = new \stdClass();
                            if ( $subject->markType["REVALUATION"]->exam[$subjectData->examRegistrationId]){
                                $subjectData = $subject->markType["REVALUATION"]->exam[$subjectData->examRegistrationId];
                                
                                $revaluationHistory->mark = $subjectData->externalMark;
                                $revaluationHistory->grade = $subjectData->grade->letterGrade;
                                $revaluationHistory->gradePoint = $subjectData->grade->gradePoint;
                                $revaluationHistory->revaluationId = $subjectData->revaluationId;
                                $revaluationHistory->creditGradePoint = $subjectData->creditGradePoint;
                                $revaluationHistory->isFailed = $subjectData->isFailed;
                                $distinctRevaluations[$subjectData->revaluationId]->revaluationId = $subjectData->revaluationId;
                                $distinctRevaluations[$subjectData->revaluationId]->examMonth = $subjectData->examMonth;
                                $distinctRevaluations[$subjectData->revaluationId]->examYear = $subjectData->examYear;
                                $distinctRevaluations[$subjectData->revaluationId]->parentExamRegistrationId = $subjectData->examRegistrationId;
                            }
                            if ( $subject->markType["MODERATION"]->exam[$subjectData->examRegistrationId]){
                                $moderationMark = $subject->markType["MODERATION"]->exam[$subjectData->examRegistrationId];
                                $hasChangeInExistingMark = 1;
                                $subjectData->moderationMark = $moderationMark->externalMark;
                                $subjectMarkType = new \stdClass();
                                $subjectMarkType->mark += $markObtainedInExam + $moderationMark->externalMark;
                                $subjectData = $this->checkSubjectPassStatus($request, $subjectData);
                                $markHistoryStatus = $this->getCalculatedSubjectForMarkHistory($request, $subjectData, $academicTermId, $subjectMarkType);
                                $moderationHistory->mark = $moderationMark->externalMark;
                                $moderationHistory->grade = $markHistoryStatus->letterGrade;
                                $moderationHistory->gradePoint = $markHistoryStatus->gradePoint;
                                $moderationHistory->creditGradePoint = $markHistoryStatus->creditGradePoint;
                                $moderationHistory->isFailed = $markHistoryStatus->isFailed;
                            }
                            if ( $subject->markType["GRACEMARK"]->exam[$subjectData->examRegistrationId]){
                                $graceMark = $subject->markType["GRACEMARK"]->exam[$subjectData->examRegistrationId];
                                $hasChangeInExistingMark = 1;
                                $subjectData->graceMark = $graceMark->externalMark;
                                $subjectMarkType = new \stdClass();
                                $subjectMarkType->mark += $markObtainedInExam + $graceMark->externalMark;
                                $subjectData = $this->checkSubjectPassStatus($request, $subjectData);
                                $markHistoryStatus = $this->getCalculatedSubjectForMarkHistory($request, $subjectData, $academicTermId, $subjectMarkType);
                                $graceMarkHistory->mark = $graceMark->externalMark;
                                $graceMarkHistory->grade = $markHistoryStatus->letterGrade;
                                $graceMarkHistory->gradePoint = $markHistoryStatus->gradePoint;
                                $graceMarkHistory->creditGradePoint = $markHistoryStatus->creditGradePoint;
                                $graceMarkHistory->isFailed = $markHistoryStatus->isFailed;
                            }
                            if ( $subject->markType["REVALUATION"]->exam[$subjectData->examRegistrationId]){
                                $withoutRevaluationSubjectMarkType = new \stdClass();
                                $withoutRevaluationSubjectMarkType->mark = $markObtainedInExam + $moderationHistory->mark +  $graceMarkHistory->mark ;
                                $subjectDataCopy = json_decode(json_encode($subjectData)); 
                                $withoutRevaluationSubjectData = $this->checkSubjectPassStatus($request, $subjectDataCopy);
                                $markHistoryStatus = $this->getCalculatedSubjectForMarkHistory($request, $withoutRevaluationSubjectData, $academicTermId, $withoutRevaluationSubjectMarkType);
                                $withoutRevaluationMark->mark = $withoutRevaluationSubjectMarkType->mark;
                                $withoutRevaluationMark->grade = $markHistoryStatus->letterGrade;
                                $withoutRevaluationMark->gradePoint = $markHistoryStatus->gradePoint;
                                $withoutRevaluationMark->creditGradePoint = $markHistoryStatus->creditGradePoint;
                                $withoutRevaluationMark->isFailed = $markHistoryStatus->isFailed;
                            }
                            // if( $hasChangeInExistingMark ){
                            //     $subjectData = $this->checkSubjectPassStatus($request, $subjectData);
                            // }
                            $subjectData->writternHistory = $writternHistory;
                            $subjectData->revaluationHistory = $revaluationHistory;
                            $subjectData->moderationHistory = $moderationHistory;
                            $subjectData->graceMarkHistory = $graceMarkHistory;
                            $subjectData->markObtainedInExam = $markObtainedInExam;
                            $subjectData->withoutRevaluationMark = $withoutRevaluationMark;
                            if ( $subjectData->examRegType == "SUPPLEMENTARY" ){
                                $subjectData->examRegType = ExamType::SUPPLY;
                            }
                            $subjectmarkHistoryObj = $this->subjectHistoryProcess($subjectData, $request);
                            if ( $subjectmarkHistoryObj ){
                                $semester->history[] = $subjectmarkHistoryObj;
                                $subject->finalConsolidated->markHistory[] = $subjectmarkHistoryObj;
                                $semester->examRegistration[$subjectmarkHistoryObj->examRegistrationId]->subject = $subjectmarkHistoryObj;
                                if ( $subject->consolidated[$subjectmarkHistoryObj->academicPaperSubjectId] ){
                                    $subject->supplyAttemptCount = $subject->supplyAttemptCount + 1;
                                    $subjectmarkHistoryObj->supplyAttemptCount = $subject->supplyAttemptCount;
                                    if($subject->consolidated[$subjectmarkHistoryObj->academicPaperSubjectId]->internalMark != $subjectmarkHistoryObj->internalMark ){
                                        $subject->hasSupplyInternal = 1;
                                    }
                                    if($subjectmarkHistoryObj->examMarkType == "IMPROVEMENT"){
                                        $subject->hasImprovementChance = 1;
                                        $subject->improveExamMonth = $subjectmarkHistoryObj->examMonth;
                                        $subject->improveExamYear = $subjectmarkHistoryObj->examYear;
                                    }
                                    if ( $subject->consolidated[$subjectmarkHistoryObj->academicPaperSubjectId]->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 $consolidatedKey => $consolidatedSubject ){
                        $regularExamDataFetched = reset($subject->markType["REGULAR"]->exam);
                        if( $subject->hasSupplyInternal ){
                            $internalChangedData = json_decode(json_encode($consolidatedSubject));
                            $internalChangedData->internalMark = $subject->internalMark;
                            $internalChangedData->externalMark = $consolidatedSubject->externalMark;
                            $internalChangedData = $this->checkSubjectPassStatus($request, $internalChangedData);
                            $consolidatedSubject = $this->subjectHistoryProcess($internalChangedData, $request);
                        }
                        if ( $subject->hasImprovementChance ){
                            $consolidatedSubject->hasImprovementChance = $subject->hasImprovementChance;
                            $consolidatedSubject->examMonth = $subject->improveExamMonth;
                            $consolidatedSubject->examYear = $subject->improveExamYear;
                        }
                        $subjectMarkDetails = $this->consolidatedSubjectProcess($consolidatedSubject, $regularExamDataFetched); 
                        if ($request->subCourseSubjects[$consolidatedSubject->amsSubjectId]){
                            $mergedSubjectHistory[$request->subCourseSubjects[$consolidatedSubject->amsSubjectId]->parentSubjectId]->subject[$consolidatedSubject->amsSubjectId] = $subjectMarkDetails;
                            $subjectMarkDetails->parentSubjectId = $request->subCourseSubjects[$consolidatedSubject->amsSubjectId]->parentSubjectId;
                            $mergedSubjectHistory[$request->subCourseSubjects[$consolidatedSubject->amsSubjectId]->parentSubjectId]->subject[$consolidatedSubject->amsSubjectId]->consolidatedKey = $semSubjectkey;
                        }
                        $subject->finalConsolidated->markDetails = $subjectMarkDetails;
                        $subject->finalConsolidated->groupId = $subjectMarkDetails->groupId;
                        $subject->finalConsolidated->id = $subjectMarkDetails->academicPaperSubjectId;
                        $subject->finalConsolidated->studentId = $studentId;
                        $subject->finalConsolidated->noOfChancesTaken = $subjectMarkDetails->supplyAttemptCount + 1;
                        $subject->finalConsolidated->supplyAttemptCount = $subjectMarkDetails->supplyAttemptCount;
                        $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 will show as passed even if exclude subject is failed it is considered to be failed in cgpa calc only
                            // $semester->arrears++;
                            $studentData->totalArrears++;
                        }
                        if ( $semester->supplyAttemptCount < $subject->finalConsolidated->supplyAttemptCount ){
                            $semester->supplyAttemptCount = $subject->finalConsolidated->supplyAttemptCount;
                        }
                        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->lastExamYear == $subjectMarkDetails->examYear && 
                        $semester->lastExamMonth < $subjectMarkDetails->examMonth ) {
                            $semester->lastExamMonth = $subjectMarkDetails->examMonth;
                            $semester->lastExamReg = $consolidatedSubject->examMarkType;
                        }
                        if ($request->subCourseSubjects[$consolidatedSubject->amsSubjectId]){
                            continue;
                        }
                        $studentData->allCredit += $consolidatedSubject->credit;
                        if( !$consolidatedSubject->excludeSubjectFromTotal ){
                            if ( $subjectMarkDetails->isFailed ){
                                $semester->arrears++;
                            }
                            $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->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;
                    }
                }
                foreach($mergedSubjectHistory as $mergedSubject){
                    $subCoursesInternalMark = 0;
                    $subCoursesInternalMaxMark = 0;
                    $subCoursesExternalMark = 0;
                    $subCoursesExternalMaxMark = 0;
                    $subCoursesTotalObtainedMark = 0;
                    $subCoursesTotalMaxMark = 0;
                    $subCoursesTotalCredit = 0;
                    $subCoursesIsFailed = 0;
                    foreach($mergedSubject->subject as $singleSubject){
                        $subCoursesInternalMark += $singleSubject->internalMark;
                        $subCoursesInternalMaxMark += $singleSubject->internalMaxMark;
                        $subCoursesExternalMark += $singleSubject->externalMark;
                        $subCoursesExternalMaxMark += $singleSubject->externalMaxMark;
                        $subCoursesTotalObtainedMark += $singleSubject->markObtained;
                        $subCoursesTotalMaxMark += $singleSubject->totalMarks;
                        $subCoursesTotalCredit += $singleSubject->credit;
                        if ( $singleSubject->isFailed ){
                            $subCoursesIsFailed = $singleSubject->isFailed;
                        }
                    }
                    $subCoursesTotalObtainedMark = round($subCoursesTotalObtainedMark);
                    $gradeDetails = $request->subjectGradeSchemeArray[$singleSubject->academicPaperSubjectId]->grades;
                    $maxGradePercent = $gradeDetails[0]->rangeTo;
                    if ( $subCoursesIsFailed ) {
                        $percentageObtained = 0;
                    }
                    else {
                        $percentageObtained = $maxGradePercent * $subCoursesTotalObtainedMark / $subCoursesTotalMaxMark;
                        $percentageObtained = round($percentageObtained, 2);
                    }
                    $grade = $this->getGradeByPercentage($percentageObtained, $gradeDetails);
                    if (!empty ($grade)) {
                        $subCoursesGradePoint = $grade->gradePoint;
                        $subCoursesCreditGradePoint = ($subCoursesTotalCredit * $grade->gradePoint);
                        if ($grade->failStatus == 1) {
                            $subCoursesIsFailed = 1;
                        }
                        $subCoursesGrade = $grade->letterGrade;
                        $subCoursesClassName = $grade->className;
                    }
                    foreach($mergedSubject->subject as $singleSubject){
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesInternalMark = $subCoursesInternalMark;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesInternalMaxMark = $subCoursesInternalMaxMark;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesExternalMark = $subCoursesExternalMark;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesExternalMaxMark = $subCoursesExternalMaxMark;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesTotalObtainedMark = $subCoursesTotalObtainedMark;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesTotalMaxMark = $subCoursesTotalMaxMark;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesTotalCredit = $subCoursesTotalCredit;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesIsFailed = $subCoursesIsFailed;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesGrade = $subCoursesGrade;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesClassName = $subCoursesClassName;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesGradePoint = $subCoursesGradePoint;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesCreditGradePoint = $subCoursesCreditGradePoint;
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->subCoursesResultStatus = $subCoursesIsFailed == 1 ? 'FAILED' : 'PASSED';
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->grade = "";
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->gradePoint = "";
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->creditGradePoint = "";
                        $semester->subject[$singleSubject->consolidatedKey]->finalConsolidated->markDetails->class = "";
                    }
                    $studentData->allCredit += $subCoursesTotalCredit;
                    if( !$singleSubject->excludeSubjectFromTotal ){
                        if ( $subjectMarkDetails->isFailed ){
                            $semester->arrears++;
                        }
                        $semester->credit += $subCoursesTotalCredit;
                        $semester->creditGradePoint += $subCoursesCreditGradePoint;
                        $studentData->credit += $subCoursesTotalCredit;
                        $studentData->creditGradePoint += $subCoursesCreditGradePoint;
                    }
                    $studentData->totalMarkObtained += $subCoursesTotalObtainedMark;
                    $studentData->totalMark += $subCoursesTotalMaxMark;
                    $semester->totalMarks += $subCoursesTotalObtainedMark;
                    $semester->examTotalMarks += $subCoursesTotalMaxMark;
                }
                $semesterGradeDetails = $request->semesterGradeSchemeArray[$academicTermId]->grades;
                $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->sgpa = $semester->credit ? round($semester->creditGradePoint / $semester->credit, 2) : 0;
                    $semester->isFailed = true;
                    $studentData->isFailed = true;
                } else {
                    /**
                     * Semester wise aggregate percentage criteria check
                     */
                    $semesterPercentage = round ( ( $semester->examTotalMarks ? 100 * $semester->totalMarks / $semester->examTotalMarks : 0) , 2);
                    //only for PG students SJU
                    // if ( $studentData->isPG == 1 && $semesterPercentage < 50 ) {
                    //     $studentData->isFailed = true;
                    //     $semester->isFailed = true;
                    // }
                    /** codeEnds **/
                    $semester->sgpa = $semester->credit ? round($semester->creditGradePoint / $semester->credit, 2) : 0;
                    if ( !$semester->isFailed ) {
                        $semMarkGrade = $this->getGradeByPercentage($semester->sgpa, $semesterGradeDetails);
                    }
                    else{
                        $semMarkGrade = $this->getGradeByPercentage(0, $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;
                $semester->roundedSgpaxCredit = round($semester->rawSgpa,2) * $semester->credit;
                $studentData->totalSgpaCreditGradePoint += $semester->roundedSgpaxCredit;
                $studentData->totalSgpaCredits +=  $semester->credit;
                if ($studentData->totalArrears > 0) {
                    $studentData->isFailed = true;
                }
                $semConsolidated = $this->calculateRegistrationWiseData( $semester);
                $semester->groupId = $subjectMarkDetails->groupId;
                $semester->studentId = $studentId;
                $semester->status = $semConsolidated->status;
                $studentData->groupId = $subjectMarkDetails->groupId;
                $studentData->studentId = $studentId;
                $semester->markDetails = $semConsolidated;
                $semester->supplyAttemptCount = $semConsolidated->supplyAttemptCount ? $semConsolidated->supplyAttemptCount : 0 ;
                $studentData->supplyAttemptCount = 0;
                
                foreach( $distinctExamRegistration as $distinctExam ){
                    $mergedSubjectHistory = [];
                    foreach ($semester->history as $historyKey => $subjectHistory ){
                        if ( $distinctExam->examYear."-".date("m", mktime(0, 0, 0, (int)$distinctExam->examMonth, 10)) >= $subjectHistory->examYear."-".date("m", mktime(0, 0, 0, (int)$subjectHistory->examMonth, 10) )){
                            if( $distinctExam->markHistory == "REGULAR" && $subjectHistory->examMarkType != "REGULAR" ){
                                continue;
                            }
                            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($semester->subject[$subjectHistory->academicPaperSubjectId]->markType["REGULAR"]->exam);
                                    if ( $regularExamDataFetched->internalMark != $subjectHistory->internalMark){
                                        $maxInternalObtained = max($regularExamDataFetched->internalMark,$subjectHistory->internalMark);
                                        $internalChangedExamData = json_decode(json_encode($subjectHistory));
                                        $internalChangedExamData->internalMark = $maxInternalObtained;
                                        $internalChangedExamData->externalMark = $subjectHistory->externalMark;
                                        $internalChangedExamData = $this->checkSubjectPassStatus($request, $internalChangedExamData);
                                        $subjectHistory = $this->subjectHistoryProcess($internalChangedExamData, $request);
                                        $semester->examRegistration[$distinctExam->examRegistrationId]->subjectHistory[$subjectHistory->academicPaperSubjectId] = $subjectHistory;
                                        if ($request->subCourseSubjects[$subjectHistory->amsSubjectId]){
                                            $mergedSubjectHistory[$request->subCourseSubjects[$subjectHistory->amsSubjectId]->parentSubjectId]->subject[$subjectHistory->amsSubjectId] = $subjectHistory;
                                            $subjectHistory->parentSubjectId = $request->subCourseSubjects[$subjectHistory->amsSubjectId]->parentSubjectId;
                                            $mergedSubjectHistory[$request->subCourseSubjects[$subjectHistory->amsSubjectId]->parentSubjectId]->subject[$subjectHistory->amsSubjectId]->historyKey = $historyKey;
                                        }
                                    }
                                }
                            }
                            else{
                                $semester->examRegistration[$distinctExam->examRegistrationId]->subjectHistory[$subjectHistory->academicPaperSubjectId] = $subjectHistory;
                                if ($request->subCourseSubjects[$subjectHistory->amsSubjectId]){
                                    $mergedSubjectHistory[$request->subCourseSubjects[$subjectHistory->amsSubjectId]->parentSubjectId]->subject[$subjectHistory->amsSubjectId] = $subjectHistory;
                                    $subjectHistory->parentSubjectId = $request->subCourseSubjects[$subjectHistory->amsSubjectId]->parentSubjectId;
                                    $mergedSubjectHistory[$request->subCourseSubjects[$subjectHistory->amsSubjectId]->parentSubjectId]->subject[$subjectHistory->amsSubjectId]->historyKey = $historyKey;
                                }
                            }
                            
                        }
                    }
                    foreach($mergedSubjectHistory as $mergedSubject){
                        $subCoursesInternalMark = 0;
                        $subCoursesInternalMaxMark = 0;
                        $subCoursesExternalMark = 0;
                        $subCoursesExternalMaxMark = 0;
                        $subCoursesTotalObtainedMark = 0;
                        $subCoursesTotalMaxMark = 0;
                        $subCoursesTotalCredit = 0;
                        $subCoursesIsFailed = 0;
                        foreach($mergedSubject->subject as $singleSubject){
                            $subCoursesInternalMark += $singleSubject->internalMark;
                            $subCoursesInternalMaxMark += $singleSubject->internalMaxMark;
                            $subCoursesExternalMark += $singleSubject->externalMark;
                            $subCoursesExternalMaxMark += $singleSubject->externalMaxMark;
                            $subCoursesTotalObtainedMark += $singleSubject->markObtained;
                            $subCoursesTotalMaxMark += $singleSubject->totalMark;
                            $subCoursesTotalCredit += $singleSubject->credit;
                            if ( $singleSubject->isFailed ){
                                $subCoursesIsFailed = $singleSubject->isFailed;
                            }
                        }
                        $subCoursesTotalObtainedMark = round($subCoursesTotalObtainedMark);
                        $gradeDetails = $request->subjectGradeSchemeArray[$singleSubject->academicPaperSubjectId]->grades;
                        $maxGradePercent = $gradeDetails[0]->rangeTo;
                        if ( $subCoursesIsFailed ) {
                            $percentageObtained = 0;
                        }
                        else {
                            $percentageObtained = $maxGradePercent * $subCoursesTotalObtainedMark / $subCoursesTotalMaxMark;
                            $percentageObtained = round($percentageObtained, 2);
                        }
                        $grade = $this->getGradeByPercentage($percentageObtained, $gradeDetails);
                        if (!empty ($grade)) {
                            $subCoursesGradePoint = $grade->gradePoint;
                            $subCoursesCreditGradePoint = ($subCoursesTotalCredit * $grade->gradePoint);
                            if ($grade->failStatus == 1) {
                                $subCoursesIsFailed = 1;
                            }
                            $subCoursesGrade = $grade->letterGrade;
                            $subCoursesClassName = $grade->className;
                        }
                        foreach($mergedSubject->subject as $singleSubject){
                            if ( $singleSubject->examRegistrationId == $distinctExam->examRegistrationId && ($singleSubject->historyKey || $singleSubject->historyKey == 0)){
                                $semester->history[$singleSubject->historyKey]->subCoursesInternalMark = $subCoursesInternalMark;
                                $semester->history[$singleSubject->historyKey]->subCoursesInternalMaxMark = $subCoursesInternalMaxMark;
                                $semester->history[$singleSubject->historyKey]->subCoursesExternalMark = $subCoursesExternalMark;
                                $semester->history[$singleSubject->historyKey]->subCoursesExternalMaxMark = $subCoursesExternalMaxMark;
                                $semester->history[$singleSubject->historyKey]->subCoursesTotalObtainedMark = $subCoursesTotalObtainedMark;
                                $semester->history[$singleSubject->historyKey]->subCoursesTotalMaxMark = $subCoursesTotalMaxMark;
                                $semester->history[$singleSubject->historyKey]->subCoursesTotalCredit = $subCoursesTotalCredit;
                                $semester->history[$singleSubject->historyKey]->subCoursesIsFailed = $subCoursesIsFailed;
                                $semester->history[$singleSubject->historyKey]->subCoursesGrade = $subCoursesGrade;
                                $semester->history[$singleSubject->historyKey]->subCoursesClassName = $subCoursesClassName;
                                $semester->history[$singleSubject->historyKey]->subCoursesGradePoint = $subCoursesGradePoint;
                                $semester->history[$singleSubject->historyKey]->subCoursesCreditGradePoint = $subCoursesCreditGradePoint;
                                $semester->history[$singleSubject->historyKey]->subCoursesResultStatus = $subCoursesIsFailed == 1 ? 'FAILED' : 'PASSED';
                                $semester->history[$singleSubject->historyKey]->grade = "";
                                $semester->history[$singleSubject->historyKey]->gradePoint = "";
                                $semester->history[$singleSubject->historyKey]->creditGradePoint = "";
                                $semester->history[$singleSubject->historyKey]->class = "";
                            }
                        }
                    }
                    $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[$distinctExam->examRegistrationId]->subjectHistory, $semExtraDetails, $request);
                    $semHistory->withoutRevaluationsgpa = $semHistory->sgpa;
                    $semHistory->withoutRevaluationFailedStatus = $semHistory->isFailed == 1 ? 'FAILED' : 'PASSED' ;
                    $semester->markHistory[] = $semHistory;
                }
                foreach( $distinctRevaluations as $distinctRevaluation ){
                    foreach ($semester->history as $subjectHist ){
                        $subjectHistory = json_decode(json_encode($subjectHist));
                        if ( $distinctRevaluation->examYear."-".date("m", mktime(0, 0, 0, (int)$distinctRevaluation->examMonth, 10)) >= $subjectHistory->examYear."-".date("m", mktime(0, 0, 0, (int)$subjectHistory->examMonth, 10) )){
                            if($subjectHistory->revaluationId == $distinctRevaluation->revaluationId){
                                $subjectHistory->creditGradePoint = $subjectHistory->withoutRevaluationCreditGradePoint;
                                $subjectHistory->isFailed = $subjectHistory->withoutRevaluationIsFailed;
                                $subjectHistory->externalMark = $subjectHistory->withoutRevaluationMark;
                            }
                            if ($semester->examRegistration[$distinctRevaluation->revaluationId]->subjectHistory[$subjectHistory->academicPaperSubjectId]){
                                $currentSubject = $semester->examRegistration[$distinctRevaluation->revaluationId]->subjectHistory[$subjectHistory->academicPaperSubjectId];
                                if ($currentSubject->externalMark < $subjectHistory->externalMark){
                                    $semester->examRegistration[$distinctRevaluation->revaluationId]->subjectHistory[$subjectHistory->academicPaperSubjectId] = $subjectHistory;
                                }
                                if ( $subjectHistory->examMarkType != "REGULAR"){
                                    $regularExamDataFetched = reset($semester->subject[$subjectHistory->academicPaperSubjectId]->markType["REGULAR"]->exam);
                                    if ( $regularExamDataFetched->internalMark != $subjectHistory->internalMark){
                                        $maxInternalObtained = max($regularExamDataFetched->internalMark,$subjectHistory->internalMark);
                                        $internalChangedExamData = json_decode(json_encode($subjectHistory));
                                        $internalChangedExamData->internalMark = $maxInternalObtained;
                                        $internalChangedExamData->externalMark = $subjectHistory->externalMark;
                                        $internalChangedExamData = $this->checkSubjectPassStatus($request, $internalChangedExamData);
                                        $subjectHistory = $this->subjectHistoryProcess($internalChangedExamData, $request);
                                        $semester->examRegistration[$distinctRevaluation->revaluationId]->subjectHistory[$subjectHistory->academicPaperSubjectId] = $subjectHistory;
                                    }
                                }
                            }
                            else{
                                $semester->examRegistration[$distinctRevaluation->revaluationId]->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[$distinctRevaluation->revaluationId]->subjectHistory, $semExtraDetails, $request);
                    foreach( $semester->markHistory as $semCurrentHistory ){
                        if( $semCurrentHistory->examRegistrationId == $distinctRevaluation->parentExamRegistrationId){
                            $semCurrentHistory->withoutRevaluationsgpa = $semHistory->sgpa;
                            $semCurrentHistory->withoutRevaluationFailedStatus = $semHistory->isFailed == 1 ? 'FAILED' : 'PASSED' ;
                            $semCurrentHistory->hasRevaluationMark = 1;
                            $semCurrentHistory->revaluationId = $distinctRevaluation->revaluationId;
                        }
                    }
                    // $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);
            $cgpaGradeSchemeDetails = reset($request->cgpaGradeSchemeArray)->grades;
            if ($studentData->credit) {
                $studentData->cgpa = $studentData->totalSgpaCreditGradePoint / $studentData->totalSgpaCredits;
                // if ($studentData->totalArrears > 0 || $studentData->isFailed ) {
                //     $percentageGrade = $this->getGradeByPercentage(0, $cgpaGradeSchemeDetails);
                // } else {
                $studentData->cgpa = round($studentData->cgpa, 2);
                $percentageGrade = $this->getGradeByPercentage($studentData->cgpa, $cgpaGradeSchemeDetails);
                // }
                if (!empty ($percentageGrade)) {
                    $studentData->grade = $percentageGrade->letterGrade;
                    $studentData->class = $percentageGrade->className;
                }
            }
            $studentData->rawCgpa = $studentData->cgpa;
            $studentData->markDetails = $this->processStudentCourseData($studentData);
            $studentData->status = $studentData->isFailed ? "FAILED" : "PASSED";
            $studentData->supplyAttemptCount = $studentData->markDetails->supplyAttemptCount ? $studentData->markDetails->supplyAttemptCount : 0;
            $studentData->noOfArrears = $studentData->markDetails->arrearCount ? $studentData->markDetails->arrearCount : 0;
        }
        return $studentArray;
    }
    protected function subjectHistoryProcess($subjectData, $request){
        $subjectmarkHistoryObj = new \stdClass();
        $markHistoryType = $subjectData->studentExamRegType;
        $subjectmarkHistoryObj->code = $subjectData->subjectName;
        $subjectmarkHistoryObj->examMarkType = $markHistoryType;
        $subjectmarkHistoryObj->amsSubjectId = $subjectData->amsSubjectId;
        $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->wgpa = $subjectData->wgpa ?? 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((array)$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((array)$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;
            $subjectmarkHistoryObj->hasRevaluationMark = 1;
            $subjectmarkHistoryObj->revaluationId = $revaluationHistory->revaluationId;
            $withoutRevaluationMark = $subjectData->withoutRevaluationMark;
            $subjectmarkHistoryObj->withoutRevaluationMark = $withoutRevaluationMark->mark;
            $subjectmarkHistoryObj->withoutRevaluationGrade = $withoutRevaluationMark->grade;
            $subjectmarkHistoryObj->withoutRevaluationGradePoint = $withoutRevaluationMark->gradePoint;
            $subjectmarkHistoryObj->withoutRevaluationCreditGradePoint = $withoutRevaluationMark->creditGradePoint;
            $subjectmarkHistoryObj->withoutRevaluationIsFailed = $withoutRevaluationMark->isFailed;
        }
        else{
            $subjectmarkHistoryObj->withoutRevaluationMark = $subjectmarkHistoryObj->externalMark;
            $subjectmarkHistoryObj->withoutRevaluationGrade = $subjectmarkHistoryObj->grade;
            $subjectmarkHistoryObj->withoutRevaluationGradePoint = $subjectmarkHistoryObj->gradePoint;
            $subjectmarkHistoryObj->withoutRevaluationCreditGradePoint = $subjectmarkHistoryObj->creditGradePoint;
            $subjectmarkHistoryObj->withoutRevaluationIsFailed = $subjectmarkHistoryObj->isFailed;
        }
        if( !empty((array)$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;
        }
        if( !empty((array)$subjectData->graceMarkHistory) ){
            $graceMarkHistory = $subjectData->graceMarkHistory;
            $subjectmarkHistoryObj->graceMark = $graceMarkHistory->mark;
            $subjectmarkHistoryObj->graceMarkGrade = $graceMarkHistory->grade;
            $subjectmarkHistoryObj->graceMarkGradePoint = $graceMarkHistory->gradePoint;
            $subjectmarkHistoryObj->graceMarkCreditGradePoint = $graceMarkHistory->creditGradePoint;
            $subjectmarkHistoryObj->graceMarkIsFailed = $graceMarkHistory->isFailed;
        }
        if (  $subjectmarkHistoryObj->hasRevaluationMark == 1 ){
        }
        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 ? $subjectData->supplyAttemptCount : 0;
        $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;
        if ($subjectData->hasImprovementChance){
            $subjectMarkDetails->latestExamType = "IMPROVEMENT";
        }
        $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);
        $subjectCourses = [];
        foreach($subjects as $subjectData ){
            if($subjectCourses[$subjectData->parentSubjectId]){
                continue;
            }
            if( !$subjectData->excludeSubjectFromTotal ){
                if($subjectData->examRegistrationId == $semExtraDetails->examRegistrationId && $subjectData->parentSubjectId){
                    $subjectCourses[$subjectData->parentSubjectId] = $subjectData->parentSubjectId;
                    $semObject->credit += $subjectData->subCoursesTotalCredit;
                    $semObject->creditGradePoint += $subjectData->subCoursesCreditGradePoint;
                    //exclude subject fail status is not considered for semester 
                    if ( $subjectData->subCoursesIsFailed ){
                        $semObject->arrears++;
                    }
                }
                else{
                    $semObject->credit += $subjectData->credit;
                    $semObject->creditGradePoint += $subjectData->creditGradePoint;
                    //exclude subject fail status is not considered for semester 
                    if ( $subjectData->isFailed ){
                        $semObject->arrears++;
                    }
                }
            }
            if ($subjectData->isPG == 0 && (
                $subjectData->subjectType == ExamSubjectTypeConstants::FOUNDATION_COURSE ||
                $subjectData->subjectType == ExamSubjectTypeConstants::OPEN_ELECTIVE ||
                $subjectData->subjectType == ExamSubjectTypeConstants::TERM_PAPER)) {
            continue;
            } else if ( $subjectData->excludeSubjectFromTotal == 1) {
                continue;
            } else if ($subjectData->isPG == 1 && (
                $subjectData->subjectType == ExamSubjectTypeConstants::OPEN_ELECTIVE ||
                $subjectData->subjectType == ExamSubjectTypeConstants::IGNITORS )) {
                continue;
            }
            if($subjectData->examRegistrationId == $semExtraDetails->examRegistrationId && $subjectData->parentSubjectId){
                $semObject->totalMarks += $subjectData->subCoursesTotalObtainedMark;
                $semObject->examTotalMarks += $subjectData->subCoursesTotalMaxMark;
            }
            else{
                $semObject->totalMarks += $subjectData->markObtained;
                $semObject->examTotalMarks += $subjectData->totalMark;
            }
        }
        $semesterGradeDetails = $request->semesterGradeSchemeArray[$semExtraDetails->academicTermId]->grades;
        if ( $semObject->arrears ) {
            $semObject->sgpa = "0"; // Please don't update "-"
            $semMarkGrade = $this->getGradeByPercentage(0, $semesterGradeDetails);
            $semObject->sgpa = $semObject->credit ? round($semObject->creditGradePoint / $semObject->credit, 2) : 0;
            $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 < 50 ) {
            //      // $studentObj->isFailed = true;
            //      $semObject->isFailed = true;
            //  }
             /** codeEnds **/
             $semObject->sgpa = $semObject->credit ? round($semObject->creditGradePoint / $semObject->credit, 2) : 0;
            if ( !$semObject->isFailed ) {
                $semMarkGrade = $this->getGradeByPercentage( $semObject->sgpa, $semesterGradeDetails);
            }
            else{
                $semMarkGrade = $this->getGradeByPercentage(0, $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)
    {
        $gradeDetails =  $request->subjectGradeSchemeArray[$subject->academicPaperSubjectId]->grades;
        $maxGradePercent = $gradeDetails[0]->rangeTo;
        $maxGradePoint = max(array_column($gradeDetails,"gradePoint"));
        $checkPassPercentCriteria = new \stdClass(); 
        $checkPassPercentCriteria->isInternal = $subject->isInternal;
        $checkPassPercentCriteria->internalMaxMark = $subject->internalMaxMark;
        
        $checkPassPercentCriteria->isExternal = $subject->isExternal;
        $checkPassPercentCriteria->externalMaxMark = $subject->externalMaxMark;
        $checkPassPercentCriteria->internalMark = $subject->internalMark;
        $checkPassPercentCriteria->courseType = $subject->courseType;
        $checkPassPercentCriteria->maxGradePercent = $maxGradePercent;
        // $checkPassPercentCriteria->considerOverallPassCriteriaOnly = $considerOverallPassCriteriaOnly;
        $checkPassPercentCriteria->passPercentConfig = $request->passCriteriaArray[$subject->academicPaperSubjectId];
        $overallPassCriteria = $request->passCriteriaArray[$subject->academicPaperSubjectId]->overallPassCriteria;
        $checkPassPercentCriteria->externalMark = $markHistory->mark;
        $isFailedForTheSubject = $this->checkIsFailedByPassPercentCriteria ( $checkPassPercentCriteria );
        if ( $isFailedForTheSubject ) {
            $percentageObtained = 0;
            // $semesterGradePercentObtained = 0;
        }
        else {
            $percentageObtained = $maxGradePercent * ($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);
        $x = 1;
        if ($subject->courseType == "PG") {
            $subject->externalMaxMark = $subject->externalMaxMark? $subject->externalMaxMark : 0;
            $internalMarkPer = $externalMarkPer = 0;
            $x = 1;
            // $isFailed = 0;
            // $studentExternalMark = round($studentExternalMark);
            if ($subject->isInternal) {
                $internalMarkPer = round($maxGradePercent * $subject->internalMark / $subject->internalMaxMark, 2); 
                // $internalGrade = $this->getGradeByPercentage($internalMarkPer, $gradeDetails);
            }
            if ($subject->isExternal) {
                $externalMarkPer = round($maxGradePercent * $markHistory->mark / $subject->externalMaxMark, 2); 
                // $externalGrade = $this->getGradeByPercentage($externalMarkPer, $gradeDetails);
            }
            if ($subject->isInternal && $subject->isExternal) {
                $gradePoint = round(( $internalMarkPer + ( 3 * $externalMarkPer ) ) / 4, 2);
            }
            else {
                $gradePoint = $internalMarkPer + $externalMarkPer;
            }
            $overallPercentPG = 100 * $gradePoint / $maxGradePercent ?? 0;
            if (!empty ($overallPassCriteria)) {
                $isFailedForTheSubject = $overallPassCriteria <= $overallPercentPG ? $isFailedForTheSubject : 1;
            }
            if ($isFailedForTheSubject) {
                $gradePoint = 0;
            }
            $grade = $this->getGradeByPercentage($gradePoint, $gradeDetails);
            $grade = json_decode(json_encode($grade));
            $grade->gradePoint = $gradePoint;
        }
        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($semester->subject,"finalConsolidated"),"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->arrears;
        $semMarkDetails->supplyAttemptCount = $semester->supplyAttemptCount ? $semester->supplyAttemptCount : 0;
        $semMarkDetails->sgpa = $semester->sgpa;
        $semMarkDetails->rawSgpa = $semester->rawSgpa;
        $semMarkDetails->semesterCgpa = $semester->semesterCgpa;
        // $semMarkDetails->wgpa = $semester->consolidated->wgpa ?? 0;
        $semMarkDetails->status = $semester->isFailed ? "FAILED" : "PASSED";
        // $semMarkDetails->resultStatus = $semester->isFailed ? "FAILED" : "PASSED";
        $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($student->semester,"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 = array_sum(array_column(array_column($student->semester,"markDetails"),"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 = $checkPassPercentCriteria->courseType == "PG" ? round($checkPassPercentCriteria->internalMark, 2) : 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 += $checkPassPercentCriteria->courseType == "PG" && ( round($checkPassPercentCriteria->externalMaxMark, 2) == round( $checkPassPercentCriteria->maxGradePercent, 2))? round($checkPassPercentCriteria->externalMark, 2) : 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;
    }   
}