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 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 593
ModerationModuleService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 8
7832.00
0.00% covered (danger)
0.00%
0 / 593
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 2
 getSubjectsForModerationMark
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 58
 getSubjectsForModerationModule
0.00% covered (danger)
0.00%
0 / 1
156.00
0.00% covered (danger)
0.00%
0 / 112
 getModerationReport
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 48
 getModerationAppliedStudentDetails
0.00% covered (danger)
0.00%
0 / 1
182.00
0.00% covered (danger)
0.00%
0 / 138
 getModerationStatisticalAnalysisReport
0.00% covered (danger)
0.00%
0 / 1
756.00
0.00% covered (danger)
0.00%
0 / 165
 getGradeByPercentage
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 8
 getBatchStudentForModerationMark
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 62
<?php
namespace com\linways\ec\core\service;
use com\linways\ec\core\dto\FalseNumberSetting;
use com\linways\ec\core\dto\FalseNumberSettingExamLog;
use com\linways\base\util\MakeSingletonTrait;
use com\linways\base\util\SecurityUtils;
use com\linways\ec\core\constant\StatusConstants;
use com\linways\ec\core\exception\ExamControllerException;
use com\linways\ec\core\mapper\ModerationModuleServiceMapper;
use com\linways\ec\core\service\CommonExamService;
use com\linways\ec\core\request\SearchExamRegistrationRequest;
use com\linways\ec\core\service\ExamRegistrationService;
use com\linways\base\util\TwigRenderer;
use com\linways\core\ams\professional\util\PdfUtil;
use com\linways\core\ams\professional\service\CommonService;
use com\linways\core\ams\professional\dto\SettingsConstents;
use com\linways\ec\core\service\GroupService as ECGroupService;
use com\linways\core\ams\professional\request\academic\SearchGroupRequest;
use com\linways\core\ams\professional\service\StudentService;
use com\linways\ec\core\request\SearchRuleRequest;
use com\linways\ec\core\service\RuleService;
class ModerationModuleService extends BaseService
{
    use MakeSingletonTrait;
    private function __construct() {
        $this->mapper = ModerationModuleServiceMapper::getInstance()->getMapper();
    }
     /**
     * get Subjects For Moderation Mark
     * @param $searchRequest
     * @return $moderationDetails
     */
    public function getSubjectsForModerationMark($searchRequest){
        try{
            if((empty($searchRequest->registerNo) && empty($searchRequest->rollNo )) || empty($searchRequest->examRegistrationId )){
                throw new ExamControllerException (ExamControllerException::INVALID_PARAMETERS,"Register Number Or Registration Missing!");
            }
            $moderationDetails = reset($this->getSubjectsForModerationModule($searchRequest));
            if(empty($moderationDetails)){
                throw new ExamControllerException (ExamControllerException::INVAILED_REGISTER_NUMBER,"Invailed Register Number Entered!");
            }
            else{
                $moderationDetails->studentImage  = StudentService::getInstance()->getStudentProfilePic($moderationDetails->studentId)->docpath;
                $searchRuleRequest = new SearchRuleRequest;
                $searchRuleRequest->name = "EXAM_MODERATION_RULE";
                $moderationRule = reset(RuleService::getInstance()->searchRule($searchRuleRequest))->rule;
                $isShowFailedSubjectOnlyInMarkEntry = $moderationRule->isShowFailedSubjectOnlyInMarkEntry == 1 ? true : false;
                if($isShowFailedSubjectOnlyInMarkEntry){
                    $studentSubjects = [];
                    $failedSubjects = [];
                    $studentSubjects = $moderationDetails->subjects;
                    foreach($studentSubjects as $subject){
                        $searchRequestForGradeScheme = new \stdClass();
                        $searchRequestForGradeScheme->groupId = $moderationDetails->groupId;
                        $searchRequestForGradeScheme->academicTermId = $moderationDetails->academicTermId;
                        $searchRequestForGradeScheme->academicPaperSubjectId = $subject->id;
                        $subjectGradeSchemeArray = GradeSchemeService::getInstance()->getAllSubjectGradeSchemesByRequest($searchRequestForGradeScheme);
                        $subjectGradeKey = array_search($subject->id, array_column( $subjectGradeSchemeArray, "id"));
                        $gradeDetails = [];
                        if($subjectGradeKey || $subjectGradeKey === 0){
                            $gradeDetails = $subjectGradeSchemeArray[$subjectGradeKey]->grades;
                        }
                        $maxGradePercent =  max(array_column($gradeDetails,"rangeTo"));
                        $schemeType = "PERCENTAGE";
                        $passCriteriaArray[$subject->id] = GradeSchemeService::getInstance()->getSubjectPassCriteriaByAcademicPaperSubject($subject->id, $schemeType);
                        $checkPassPercentCriteria = new \stdClass();
                        $checkPassPercentCriteria->courseTypeMethod = $moderationDetails->courseTypeMethod;
                        $checkPassPercentCriteria->schemeType = $subjectGradeSchemeArray[$subjectGradeKey]->schemeType ? $subjectGradeSchemeArray[$subjectGradeKey]->schemeType : "PERCENTAGE";
                        $checkPassPercentCriteria->isInternal = $subject->isInternal;
                        $checkPassPercentCriteria->internalMaxMark = $subject->internalMaxMark;
                        $checkPassPercentCriteria->isExternal = $subject->isExternal;
                        $checkPassPercentCriteria->externalMaxMark = $subject->externalMaxMark;
                        $checkPassPercentCriteria->internalMark = round($subject->internalMark, 2 );
                        $checkPassPercentCriteria->passPercentConfig = $passCriteriaArray[$subject->id];
                        $checkPassPercentCriteria->externalMark = round ( $subject->externalMark, 2 );
                        $checkPassPercentCriteria->maxGradePercent = $maxGradePercent;
                        $checkPassPercentCriteria->gradeDetails = $gradeDetails;
                        $subjectPassCriteria = CommonExamService::getInstance()->checkIsFailedByPassPercentCreditCriteria ( $checkPassPercentCriteria );
                        if($subjectPassCriteria->failedStatus =='FAILED'){
                            $failedSubjects[] = $subject;
                        }
                    }
                    $moderationDetails->subjects = $failedSubjects;
                }
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $moderationDetails;
    }
    /**
     * get All Subjects By ExamRegistrationId And RegisterNo
     * @param $academicTermIds
     * @param $studentRegisterNo
     * @return $subjects
     */
    public function getSubjectsForModerationModule($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
       
        try{
            $whereQuery = null;
            $orderBy = " ORDER BY s.code ASC ";
            $whereQuery = "";
            if(!empty($searchRequest->registerNo)) {
                $registerNoString = is_array($searchRequest->registerNo) ? "'" . implode("','",$searchRequest->registerNo) . "'" : "'".$searchRequest->registerNo."'";
                $whereQuery .= " AND spa.properties->>'$.registerNumber' IN ( $registerNoString )";
            }
            if(!empty($searchRequest->rollNo)) {
                $rollNoString = is_array($searchRequest->rollNo) ? "'" . implode("','",$searchRequest->rollNo) . "'" : "'".$searchRequest->rollNo."'";
                $whereQuery .= " AND spa.properties->>'$.rollNumber' IN ( $rollNoString )";
            }
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->examRegistrationId)) {
                $examRegistrationIdString = is_array($searchRequest->examRegistrationId) ? "'" . implode("','",$searchRequest->examRegistrationId) . "'" : "'".$searchRequest->examRegistrationId."'";
                $whereQuery .= " AND eerb.ec_exam_registration_id IN ( $examRegistrationIdString )";
            }
            if(!empty($searchRequest->subjectCode)) {
                $whereQuery .= " AND s.code LIKE '%$searchRequest->subjectCode%'";
            }
            if(!empty($searchRequest->considerOnlyExternalPapers)){
                $whereQuery .= " AND aps.properties ->> '$.isExternal' = 1";
            }
            $query = "SELECT
                            DISTINCT  esar.am_assessment_id as id,
                            esar.am_assessment_id as assessmentId,
                            sa.studentID AS studentAccId,
                            sa.studentName,
                            ct.course_Type AS courseTypeMethod,
                            g.name AS groupName,
                            g.id AS groupId,
                            s.code as subjectCode,
                            s.name as subjectName,
                            IF(aps.properties ->> '$.classType' = 'THEORY',1,0) AS isTheory,
                            spa.properties->>'$.registerNumber' as regNo,
                            spa.properties->>'$.rollNumber' as rollNo,
                            aps.id as academicPaperSubjectId,
                            im.internal_mark as internalMark,
                            ostm.mark_obtained  as obtainedExternal,
                            IF( IF(ostm.mark_obtained IS NULL, 0 , ostm.mark_obtained) >  IF(ostm2.mark_obtained IS NULL, 0 , ostm2.mark_obtained), ostm.mark_obtained, ostm2.mark_obtained) + IF(ostm4.mark_obtained IS NULL, 0 , ostm4.mark_obtained)  as externalMark,
                            ostm.attendance_status as isAbsent,
                            ostm2.mark_obtained  as revaluationMark,
                            ostm3.mark_obtained  as moderationMark,
                            ostm3.mark_obtained  as hasModerationMark,
                            ostm3.properties as moderationMarkproperties,
                            ostm3.properties ->> '$.moderationMarkRemarks'  as moderationMarkRemarks,
                            ostm4.mark_obtained  as graceMark,
                            act.id AS academicTermId,
                            act.name AS academicTermName,
                            oe.id AS oeExamId,
                            aps.properties ->> '$.isInternal' as isInternal,
                            aps.properties ->> '$.isExternal' as isExternal,
                            aps.properties ->> '$.externalMaxMark' as externalMaxMark,
                            aps.properties ->> '$.internalMaxMark' as internalMaxMark,
                            aps.properties ->> '$.externalMaxMark' + aps.properties ->> '$.internalMaxMark' as totalMaxMark,
                            ostm.mark_obtained + im.internal_mark as totalObtainedMark
                        FROM
                            ec_student_assessment_registration esar
                        INNER JOIN studentaccount sa ON 
                            sa.studentID = esar.student_id
                        INNER JOIN student_program_account spa
                            ON spa.student_id = sa.studentID
                        INNER JOIN ec_exam_registration_subject eers ON 
                            eers.am_assessment_id = esar.am_assessment_id
                        INNER JOIN  cm_academic_paper_subjects aps ON 
                            aps.id = eers.cm_academic_paper_subjects_id
                        INNER JOIN v4_ams_subject s ON 
                            s.id = aps.ams_subject_id
                        INNER JOIN ec_exam_registration_batch eerb ON
                            eerb.id = eers.ec_exam_registration_batch_id
                        INNER JOIN ec_exam_registration eer ON
                            eer.id = eerb.ec_exam_registration_id AND eer.type = esar.ec_exam_registration_type
                        INNER JOIN `groups` g ON
                            g.id = eerb.groups_id
                        INNER JOIN program p ON 
                            p.id = g.properties->>'$.programId'
                        INNER JOIN `course_type` ct ON
                            ct.courseTypeID = p.course_type_id
                        INNER JOIN cm_academic_paper ap ON 
                            aps.cm_academic_paper_id = ap.id
                        INNER JOIN  academic_term act ON 
                            act.id = CAST(eerb.properties ->> '$.academicTermId'AS CHAR) 
                        INNER JOIN cm_syllabus_academic_term_settings str ON 
                            str.id = ap.cm_syllabus_academic_term_settings_id 
                        INNER JOIN oe_exams oe ON
                            oe.assessment_id = eers.am_assessment_id AND oe.is_deleted = 0
                        LEFT JOIN ec_internal_marks im ON
                            im.groups_id = eerb.groups_id AND 
                            im.academic_paper_subjects_id = aps.id AND 
                            im.academic_term_id = str.academic_term_id AND im.student_id = sa.studentID
                        LEFT JOIN oe_student_total_mark ostm ON 
                            ostm.student_id = sa.studentID AND ostm.am_assessment_id = esar.am_assessment_id AND (ostm.valuation_type IS NULL OR ostm.valuation_type = '') AND ostm.valuation_count = 'FINALIZED'
                        LEFT JOIN oe_student_total_mark ostm2 ON 
                            ostm2.student_id = sa.studentID AND ostm2.am_assessment_id = esar.am_assessment_id AND ostm2.valuation_type = 'REVALUATION'
                        LEFT JOIN oe_student_total_mark ostm3 ON 
                            ostm3.student_id = sa.studentID AND ostm3.am_assessment_id = esar.am_assessment_id AND ostm3.valuation_type = 'MODERATION'
                        LEFT JOIN oe_student_total_mark ostm4 ON 
                            ostm4.student_id = sa.studentID AND ostm4.am_assessment_id = esar.am_assessment_id AND ostm4.valuation_type = 'GRACEMARK'
                        WHERE
                            1 = 1 AND esar.properties ->> '$.registrationStatus' = 'REGISTERED' ";
                $subjects =  $this->executeQueryForList($query.$whereQuery.$orderBy, $this->mapper[ModerationModuleServiceMapper::GET_STUDENT_SUBJECT_DETAILS]);
        }
        catch (\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $subjects;
    }
    /**
     * Get Moderation Report
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getModerationReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $request = new \stdClass;
        $request->examRegistrationId = $searchRequest->examRegistrationId;
        $request->courseTypeId = $searchRequest->courseTypeId;
        $request->subjectId = $searchRequest->subjectId;
        $request->reportType = $searchRequest->reportType;
        $additionalInfo = new \stdClass;
        $resultData = new \stdClass;
        $templateName = "moderation-report-template-1";
        if(empty($request->examRegistrationId)){
            throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request");
        }
        $resultData =  $this->getModerationAppliedStudentDetails($request);
        $requestForExamRegistration = new SearchExamRegistrationRequest;
        $requestForExamRegistration->id = $request->examRegistrationId;
        $examRegistration = reset(ExamRegistrationService::getInstance()->searchExamRegistration($requestForExamRegistration));
        $collegeData = CommonExamService::getInstance()->getCollegeDetails();
        if(empty($resultData)){
            throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No details found.");
        }
        if( $searchRequest->reportType == 'SUBJECT_WISE'){
            $templateName = "moderation-report-subject-wise-template-1";
        }
        $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/moderationReport/$templateName.twig"), [ 'moderationBatches'=>$resultData,'college'=>$collegeData,'examRegistration'=>$examRegistration]);
        $prtContent = NULL;
            $prtContent .= '<html><head>';
            $prtContent .= "<style>
                </style>";
            $prtContent .= '</head><title>Moderation Report</title><body>';
            $prtContent .= $responseHtml;
            $prtContent .= '</body></html>';
            $totalWidth = 297;
            $totalHeight = 210;
            $options = array(
                'page-width'     => $totalWidth."mm",
                'page-height'    => $totalHeight."mm",
                'dpi'            => 96,
                'margin-top' => "9mm",
                'margin-left' => "1mm",
                'margin-right' => "1mm",
                'margin-bottom' => "9mm",
                // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
            );
        $programResult = new \stdClass;
        $programResult->dispalyHtmlData = $responseHtml;
        $programResult->printData = PdfUtil::renderPdf($prtContent, $options);
        return  $programResult;
    }
      /**
     * Moderation Applied Student Details
     * @param $academicTermIds
     * @param $studentRegisterNo
     * @return $response
     */
    public function getModerationAppliedStudentDetails($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $whereQuery = null;
            $orderBy = " ORDER BY g.name ASC, CAST(spa.properties->>'$.registerNumber' AS CHAR) ASC, s.code ASC";
            $whereQuery = "";
            if(!empty($searchRequest->examRegistrationId)) {
                $examRegistrationIdString = is_array($searchRequest->examRegistrationId) ? "'" . implode("','",$searchRequest->examRegistrationId) . "'" : "'".$searchRequest->examRegistrationId."'";
                $whereQuery .= " AND eerb.ec_exam_registration_id IN ( $examRegistrationIdString )";
            }
            if(!empty($searchRequest->academicPaperSubjectId)) {
                $academicPaperSubjectIdString = is_array($searchRequest->academicPaperSubjectId) ? "'" . implode("','",$searchRequest->academicPaperSubjectId) . "'" : "'".$searchRequest->academicPaperSubjectId."'";
                $whereQuery .= " AND aps.id IN ( $academicPaperSubjectIdString )";
            }
            if(!empty($searchRequest->subjectId)) {
                $subjectIdString = is_array($searchRequest->subjectId) ? "'" . implode("','",$searchRequest->subjectId) . "'" : "'".$searchRequest->subjectId."'";
                $whereQuery .= " AND s.id IN ( $subjectIdString )";
            }
            $query = "SELECT
                    DISTINCT  esar.am_assessment_id as id,
                    esar.am_assessment_id as assessmentId,
                    sa.studentID AS studentAccId,
                    spa.properties->>'$.registerNumber' AS studentRegisterNo,
                    sa.studentName,
                    g.name AS groupName,
                    g.id AS groupId,
                    s.code as subjectCode,
                    s.name as subjectName,
                    IF(aps.properties ->> '$.classType' = 'THEORY',1,0) AS isTheory,
                    sa.regNo,
                    aps.id as academicPaperSubjectId,
                    esmdsubcon.mark_details ->>'$.internalMark' AS internalMark,
                    -- im.internal_mark as internalMark,
                    ostm.mark_obtained  as obtainedExternal,
                    ostm.attendance_status as isAbsent,
                    ostm3.mark_obtained  as moderationMark,
                    ostm3.mark_obtained  as hasModerationMark,
                    ostm3.properties as moderationMarkproperties,
                    ostm3.properties ->> '$.moderationMarkRemarks'  as moderationMarkRemarks,
                    act.id AS academicTermId,
                    act.name AS academicTermName,
                    oe.id AS oeExamId,
                    aps.properties ->> '$.isInternal' as isInternal,
                    aps.properties ->> '$.isExternal' as isExternal,
                    aps.properties ->> '$.externalMaxMark' as externalMaxMark,
                    aps.properties ->> '$.internalMaxMark' as internalMaxMark,
                    aps.properties ->> '$.externalMaxMark' + aps.properties ->> '$.internalMaxMark' as totalMaxMark,
                    ostm.mark_obtained + esmdsubcon.mark_details ->>'$.internalMark' as totalObtainedMark
                FROM
                    ec_student_assessment_registration esar
                INNER JOIN studentaccount sa ON 
                    sa.studentID = esar.student_id
                INNER JOIN ec_exam_registration_subject eers ON 
                    eers.am_assessment_id = esar.am_assessment_id
                INNER JOIN  cm_academic_paper_subjects aps ON 
                    aps.id = eers.cm_academic_paper_subjects_id
                INNER JOIN v4_ams_subject s ON 
                    s.id = aps.ams_subject_id
                INNER JOIN ec_exam_registration_batch eerb ON
                    eerb.id = eers.ec_exam_registration_batch_id
                INNER JOIN ec_exam_registration eer ON
                    eer.id = eerb.ec_exam_registration_id AND eer.type = esar.ec_exam_registration_type
                    AND eer.trashed IS NULL
                INNER JOIN `groups` g ON
                    g.id = eerb.groups_id
                INNER JOIN program p ON 
                    p.id = g.properties->>'$.programId'
                INNER JOIN student_program_account spa ON 
                    spa.student_id  = esar.student_id  AND
                    spa.current_program_id = p.id AND 
                    spa.properties->>'$.academicStatus' IN ('ACTIVE','COMPLETED')
                INNER JOIN cm_academic_paper ap ON 
                    aps.cm_academic_paper_id = ap.id
                INNER JOIN  academic_term act ON 
                    act.id = CAST(eerb.properties ->> '$.academicTermId'AS CHAR) 
                INNER JOIN cm_syllabus_academic_term_settings str ON 
                    str.id = ap.cm_syllabus_academic_term_settings_id 
                INNER JOIN oe_exams oe ON
                    oe.assessment_id = eers.am_assessment_id AND oe.is_deleted = 0
                -- LEFT JOIN ec_internal_marks im ON
                --     im.groups_id = eerb.groups_id AND 
                --     im.academic_paper_subjects_id = aps.id AND 
                --     im.academic_term_id = str.academic_term_id AND im.student_id = sa.studentID
                INNER JOIN oe_student_total_mark ostm3 ON 
                    ostm3.student_id = sa.studentID AND ostm3.am_assessment_id = esar.am_assessment_id AND ostm3.valuation_type = 'MODERATION'
                LEFT JOIN oe_student_total_mark ostm ON 
                    ostm.student_id = sa.studentID AND ostm.am_assessment_id = esar.am_assessment_id AND (ostm.valuation_type IS NULL OR ostm.valuation_type = '') AND ostm.valuation_count = 'FINALIZED'
                INNER JOIN ec_consolidated_subject_mark_details esmdsubcon ON
                    esmdsubcon.groups_id = eerb.groups_id AND esmdsubcon.cm_academic_paper_subjects_id = eers.cm_academic_paper_subjects_id AND esmdsubcon.student_id = sa.studentID 
                
                WHERE
                    1 = 1 ";
            $modeationStudents =  $this->executeQueryForList($query.$whereQuery.$orderBy);
            $response = "";
            if($searchRequest->reportType == "SUBJECT_WISE"){
                $modeationSubjects = [];
                foreach($modeationStudents as $student){
                    $modeationSubjects[$student->subjectCode]->id = $student->subjectCode;
                    $modeationSubjects[$student->subjectCode]->name = $student->subjectName." (".$student->subjectCode.")";
                    $modeationSubjects[$student->subjectCode]->isInternal = $student->isInternal;
                    $modeationSubjects[$student->subjectCode]->isExternal = $student->isExternal;
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->id = $student->studentAccId;
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->name = $student->studentName;
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->regNo = $student->studentRegisterNo;
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->internalMark = $student->isInternal ? ceil($student->internalMark) : 0;
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->obtainedExternal = ceil($student->obtainedExternal);
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->moderationMark = $student->moderationMark;
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->externalMarkAfterModeration = (int)ceil($student->obtainedExternal) + (int)$student->moderationMark;
                    $modeationSubjects[$student->subjectCode]->students[$student->studentAccId]->totalMarkAfterModeration = (int)ceil($student->obtainedExternal) + (int)$student->moderationMark + (int)ceil($student->internalMark);
                }
                $response = $modeationSubjects;
            }
            else{
                $modeationBatches = [];
                foreach($modeationStudents as $student){
                    $modeationBatches[$student->groupId]->id = $student->groupId;
                    $modeationBatches[$student->groupId]->name = $student->groupName;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->id = $student->studentAccId;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->name = $student->studentName;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->regNo = $student->studentRegisterNo;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->id = $student->assessmentId;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->code = $student->subjectCode;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->name = $student->subjectName;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->isInternal = $student->isInternal;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->isInternal = $student->isInternal;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->isExternal = $student->isExternal;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->internalMark = $student->isInternal ? ceil($student->internalMark) : 0;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->obtainedExternal = ceil($student->obtainedExternal);
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->moderationMark = $student->moderationMark;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->externalMarkAfterModeration = (int)ceil($student->obtainedExternal) + (int)$student->moderationMark;
                    $modeationBatches[$student->groupId]->students[$student->studentAccId]->subjects[$student->assessmentId]->totalMarkAfterModeration = (int)ceil($student->obtainedExternal) + (int)$student->moderationMark + (int)ceil($student->internalMark);
                }
                $response = $modeationBatches;
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $response;
    }
        /**
     * Get Moderation Statistical Analysis Report
     * @param $searchRequest 
     * @return $programResult 
     */
    public function getModerationStatisticalAnalysisReport($searchRequest) {
        $searchRequest = $this->realEscapeObject($searchRequest);
        $request = new \stdClass;
        $request->examRegistrationId = $searchRequest->examRegistrationId;
        $request->groupId = $searchRequest->groupId;
        $moderationMarkArr = (array) $searchRequest->moderationMark;
        $request->courseTypeId = $searchRequest->courseTypeId;
        $additionalInfo = new \stdClass;
        $college = new \stdClass;
        $resultData = new \stdClass;
        $templateName = "moderation-statistical-analysis";
        if(empty($request->examRegistrationId)){
            throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request");
        }
        ksort($moderationMarkArr);
        $keyIndex = reset($moderationMarkArr);
        $subjectList=[];
        $studentFailedList=[];
        $semesterPercentage=[];
        $studentsMarkList = StudentMarkListService::getInstance()->getAllRegistredStudentMarkDetailsDummyData($request);
        if (!empty($studentsMarkList)) {
            foreach($moderationMarkArr as $moderationMark){
                $studentsMarkDetails = json_decode(json_encode($studentsMarkList));
                foreach($studentsMarkDetails as $key => $student){
                    $studentId = $student->id;
                    $academicTerm = reset(array_filter(reset($student->academicTerms)->markHistory,function($value)use($request){
                        return $value->examRegistrationId == $request->examRegistrationId;
                    }));
                    $failedSubject = array_filter($student->academicTerms[0]->subjects,function($value){
                        return $value->isFailed == "FAILED";
                    });
                    $student->failedStatus = $academicTerm->failedStatus;
                    $student->arrearCount = count($failedSubject) ;
                    $academicTermId = $student->academicTerms[0]->id;
                    if( $moderationMark != 0 ){ 
                        $student->failedStatus = "PASSED";
                    }
                    foreach($student->academicTerms[0]->subjects  as $subject){
                        if( $moderationMark != 0 && $subject->isFailed != "PASSED"){
                            $schemeType = "PERCENTAGE";
                            $passCriteriaArray[$subject->id] = GradeSchemeService::getInstance()->getSubjectPassCriteriaByAcademicPaperSubject($subject->id, $schemeType);
                            $checkPassPercentCriteria = new \stdClass();
                            $checkPassPercentCriteria->isInternal = $subject->isInternal;
                            $checkPassPercentCriteria->internalMaxMark = $subject->internalMaxMark;
                            $checkPassPercentCriteria->isExternal = $subject->isExternal;
                            $checkPassPercentCriteria->externalMaxMark = $subject->externalMaxMark;
                            $checkPassPercentCriteria->internalMark = round($subject->internalMark, 2 );
                            $checkPassPercentCriteria->passPercentConfig = $passCriteriaArray[$subject->id];
                            $checkPassPercentCriteria->externalMark = $subject->externalMark + $moderationMark;
                            $subjectPassCriteria = CommonExamService::getInstance()->checkIsFailedByPassPercentCriteria ( $checkPassPercentCriteria );
                            $searchRequest = new \stdClass();
                            $searchRequest->groupId =  $request->groupId;
                            $searchRequest->academicTermId = $academicTermId;
                            $searchRequest->academicPaperSubjectId =current($subjectList)->subject->id;
                            $subjectGradeSchemeArray = GradeSchemeService::getInstance()->getAllSubjectGradeSchemesByRequest($searchRequest);
                            $gradeDetails = reset($subjectGradeSchemeArray)->grades;
                            $maxGradePercent = $gradeDetails[0]->rangeTo;
                            if ( $subjectPassCriteria->failedStatus == "FAILED"  ) {
                                $percentageObtained = 0;
                            }
                            else {
                                $percentageObtained = $maxGradePercent * ( $checkPassPercentCriteria->externalMark + $checkPassPercentCriteria->internalMark) / (($subject->externalMaxMark + $subject->internalMaxMark));
                                $percentageObtained = round($percentageObtained, 2);
                            }
                            $grade = $this->getGradeByPercentage($percentageObtained, $gradeDetails);
                            if (!empty ($grade)) {
                                if ($grade->failStatus == 1) {
                                    $subjectPassCriteria->failedStatus = "FAILED";
                                }
                            }
                            if( $subjectPassCriteria->failedStatus == "FAILED" &&  $subject->isFailed != "PASSED"){
                                $student->failedStatus = "FAILED";
                            }
                            $subject->isFailed = $subject->isFailed != "PASSED" ? $subjectPassCriteria->failedStatus : $subject->isFailed;
                            $subject->grade = $grade->letterGrade;
                            
                        }
                        if( $moderationMark == $keyIndex ){
                            $subjectList[$subject->id]->appeared++;
                            $subjectList[$subject->id]->subject = $subject;
                            if( $student->failedStatus == "FAILED" &&  $student->arrearCount == 1){
                                if ($subject->isFailed == "FAILED") {
                                    $subjectList[$subject->id]->subjectFailCnt++;
                                    $studentFailedList[$studentId]->subject[$subject->id]->isFailed = 1;
                                }
                            }
                        }
                        if ( $subject->isFailed == "FAILED" ) {
                            $subjectList[$subject->id]->totalFailCount++;
                        }
                        else{
                            $subjectList[$subject->id]->chance[$moderationMark]->passCount++;
                            
                        } 
                        $subjectList[$subject->id]->chance[$moderationMark]->percentage = round(($subjectList[$subject->id]->chance[$moderationMark]->passCount / $subjectList[$subject->id]->appeared) *100 , 2);
                        if($moderationMark != 0){
                            if( $semesterPercentage[$keyIndex]->percentage !=  $semesterPercentage[$moderationMark]->percentage){
                                $semesterPercentage[$moderationMark]->hasChange = 1;
                            }
                            $subjectList[$subject->id]->chance[$moderationMark]->hasChange = 0;
                            if($subjectList[$subject->id]->chance[$keyIndex]->percentage != $subjectList[$subject->id]->chance[$moderationMark]->percentage){
                                $subjectList[$subject->id]->chance[$moderationMark]->hasChange = 1;
                            }
                        }
                        $subjectList[$subject->id]->chance[$moderationMark]->grades[$subject->grade]++;
                    }
                    $semesterPercentage[$moderationMark]->totalCount++;
                    if( $student->failedStatus != "FAILED" ){
                        $semesterPercentage[$moderationMark]->passCount++;
                    }
                    $semesterPercentage[$moderationMark]->percentage = round(($semesterPercentage[$moderationMark]->passCount / $semesterPercentage[$moderationMark]->totalCount) *100 , 2);
                    $semesterPercentage[$moderationMark]->hasChange = 0;
                    if($moderationMark != $keyIndex){
                        if( $semesterPercentage[$keyIndex]->percentage !=  $semesterPercentage[$moderationMark]->percentage){
                            $semesterPercentage[$moderationMark]->hasChange = 1;
                        }
                    }
                }
            } 
        } 
        $requestForExamRegistration = new SearchExamRegistrationRequest;
        $requestForExamRegistration->id = $request->examRegistrationId;
        $examRegistration = reset(ExamRegistrationService::getInstance()->searchExamRegistration($requestForExamRegistration));
        if(empty($studentsMarkList)){
            throw new ExamControllerException(ExamControllerException::NO_REPORTS_DETAILS_FOUND,"No details found.");
        }
        $searchGroupRequest = new SearchGroupRequest;
        $searchGroupRequest->id = $request->groupId;
        $searchGroupRequest->type = "BATCH";
        $batch = reset(ECGroupService::getInstance()->searchGroupByRequest($searchGroupRequest));
        $searchRequest = new \stdClass();
        $searchRequest->groupId =  $request->groupId;
        $searchRequest->academicTermId = $academicTermId;
        $searchRequest->academicPaperSubjectId =current($subjectList)->subject->id;
        $subjectGradeSchemeArray = GradeSchemeService::getInstance()->getAllSubjectGradeSchemesByRequest($searchRequest);
        
        $additionalInfo->allGrades = reset( $subjectGradeSchemeArray )->grades;
        usort($additionalInfo->allGrades, function ($a, $b) {
            return $a->percentFrom < $b->percentFrom;
        });
        $additionalInfo->moderationMarkArr = $moderationMarkArr;
        $additionalInfo->patternCourseName = reset($studentsMarkList)->studentDetails->degree;
        $additionalInfo->examRegName = $examRegistration->name;
        $additionalInfo->admissionYear = $batch->properties->startYear;
        $additionalInfo->totalGrade = count($additionalInfo->allGrades);
        $additionalInfo->totalcolumns = count($additionalInfo->allGrades) * ( count($moderationMarkArr) + 1) + 4;
        $additionalInfo->semesterPercentage = $semesterPercentage;
        $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/moderationStatisticalAnalysisReport/$templateName.twig"),  ['departments' =>  $subjectList, 'additionalInfo' => $additionalInfo]);
        $prtContent = NULL;
            $prtContent .= '<html><head>';
            $prtContent .= "<style>
                </style>";
            $prtContent .= '</head><title>Moderation Statistical Analysis Report</title><body>';
            $prtContent .= $responseHtml;
            $prtContent .= '</body></html>';
            $totalWidth = 297;
            $totalHeight = 210;
            $options = array(
                'page-width'     => $totalWidth."mm",
                'page-height'    => $totalHeight."mm",
                'dpi'            => 96,
                'margin-top' => "9mm",
                'margin-left' => "1mm",
                'margin-right' => "1mm",
                'margin-bottom' => "9mm",
                // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
            );
        $programResult = new \stdClass;
        $programResult->dispalyHtmlData = $responseHtml;
        $programResult->printData = PdfUtil::renderPdf($prtContent, $options);
        return  $programResult;
    }
    public function getGradeByPercentage($percentage, $gradeDetails)
    {
        foreach ($gradeDetails as $grade) {
            if ($grade->rangeFrom <= $percentage && $grade->rangeTo >= $percentage) {
                return $grade;
            }
        }
        return null;
    }
    /**
     * get Subjects For Moderation Mark
     * @param $searchRequest
     * @return $moderationDetails
     */
    public function getBatchStudentForModerationMark($searchRequest){
        try{
            if(empty($searchRequest->groupId) || empty($searchRequest->examRegistrationId )){
                throw new ExamControllerException (ExamControllerException::INVALID_PARAMETERS,"Batch Or Registration Missing!");
            }
            $moderationStudentsDetails = $this->getSubjectsForModerationModule($searchRequest);
            if(empty($moderationStudentsDetails)){
                throw new ExamControllerException (ExamControllerException::INVAILED_REGISTER_NUMBER,"Invailed Register Number Entered!");
            }
            else{
                $searchRuleRequest = new SearchRuleRequest;
                $searchRuleRequest->name = "EXAM_MODERATION_RULE";
                $moderationRule = reset(RuleService::getInstance()->searchRule($searchRuleRequest))->rule;
                $isShowFailedSubjectOnlyInMarkEntry = $moderationRule->isShowFailedSubjectOnlyInMarkEntry == 1 ? true : false;
                if($isShowFailedSubjectOnlyInMarkEntry){
                    foreach($moderationStudentsDetails as $moderationKey => $moderationDetails){
                        $studentSubjects = [];
                        $failedSubjects = [];
                        $studentSubjects = $moderationDetails->subjects;
                        foreach($studentSubjects as $subject){
                            $searchRequestForGradeScheme = new \stdClass();
                            $searchRequestForGradeScheme->groupId = $moderationDetails->groupId;
                            $searchRequestForGradeScheme->academicTermId = $moderationDetails->academicTermId;
                            $searchRequestForGradeScheme->academicPaperSubjectId = $subject->id;
                            $subjectGradeSchemeArray = GradeSchemeService::getInstance()->getAllSubjectGradeSchemesByRequest($searchRequestForGradeScheme);
                            $subjectGradeKey = array_search($subject->id, array_column( $subjectGradeSchemeArray, "id"));
                            $gradeDetails = [];
                            if($subjectGradeKey || $subjectGradeKey === 0){
                                $gradeDetails = $subjectGradeSchemeArray[$subjectGradeKey]->grades;
                            }
                            $maxGradePercent =  max(array_column($gradeDetails,"rangeTo"));
                            $schemeType = "PERCENTAGE";
                            $passCriteriaArray[$subject->id] = GradeSchemeService::getInstance()->getSubjectPassCriteriaByAcademicPaperSubject($subject->id, $schemeType);
                            $checkPassPercentCriteria = new \stdClass();
                            $checkPassPercentCriteria->courseTypeMethod = $moderationDetails->courseTypeMethod;
                            $checkPassPercentCriteria->schemeType = $subjectGradeSchemeArray[$subjectGradeKey]->schemeType ? $subjectGradeSchemeArray[$subjectGradeKey]->schemeType : "PERCENTAGE";
                            $checkPassPercentCriteria->isInternal = $subject->isInternal;
                            $checkPassPercentCriteria->internalMaxMark = $subject->internalMaxMark;
                            $checkPassPercentCriteria->isExternal = $subject->isExternal;
                            $checkPassPercentCriteria->externalMaxMark = $subject->externalMaxMark;
                            $checkPassPercentCriteria->internalMark = round($subject->internalMark, 2 );
                            $checkPassPercentCriteria->passPercentConfig = $passCriteriaArray[$subject->id];
                            $checkPassPercentCriteria->externalMark = round ( $subject->externalMark, 2 );
                            $checkPassPercentCriteria->maxGradePercent = $maxGradePercent;
                            $checkPassPercentCriteria->gradeDetails = $gradeDetails;
                            $subjectPassCriteria = CommonExamService::getInstance()->checkIsFailedByPassPercentCreditCriteria ( $checkPassPercentCriteria );
                            if($subjectPassCriteria->failedStatus =='FAILED'){
                                $failedSubjects[] = $subject;
                            }
                        }
                        $moderationDetails->subjects = $failedSubjects;
                        if(count($moderationDetails->subjects) <= 0){
                            unset($moderationStudentsDetails[$moderationKey]);
                        }
                    }
                }
            }
        }
        catch (\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $moderationStudentsDetails;
    }
}