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 / 36
CRAP
0.00% covered (danger)
0.00%
0 / 1555
FalseNumberService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 36
95790.00
0.00% covered (danger)
0.00%
0 / 1555
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 getCurrentSemesterNumber
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 16
 getCurrentYearLastDigit
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getCurrentYearSecondLastDigit
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getSubjectGroupByAcademicPaperSubjectId
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 20
 getAllStudentIdWithGroupIdAndSubjectGroupId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 23
 getAllPresentStudentIdWithGroupIdAndSubjectGroupId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 30
 getSingleFalseNumber
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 23
 saveFalseNumber
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 7
 getFalseNumberByStudentIdAndAssessmentId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 15
 updateFalseNumber
0.00% covered (danger)
0.00%
0 / 1
110.00
0.00% covered (danger)
0.00%
0 / 61
 getCountOfAllStudentBySubject
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 23
 getCountOfAllRegisteredStudentBySubject
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 28
 getAllStudentFalseNoDetailsBySubject
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 85
 searchStudentsByFalseNo
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 26
 getExamMarkEntryForExamRegistration
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 45
 getFalseNumberGeneratedStudentDetails
0.00% covered (danger)
0.00%
0 / 1
650.00
0.00% covered (danger)
0.00%
0 / 161
 getGeneratedFalseNumberReportStatus
0.00% covered (danger)
0.00%
0 / 1
420.00
0.00% covered (danger)
0.00%
0 / 102
 ValidateBeforeGenerateFalseNumber
0.00% covered (danger)
0.00%
0 / 1
272.00
0.00% covered (danger)
0.00%
0 / 64
 generateAllFalseNumber
0.00% covered (danger)
0.00%
0 / 1
756.00
0.00% covered (danger)
0.00%
0 / 130
 updateStudentAssessmentRegistration
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 32
 generateUniqueFalseNumbers
0.00% covered (danger)
0.00%
0 / 1
4830.00
0.00% covered (danger)
0.00%
0 / 268
 generateRandomString
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 17
 generateNumbers
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 14
 getAllFalseNumbers
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 18
 getFalseNumberFormat
0.00% covered (danger)
0.00%
0 / 1
506.00
0.00% covered (danger)
0.00%
0 / 74
 checkAlphaNumericCodeAlreadyExist
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 checkFalseNumberAlreadyExist
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 getFalseNumberBatchReportWithPacket
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 74
 getAllFalseNumberByStudentsAndTerm
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 40
 embedQRAnswerSheet
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 36
 generateAnswerSheetPDF
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 33
 cleanUpTmpFiles
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 8
 generateUniqueFalseNo
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 getAnswerSheetFormats
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 7
 getBase64Image
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
<?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\service\ExamRegistrationBatchService;
use com\linways\core\ams\professional\constant\examcontroller\CourseTypeConstants;
use com\linways\ec\core\request\SearchExamRegistrationRequest;
use com\linways\ec\core\service\ExamRegistrationService;
use com\linways\ec\core\constant\ExamRegistrationTypeConstants;
use com\linways\core\ams\professional\service\ExamService;
use com\linways\ec\core\service\FalseNumberSettingService;
use com\linways\base\util\TwigRenderer;
use com\linways\core\ams\professional\util\PdfUtil;
use com\linways\ec\core\mapper\FalseNumberServiceMapper;
use com\linways\core\ams\professional\logging\AMSLogger;
use com\linways\ec\core\logging\Events;
use com\linways\ec\core\logging\entities\Staff;
use com\linways\ec\core\request\SearchRuleRequest;
use com\linways\ec\core\service\ExamRegistrationSubjectService;
use com\linways\core\ams\professional\service\AmsCustomFieldsService;
use com\linways\core\ams\professional\constant\AmsCustomFieldsEntities;
use com\linways\ec\core\service\CommonExamService;
use com\linways\core\ams\professional\service\StaffService;
use com\linways\ec\core\queue\ECTaskQueue;
use Twig\TwigFunction;
use com\linways\core\ams\professional\templateEngine\twig\TwigCustomFunctions;
use mikehaertl\wkhtmlto\Pdf;
class FalseNumberService extends BaseService
{
    use MakeSingletonTrait;
    private function __construct() {
        $this->mapper = FalseNumberServiceMapper::getInstance()->getMapper();
        $this->logger = AMSLogger::getLogger('exam-controller-log');
    }
    public function getCurrentSemesterNumber($semeserId){
        try{
            $query = "SELECT
                        name
                    FROM
                        academic_term 
                    WHERE
                        id = '$semeserId' AND type = 'SEMESTER'";
            $academicTerms = $this->executeQueryForObject($query);
            $semeserName = $academicTerms->name;
            $semeserNumber = substr($semeserName, -1);
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($semeserNumber);
    }
    public function getCurrentYearLastDigit()
    {
        try
        {
            $currentYear = date('Y');
            return $lastDigit = substr($currentYear,-1);
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        
    }
    public function getCurrentYearSecondLastDigit()
    {
        try
        {
            $currentYear = date('Y');
            return $secongLastDigit = substr($currentYear, -2,1);
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    
    public function getSubjectGroupByAcademicPaperSubjectId($academicTermId){
        $whereQuery = NULL;
        if(!empty($academicTermId)){
            $whereQuery.= " AND JSON_CONTAINS(identifying_context, '{\"paperSubjectsId\":\"$academicTermId\"}') ";
        }
        $whereQuery .= " AND  g.type LIKE 'SUBJECT' ";
        try{
            $query = "SELECT
                        g.id
                    FROM
                        `groups` g
                    WHERE
                        1 = 1";
            $subjectGroup = $this->executeQueryForObject($query.$whereQuery);
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($subjectGroup->id);
    }
    public function getAllStudentIdWithGroupIdAndSubjectGroupId($BatchGroupId,$subjectGroupId)
    {
        try
        {
            $query = "SELECT
                        distinct gm.members ->> '$.studentId' as studentId
                    FROM 
                        group_members gm
                    WHERE 
                        gm.groups_id = '$BatchGroupId
                        AND gm.members ->> '$.studentId' IN (SELECT 
                                                                distinct gm1.members ->> '$.studentId' as subStudentId
                                                            FROM 
                                                                group_members gm1
                                                            WHERE 
                                                                gm1.groups_id = '$subjectGroupId')";
            $studentIds = $this->executeQueryForList($query);
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($studentIds);
        
        
    }
    
    public function getAllPresentStudentIdWithGroupIdAndSubjectGroupId($BatchGroupId,$subjectGroupId,$academicPaperSubjectId,$assessmentId)
    {
        try
        {
            $query = "SELECT
                        distinct gm.members ->> '$.studentId' as studentId
                    FROM 
                        group_members gm
                    INNER JOIN exam_attendance ea
                        ON gm.members ->> '$.studentId' = ea.studentId
                    INNER JOIN exam_reg_studentsubject erss
                        ON ea.studentId = erss.studentId
                    WHERE 
                        gm.groups_id = '$BatchGroupId
                        AND gm.members ->> '$.studentId' IN (SELECT 
                                                                distinct gm1.members ->> '$.studentId' as subStudentId
                                                            FROM 
                                                                group_members gm1
                                                            WHERE 
                                                                gm1.groups_id = '$subjectGroupId')
                        AND erss.cm_academic_paper_subjects_id = '$academicPaperSubjectId'
                        AND ea.isAbsent = 0
                        AND ea.m_assessment_id = '$assessmentId'";
            $studentIds = $this->executeQueryForList($query);
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($studentIds);
        
        
    }
    public function getSingleFalseNumber($falseNumberFormat,$randomNumber,$randomSting,$falseNoNumofdigits)
    {
        $singleFalseNumber = "";
        $countForFalseNo=0;
        $countForFalseString=0;
        for($k=1;$k<=$falseNoNumofdigits;$k++)
        {
            if ($falseNumberFormat[$k] == "FalseNumber")
            {
                $singleFalseNumber = $singleFalseNumber . substr($randomNumber, $countForFalseNo,1);
                $countForFalseNo ++;
            }
            else if ($falseNumberFormat[$k] == "FalseNumberString")
            {
                $singleFalseNumber = $singleFalseNumber . substr($randomSting, $countForFalseString,1);
                $countForFalseString ++;
            }
            else
            {
                $singleFalseNumber = $singleFalseNumber . $falseNumberFormat[$k];
            }
        }
        return($singleFalseNumber);
    }
    public function saveFalseNumber($singleFalseNumber,$studentId,$assessmentId){
        $assessmentReg = $this->getFalseNumberByStudentIdAndAssessmentId($studentId,$assessmentId);
        if($assessmentReg->id){
            if(is_null($assessmentReg->falseNo)){
                $this->updateFalseNumber($singleFalseNumber,$assessmentReg->id);
            }
        }
    }
    public function getFalseNumberByStudentIdAndAssessmentId($studentId,$assessmentId){
        try{
            $query = "SELECT
                        sar.id,
                        sar.falseNo as falseNo
                    FROM 
                    ec_student_assessment_registration sar
                    WHERE 
                        sar.am_assessment_id = '$assessmentId' AND sar.student_id = '$studentId'";
            $falseNo = $this->executeQueryForObject($query);
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($falseNo);
    }
    public function updateFalseNumber($falseNo,$falseNoRelationId,$bookletNo = null){
        $falseNo = $this->realEscapeString($falseNo);
        $falseNoRelationId = $this->realEscapeString($falseNoRelationId);
        $bookletNo = $this->realEscapeString($bookletNo);
        $updateQueryAddOn = NULL;
        if(empty($falseNo) || empty($falseNoRelationId)){
            throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS," Can't Update False Number");
        }
        $searchRuleRequest = new SearchRuleRequest;
        $searchRuleRequest->name = "FALSE_NUMBER_AND_ALPHA_NUMERIC_CODE_SETTINGS";
        $falseNoAndAlphaNumericCodeSettings = reset(RuleService::getInstance()->searchRule($searchRuleRequest));
        $alphaNumericCode = "";
        if($falseNoAndAlphaNumericCodeSettings->rule->enableAlphaNumericCode){
            while(!$alphaNumericCode){
                $generateAlphaNumericCode = reset($this->generateRandomString(1,$falseNoAndAlphaNumericCodeSettings->rule->alphaNumericCodeLength));
                $alreadyExist = $this->checkAlphaNumericCodeAlreadyExist($generateAlphaNumericCode);
                if(!$alreadyExist){
                    $alphaNumericCode  = $generateAlphaNumericCode;
                }
            }
        }
        $alreadyExistFalseNumber = $this->checkFalseNumberAlreadyExist($falseNo);
        if($alreadyExistFalseNumber){
            throw new ExamControllerException (ExamControllerException::DUPLICATE_ENTRY,"Can not update false number. False number already taken. !");
        }
        if($bookletNo){
            $updateQueryAddOn = " properties = JSON_SET(properties, '$.bookletNo','$bookletNo'),";
        }
        $updatedBy = $GLOBALS['userId'];
        $query="UPDATE ec_student_assessment_registration
                set properties = JSON_SET(properties, '$.falseNo','$falseNo'),
                    properties = JSON_SET(properties, '$.alphaNumericCode','$alphaNumericCode'),
                    $updateQueryAddOn
                    updated_by = '$updatedBy',
                    updated_date = utc_timestamp()
                WHERE id = '$falseNoRelationId'";
        
        try{
            $falseNumberRelationId = $this->executeQueryForObject($query,TRUE);
            AMSLogger::log_info($this->logger,Events::EC_GENERATE_SINGLE_FALSE_NUMBER,[
                "staff" => new Staff(["id" => $updatedBy]),
                "falseNo" => $falseNo,
                "falseNoRelationId" => $falseNoRelationId,
                "status" => StatusConstants::SUCCESS
            ]);
        }catch(\Exception $e){
            AMSLogger::log_error($this->logger,Events::EC_GENERATE_SINGLE_FALSE_NUMBER,[
                "staff" => new Staff(["id" => $updatedBy]),
                "falseNo" => $falseNo,
                "falseNoRelationId" => $falseNoRelationId,
                "errorCode" => $e->getCode(),
                "errorMessage" => $e->getMessage(),
                "status" => StatusConstants::FAILED
            ]);
            if ($e->getCode() === ExamControllerException::DUPLICATE_ENTRY) {
                throw new ExamControllerException (ExamControllerException::DUPLICATE_ENTRY,"Can not update false number. False number already taken. !");
            }
            else{
                throw new ExamControllerException($e->getCode(),$e->getMessage());
            }
        }
        return $falseNumberRelationId;
    }
     /**
     * get Count Of All Student BySubject
     * @param $batchGroupId ,$subjectGroupId
     * @return $students 
     * @author Krishnajith
     */
    public function getCountOfAllStudentBySubject($batchGroupId,$subjectGroupId){
        if(empty($batchGroupId) || empty($subjectGroupId)){
            throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For False Number");
        }
        try{
            $query = "SELECT
                        COUNT( gm.members ->> '$.studentId' ) as countStudentIds
                    FROM 
                        group_members gm
                    WHERE 
                        gm.groups_id = '$batchGroupId
                        AND gm.members ->> '$.studentId' IN (SELECT 
                                                                distinct gm1.members ->> '$.studentId' as subStudentId
                                                            FROM 
                                                                group_members gm1
                                                            WHERE 
                                                                gm1.groups_id = '$subjectGroupId')";
            $CountStudentId = $this->executeQueryForObject($query);
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($CountStudentId->countStudentIds);
    }
     /**
     * get Count Of All Registered Student By Subject
     * @param $batchGroupId ,$subjectGroupId
     * @return $students 
     * @author Krishnajith
     */
    public function getCountOfAllRegisteredStudentBySubject($assessmentId,$examRegistrationId){
        if(empty($assessmentId)){
            throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For False Number");
        }
        try{
            $query = "SELECT
                        COUNT( esar.id ) as countStudentIds
                    FROM 
                        ec_student_assessment_registration esar
                    INNER JOIN ec_exam_registration_subject eers
                        ON eers.am_assessment_id  = esar.am_assessment_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 
                    WHERE 
                        eer.id = '$examRegistrationId' AND
                        esar.am_assessment_id = '$assessmentId' AND 
                        esar.ec_exam_registration_type = eer.type AND
                        CAST(esar.properties ->> '$.registrationStatus' AS CHAR) = 'REGISTERED' AND 
                        CAST(esar.properties ->> '$.feeStatus' AS CHAR) = 'PAID'
                        GROUP BY esar.student_id";
            $CountStudentId = $this->executeQueryForObject($query);
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($CountStudentId->countStudentIds);
    }
     /**
     * get All Student FalseNo Details By Subject
     * @param  $searchRequest
     * @return $students 
     * @author Krishnajith
     */
    public function getAllStudentFalseNoDetailsBySubject($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $students = [];
        // if(empty($assessmentId)){
        //     throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For False Number");
        // }
        $orderBy = " ORDER BY g.name ASC , CAST(spa.properties->>'$.registerNumber' AS CHAR) ASC";
        if(!empty($searchRequest->groupId)) {
            $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
            $whereQuery .= " AND eerb.groups_id IN ( $groupIdString )";
        }
        if(!empty($searchRequest->examRegistrationId)) {
            $examRegistrationIdString = is_array($searchRequest->examRegistrationId) ? "'" . implode("','",$searchRequest->examRegistrationId) . "'" : "'".$searchRequest->examRegistrationId."'";
            $whereQuery .= " AND eer.id IN ( $examRegistrationIdString )";
        }
        if (!empty($searchRequest->academicPaperSubjectId)) {
            $academicPaperSubjectIdString = is_array($searchRequest->academicPaperSubjectId) ? "'" . implode("','", $searchRequest->academicPaperSubjectId) . "'" : "'" . $searchRequest->academicPaperSubjectId . "'";
            $whereQuery .= " AND eers.cm_academic_paper_subjects_id IN ( $academicPaperSubjectIdString )";
        }
        if($searchRequest->isShowPresentStudentsInCreateFalseNumber) {
            $joinQuery .= " INNER JOIN oe_student_total_mark ostm ON
            ostm.student_id = esar.student_id AND ostm.am_assessment_id = esar.am_assessment_id AND (ostm.valuation_type IS NULL OR ostm.valuation_type = '') AND ostm.attendance_status = 'PRESENT' ";
        }
        else{
            if(!$searchRequest->notFetchMarkDetails){
                $joinQuery .= " LEFT JOIN oe_student_total_mark ostm ON 
                ostm.student_id = esar.student_id AND ostm.am_assessment_id = esar.am_assessment_id AND ostm.valuation_count = 'FINALIZED' AND (ostm.valuation_type IS NULL OR ostm.valuation_type = '') ";
            }
        }
        try{
            $query = "SELECT
                        sa.studentId AS id,
                        sa.studentId AS studentId,
                        esar.id AS falseNoRelationId,
                        sa. studentId,
                        sa.studentName,
                        esar.falseNo as falseNo,
                        esar.properties ->> '$.bookletNo' as bookletNo,
                        spa.properties ->> '$.registerNumber' as regNo,
                        ostm.attendance_status as attendanceStatus,
                        oe.id as oeExamId,
                        eers.am_assessment_id as assessmentId,
                        ostm.properties as markProperties ,
                        g.id as groupId,
                        g.name as groupName
                    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 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 
                    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 
                    INNER JOIN oe_exams oe ON
                        oe.assessment_id = eers.am_assessment_id AND oe.is_deleted = 0
                    $joinQuery
                    WHERE 
                        esar.ec_exam_registration_type = eer.type AND
                       esar.properties ->> '$.registrationStatus' = 'REGISTERED' 
                        AND (esar.properties ->> '$.syllabusSubType' != 'MOOC' OR esar.properties ->> '$.syllabusSubType' IS NULL) ";
            $students = $this->executeQueryForList($query.$whereQuery.$orderBy);
            foreach($students as $student){
                $student->successStatus = "";
                $student->markProperties = json_decode($student->markProperties);
                if(empty($student->falseNo)){
                    if($student->attendanceStatus == 'ABSENT'){
                        $student->falseNo = 'AB';
                    }
                    else if($student->attendanceStatus == 'MALPRACTICE'){
                        $student->falseNo = 'MAL';
                    }
                }
            }
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($students);
    }
     /** 
     * search Students By FalseNo
     * @param $request
     * @throws ExamControllerException
     */
    public function searchStudentsByFalseNo($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $request = new \stdClass;
            $request->falseNo = $searchRequest->falseNo;
            $students = $this->getFalseNumberGeneratedStudentDetails($request);
            foreach($students as $student){
                $student->valuationDetails->assignedValuationStaffs = $student->valuationDetails->assignedValuationStaffs ? $student->valuationDetails->assignedValuationStaffs : [];
                foreach($student->valuationDetails->assignedValuationStaffs as $assignedValuationStaff){
                    $valuationStaffs = !empty($assignedValuationStaff->addiitonalExamniners) ? StaffService::getInstance()->getStaffByIds($assignedValuationStaff->addiitonalExamniners) : [] ;
                    $valuationStaffNames = array_column($valuationStaffs,'name');
                    if($assignedValuationStaff->count == '1'){
                        $student->valuer1 = implode(",",$valuationStaffNames);
                    }
                    else if($assignedValuationStaff->count == '2'){
                        $student->valuer2 = implode(",",$valuationStaffNames);
                    }
                }
            }
            $resultResponse = new \stdClass;
            $resultResponse->students = $students;
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($resultResponse);
    }
    /** 
     * get Exam MarkEntry For ExamRegistration
     * @param $request
     * @throws ExamControllerException
     */
    public function getExamMarkEntryForExamRegistration($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $whereQuery = "";
        if(!empty($searchRequest->groupId)) {
            $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
            $whereQuery .= " AND g.id IN ( $groupIdString )";
        }
        if(!empty($searchRequest->excludedClassType)) {
            $whereQuery .= " AND caps.properties ->> '$.classType' NOT IN ('" . implode("','", $searchRequest->excludedClassType) . "')";
        }
        if(!empty($searchRequest->academicPaperSubjectId)) {
            $academicPaperSubjectIdString = is_array($searchRequest->academicPaperSubjectId) ? "'" . implode("','",$searchRequest->academicPaperSubjectId) . "'" : "'".$searchRequest->academicPaperSubjectId."'";
            $whereQuery .= " AND eers.cm_academic_paper_subjects_id IN ( $academicPaperSubjectIdString )";
        }
        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->academicTermId)) {
            $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
            $whereQuery .= " AND eerb.properties ->> '$.academicTermId' IN ( $academicTermIdString )";
        }
        $query = "SELECT DISTINCT
                        ostm.id
                    FROM
                        `groups` g
                    INNER JOIN ec_exam_registration_batch eerb ON
                        eerb.groups_id = g.id
                    INNER JOIN ec_exam_registration_subject eers ON
                        eers.ec_exam_registration_batch_id = eerb.id
                    INNER JOIN cm_academic_paper_subjects caps ON
                        caps.id = eers.cm_academic_paper_subjects_id
                    INNER JOIN ec_exam_registration eer ON
                        eer.id = eerb.ec_exam_registration_id
                    INNER JOIN ec_student_assessment_registration esar ON
                        esar.am_assessment_id = eers.am_assessment_id AND  esar.properties ->> '$.registrationStatus' = 'REGISTERED' AND esar.properties ->> '$.feeStatus' = 'PAID' AND esar.ec_exam_registration_type = eer.type
                    INNER JOIN oe_student_total_mark ostm ON
                        ostm.student_id = esar.student_id AND ostm.am_assessment_id = esar.am_assessment_id AND (ostm.valuation_type IS NULL OR ostm.valuation_type = '') AND ostm.mark_obtained > 0 
                    WHERE ostm.attendance_status = 'PRESENT' AND ostm.mark_obtained IS NOT NULL";
        try {
            $examMarkEntry =  $this->executeQueryForList($query.$whereQuery);
        } catch (\Exception $e) {
            throw new ExamControllerException($e->getCode(), $e->getMessage());
        }
        return $examMarkEntry;
    }
    /**
     * get False Number Generated Student Details
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function getFalseNumberGeneratedStudentDetails($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $searchRequest->assessmentId = stripslashes($searchRequest->assessmentId);
        $searchRequest->academicPaperSubjectId = stripslashes($searchRequest->academicPaperSubjectId);
        try{
            $joinQuery = "";
            $selectColumns = "";
            $limitQuery = "";
            $orderBy = " ORDER BY s.code ASC, spa.properties ->> '$.registerNumber' ASC";
            if($searchRequest->falseNoMapper == 'SUBJECT_WISE'){
                $mapper = $this->mapper[FalseNumberServiceMapper::GET_SUBJECT_STUDENT_DETAILS];
            }
            else{
                $mapper = $this->mapper[FalseNumberServiceMapper::GET_STUDENT_DETAILS];
            }
            $whereQuery = "";
            if(!empty($searchRequest->falseNo)) {
                $falseNoString = is_array($searchRequest->falseNo) ? "'" . implode("','",$searchRequest->falseNo) . "'" : "'".$searchRequest->falseNo."'";
                $whereQuery .= " AND esar.falseNo IN ( $falseNoString )";
            }
            if(!empty($searchRequest->groupId)) {
                $groupIdString = is_array($searchRequest->groupId) ? "'" . implode("','",$searchRequest->groupId) . "'" : "'".$searchRequest->groupId."'";
                $whereQuery .= " AND g.id IN ( $groupIdString )";
            }
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND eerb.properties ->> '$.academicTermId' IN ( $academicTermIdString )";
            }
            if(!empty($searchRequest->academicPaperSubjectId)) {
                $academicPaperSubjectIdString = is_array($searchRequest->academicPaperSubjectId) ? "'" . implode("','",$searchRequest->academicPaperSubjectId) . "'" : "'".$searchRequest->academicPaperSubjectId."'";
                $whereQuery .= " AND aps.id IN ( $academicPaperSubjectIdString )";
            }
            if(!empty($searchRequest->packetNo)) {
                $packetNoString = is_array($searchRequest->packetNo) ? "'" . implode("','",$searchRequest->packetNo) . "'" : "'".$searchRequest->packetNo."'";
                $whereQuery .= " AND esar.valuation_details ->> '$.packetNo' IN ( $packetNoString )";
            }
            if(!empty($searchRequest->assessmentId)) {
                $whereQuery .= " AND aa.id IN ( '$searchRequest->assessmentId' )";
            }
            if(!empty($searchRequest->examRegistrationId)) {
                $examRegistrationIdString = is_array($searchRequest->examRegistrationId) ? "'" . implode("','",$searchRequest->examRegistrationId) . "'" : "'".$searchRequest->examRegistrationId."'";
                $whereQuery .= " AND eerb.ec_exam_registration_id IN ( $examRegistrationIdString )";
            }
            if($searchRequest->isFalseNumberNotGeneratedStudentOnly) {
                $whereQuery .= " AND esar.falseNo IS NULL";
            }
            else{
                $whereQuery .= " AND esar.falseNo IS NOT NULL";
            }
            if($searchRequest->falseNoToPresentStudentsOnly) {
                $joinQuery .= " INNER JOIN oe_student_total_mark ostm ON
                ostm.student_id = esar.student_id AND ostm.am_assessment_id = esar.am_assessment_id AND (ostm.valuation_type IS NULL OR ostm.valuation_type = '') AND ostm.attendance_status = 'PRESENT' ";
            }
            else{
                if(!$searchRequest->notFetchMarkDetails){
                    $selectColumns .= ",ostm.mark_obtained as mark";
                    $joinQuery .= " LEFT JOIN oe_student_total_mark ostm ON 
                    ostm.student_id = esar.student_id AND ostm.am_assessment_id = esar.am_assessment_id AND ostm.valuation_count = 'FINALIZED' AND (ostm.valuation_type IS NULL OR ostm.valuation_type = '') ";
                }
            }
            if(!$searchRequest->notCheckSlotCondition) {
                $selectColumns .= ",cclo.name as subjectSlot";
                $joinQuery .= " LEFT JOIN cm_common_list_object cclo ON
                cclo.id = aps.slot_id AND cclo.type = 'SLOT' ";
            }
            if(!empty($searchRequest->excludedClassType)) {
                $whereQuery .= " AND aps.properties ->> '$.classType' NOT IN ('" . implode("','", $searchRequest->excludedClassType) . "')";
            }
            if($searchRequest->orderBy == "SUBJECT_WISE"){
                $orderBy = " ORDER BY s.id ASC , spa.properties->>'$.registerNumber' ASC";
            }
            else if($searchRequest->orderBy == "BATCH_WISE"){
                $orderBy = " ORDER BY g.name ASC , spa.properties->>'$.registerNumber' ASC";
            }
            if($searchRequest->isLimitCondition) {
                $limitQuery = " LIMIT 1";
            }
            
            $query = "SELECT DISTINCT
                        esar.id,
                        esar.falseNo AS falseNo,
                        esar.properties ->> '$.alphaNumericCode' AS alphaNumericCode,
                        esar.valuation_details ->> '$.packetNo' AS packetNo,
                        esar.valuation_details AS valuationDetails,
                        aa.id AS assessmentId,
                        sa.studentID AS studentId,
                        sa.studentName,
                        spa.properties->>'$.registerNumber' AS regNo,
                        sa.rollNo,
                        sa.admissionNo,
                        act.id AS academicTermId,
                        act.name AS academicTermName,
                        act.properties->>'$.orderNo' AS academicTermOrderNo,
                        dept.deptID AS deptId,
                        dept.departmentDesc AS deptName,
                        dept.deptName AS departmentCode,
                        dept.departmentSpecialization AS departmentSpecialization,
                        ct.courseTypeID AS courseTypeId,
                        ct.typeName AS courseTypeName,
                        ct.course_Type AS courseType,
                        eer.name AS examRegistrationName,
                        eer.properties->>'$.examYear' AS examYear,
                        eer.type AS examType,
                        g.id AS groupId,
                        g.name AS groupName,
                        s.code AS subjectCode,
                        s.id AS subjectId,
                        aps.properties ->> '$.syllabusName' AS syllabusName,
                        ap.properties ->> '$.slotId' AS subjectSlotId,
                        s.name AS subjectName,
                        IF(aps.properties ->> '$.classType' = 'THEORY',1,0) AS isTheory,
                        esar.properties,
                        esar.valuation_details as studentValuationDetails,
                        eers.valuation_details as subjectValuationDetails,
                        DATE_FORMAT(aa.properties_value ->>'$.assessmentDate','%d-%m-%Y') AS assessmentDate
                        $selectColumns
                    FROM
                        `groups` g
                    INNER JOIN ec_exam_registration_batch eerb ON
                        eerb.groups_id = g.id
                    INNER JOIN ec_exam_registration_subject eers ON
                        eers.ec_exam_registration_batch_id = eerb.id
                    INNER JOIN ec_exam_registration eer ON
                        eer.id = eerb.ec_exam_registration_id
                    INNER JOIN am_assessment aa ON
                        aa.id = eers.am_assessment_id
                    INNER JOIN  cm_academic_paper_subjects aps ON 
                        eers.cm_academic_paper_subjects_id = aps.id
                    INNER JOIN cm_academic_paper ap ON 
                        aps.cm_academic_paper_id = ap.id
                    INNER JOIN  v4_ams_subject s ON 
                        aps.ams_subject_id = s.id
                    INNER JOIN ec_student_assessment_registration esar ON
                        esar.am_assessment_id = eers.am_assessment_id AND esar.properties ->> '$.registrationStatus' = 'REGISTERED'  AND esar.ec_exam_registration_type = eer.type
                    INNER JOIN studentaccount sa ON 
                        sa.studentID = esar.student_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 
                    INNER JOIN department dept ON
                        dept.deptID = g.properties ->> '$.departmentId'
                    INNER JOIN  academic_term act ON 
                        act.id = eerb.properties ->> '$.academicTermId' 
                    INNER JOIN `course_type` ct ON
                        ct.courseTypeID = p.course_type_id
                    $joinQuery
                    WHERE 
                        aa.properties_value ->>'$.assessmentDate' IS NOT NULL AND (esar.properties ->> '$.syllabusSubType' != 'MOOC' OR esar.properties ->> '$.syllabusSubType' IS NULL) ";
            if($searchRequest->avoidMapperConditions){
                $falseNumberGeneratedStudents =  $this->executeQueryForList($query.$whereQuery.$orderBy.$limitQuery);
            }
            else{
                $falseNumberGeneratedStudents =  $this->executeQueryForList($query.$whereQuery.$orderBy.$limitQuery,$mapper);
            }
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($falseNumberGeneratedStudents);
    }
     /**
     * get Generated FalseNumber Report Status
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function getGeneratedFalseNumberReportStatus($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $searchRequest->academicPaperSubjectId = stripslashes($searchRequest->academicPaperSubjectId);
        try{
            $response = new \stdClass;
            if(empty($searchRequest->examRegistrationId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For False Number");
            }
            $searchRuleRequest = new SearchRuleRequest;
            $searchRuleRequest->name = "FALSE_NUMBER_AND_ALPHA_NUMERIC_CODE_SETTINGS";
            $falseNoAndAlphaNumericCodeSettings = reset(RuleService::getInstance()->searchRule($searchRuleRequest));
            $isEnableQueueForFalseNoCreation = $falseNoAndAlphaNumericCodeSettings->rule->isEnableQueueForFalseNoCreation == '1' ? true : false;
            $isEnableRegeneratingFalseNoForNewStudents = $falseNoAndAlphaNumericCodeSettings->rule->isEnableRegeneratingFalseNoForNewStudents == '1' ? true : false;
            if($isEnableQueueForFalseNoCreation && $searchRequest->isAvoidLimitCondition == 'true' && empty($searchRequest->groupId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"please choose batch");
            }
            if($searchRequest->isAvoidLimitCondition == 'true'){
                $isEnableQueueForFalseNoCreation = false;
            }
            if($isEnableQueueForFalseNoCreation){
                $requestForExamRegistration = new SearchExamRegistrationRequest;
                $requestForExamRegistration->id = $searchRequest->examRegistrationId;
                $examRegistration = reset(ExamRegistrationService::getInstance()->searchExamRegistration($requestForExamRegistration));
                $response->falseNoQueueStatus = $examRegistration->properties->falseNoQueueStatus;
                $response->falseNoQueueMessage = $examRegistration->properties->falseNoQueueMessage;
            }
            $request = new \stdClass;
            $request->examRegistrationId = $searchRequest->examRegistrationId;
            $request->groupId = $searchRequest->groupId;
            $request->academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->reportType = $searchRequest->reportType;
            $request->notFetchMarkDetails = true;
            $request->notCheckSlotCondition = true;
            $request->isLimitCondition = $isEnableQueueForFalseNoCreation ? true : false; 
            $request->falseNoMapper = $request->reportType == 'BATCH_WISE' ? "SUBJECT_WISE" : '';
            $falsenemberGeneratedStudents = $this->getFalseNumberGeneratedStudentDetails($request);
            if(empty($falsenemberGeneratedStudents)){
                $response->isFalseNumberNotGenerated = true;
            }
            else{
                $response->isFalseNumberNotGenerated = false;
                $additionalDetails = new \stdClass; 
                $additionalDetails->collegeName = $GLOBALS['COLLEGE_NAME']; 
                $response->falseNumberGeneratedStatus = "False Number Already Generated";
                $response->isRedirectToBatchWiseReport = $isEnableQueueForFalseNoCreation ? true : false;
                $response->isEnableRegeneratingFalseNoForNewStudents = $isEnableRegeneratingFalseNoForNewStudents ? true : false;
                if(!$isEnableQueueForFalseNoCreation){
                    $markEntryStatus = $this->getExamMarkEntryForExamRegistration($request);
                    if (!empty($markEntryStatus)) {
                        $response->falseNumberGeneratedStatus = "Marks Are Already Entered";
                    }
                    $requestForExamRegistration = new SearchExamRegistrationRequest;
                    $requestForExamRegistration->id = $request->examRegistrationId;
                    $examRegistration = ExamRegistrationService::getInstance()->searchExamRegistration($requestForExamRegistration);
                    if(!empty($examRegistration)){
                        $additionalDetails->examRegistrationName = reset($examRegistration)->name;
                        $additionalDetails->examRegistrationType = reset($examRegistration)->type; 
                    }
                    if($request->reportType == 'BATCH_WISE'){
                        $requestForAssessment = new \stdClass;
                        $requestForAssessment->examRegistrationId = $searchRequest->examRegistrationId;
                        $requestForAssessment->groupId = $searchRequest->groupId;
                        $subjects = ExamRegistrationSubjectService::getInstance()->getAllAssessmentDetails($requestForAssessment);
                        $examRegistrationDetailsArray = ExamRegistrationService::getInstance()->searchDetailedExamRegistrationDetails($requestForAssessment);
                        $additionalDetails->batchName = reset($examRegistrationDetailsArray)->groups[0]->groupName;
                        $additionalDetails->courseName = reset($examRegistrationDetailsArray)->groups[0]->degreeName .'-'.reset($examRegistrationDetailsArray)->groups[0]->streamName ;
                        $additionalDetails->subjects = $subjects;
                    }
                    $templateName = $request->reportType == 'BATCH_WISE' ? 'BatchWiseFalseNumberReport' : 'FalseNumberGeneratedListReport';
                    $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/FalseNumberReports/$templateName.twig"), [ 'students'=>$falsenemberGeneratedStudents ,'additionalDetails'=>$additionalDetails]);
                    $prtContent = NULL;
                    $prtContent .= '<html><head>';
                    $prtContent .= "<style>
                        h6 {font-size: 26px;} .text-center { text-align: center;} .align-middle {vertical-align: middle;}; tr.noBorder td {border: 0;  border-collapse:collapse;}
                        table, th, td {border: 1px solid black;border-collapse: collapse;} .displayOnlyDisplayData { display: none; }
                        </style>";
                    $prtContent .= '</head><title>False Number Generated List</title><body>';
                    $prtContent .= $responseHtml;
                    $prtContent .= '</body></html>';
                    $totalWidth = 210;
                    $totalHeight = 297;
                    $options = array(
                        'page-width'     => $totalWidth."mm",
                        'page-height'    => $totalHeight."mm",
                        'dpi'            => 96,
                        'margin-top' => "10mm",
                        'margin-left' => "10mm",
                        'margin-right' => "10mm",
                        'margin-bottom' => "30mm",
                        // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                        'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
                    );
                    $response->dispalyHtmlData = $responseHtml;
                    $response->printData = PdfUtil::renderPdf($prtContent, $options);
                }
            }
            return  $response;
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * Generate All False Number Validation Before add queue
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function ValidateBeforeGenerateFalseNumber($searchRequestObj){
        $searchRequest = $this->realEscapeObject($searchRequestObj);
        $searchRuleRequest = new SearchRuleRequest;
        $searchRuleRequest->name = "FALSE_NUMBER_AND_ALPHA_NUMERIC_CODE_SETTINGS";
        $falseNoAndAlphaNumericCodeSettings = reset(RuleService::getInstance()->searchRule($searchRuleRequest));
        $isEnableQueueForFalseNoCreation = $falseNoAndAlphaNumericCodeSettings->rule->isEnableQueueForFalseNoCreation == '1' ? true : false;
        $isEnableRegeneratingFalseNoForNewStudents = $falseNoAndAlphaNumericCodeSettings->rule->isEnableRegeneratingFalseNoForNewStudents == '1' ? true : false;
        try{
            if(empty($searchRequest->examRegistrationId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For False Number");
            }
            $request = new \stdClass;
            $request->examRegistrationId = $searchRequest->examRegistrationId;
            $request->academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->groupId = $searchRequest->groupId;
            $searchRequestObj->isEnableRegeneratingFalseNoForNewStudents = $isEnableRegeneratingFalseNoForNewStudents;
            $settings= FalseNumberSettingService::getInstance()->getFalseNumberSettings($request);
            if($settings->properties->excludedClassType){
                $request->excludedClassType = $settings->properties->excludedClassType;
            }
            if(empty($settings) || empty($settings->properties)){
                throw new ExamControllerException(ExamControllerException::NO_FALSE_NUMBERS_IN_CONFIGURATION,"False Number Configuration Not Found. Please Add False Number Configuration");
            }
            $request->isLimitCondition = 1;
            $falsenemberGeneratedStudents = $this->getFalseNumberGeneratedStudentDetails($request);
            if(! empty($falsenemberGeneratedStudents) && !$isEnableRegeneratingFalseNoForNewStudents){
                throw new ExamControllerException(ExamControllerException::FALSE_NUMBER_ALREADY_GENERATED,"False Number Already Generated In This Exam");
            }
            if( $isEnableRegeneratingFalseNoForNewStudents && count($falsenemberGeneratedStudents)){
                $searchRequestObj->alreadyGenerated = 1;
            }
            $request->isLimitCondition = false;
            $markEntryStatus = $this->getExamMarkEntryForExamRegistration($request);
            if (!empty($markEntryStatus)) {
                throw new ExamControllerException(ExamControllerException::ALREADY_MARK_ENTERED_FOR_THIS_EXAM,"You Cannot Generate False Number Since Marks Are Already Entered For This Exam");
            }
            $subjects = FalseNumberGroupService::getInstance()->getAssignedSubjectByExamRegForFalseNumberGroup($request);
            if(empty($subjects)){
                throw new ExamControllerException(ExamControllerException::EMPTY_SUBJECTS_IN_EXAM_REGISTRATION_BATCH," No subjects !");
            }
            if($isEnableQueueForFalseNoCreation){
                $searchRequestObj->isEnableQueueForFalseNoCreation = true;
                $requestForExamRegistration = new SearchExamRegistrationRequest;
                $requestForExamRegistration->id = $searchRequest->examRegistrationId;
                $examRegistration = reset(ExamRegistrationService::getInstance()->searchExamRegistration($requestForExamRegistration));
                $response->falseNoQueueStatus = $examRegistration->properties->falseNoQueueStatus;
                if($response->falseNoQueueStatus == 'PROCESSING'){
                    throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS," already in Queue");
                }
                ExamRegistrationService::getInstance()->updateFalseNumberQueueUpdateStatus($searchRequest->examRegistrationId,"PROCESSING");
                $taskQueue = new ECTaskQueue();
                $params    = ['className'  => 'com\linways\ec\core\service\FalseNumberService',
                'methodName'               => 'generateAllFalseNumber',
                'methodParams'             => [$searchRequestObj]];        
                $taskQueue->enqueue('EXECUTE SERVICE', $params);
            }
            else{
                $this->generateAllFalseNumber($searchRequestObj);
            }
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * Generate All False Number 
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function generateAllFalseNumber($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            $requestForFalseNumberNotGeneratedStudent = new \stdClass;
            $requestForFalseNumberNotGeneratedStudent->examRegistrationId = $searchRequest->examRegistrationId;
            $requestForFalseNumberNotGeneratedStudent->academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $requestForFalseNumberNotGeneratedStudent->groupId = $searchRequest->groupId;
            $requestForFalseNumberNotGeneratedStudent->academicTermId = $searchRequest->academicTermId;
            $requestForFalseNumberNotGeneratedStudent->isFalseNumberNotGeneratedStudentOnly = true;
            $requestForFalseNumberNotGeneratedStudent->excludedClassType = [];
            $request = new \stdClass;
            $request->examRegistrationId = $searchRequest->examRegistrationId;
            $request->academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $request->academicTermId = $searchRequest->academicTermId;
            $request->groupId = $searchRequest->groupId;
            $settings= FalseNumberSettingService::getInstance()->getFalseNumberSettings($request);
            if($settings->properties->excludedClassType){
                $requestForFalseNumberNotGeneratedStudent->excludedClassType = $settings->properties->excludedClassType;
            }
            if($settings->falseNoToPresentStudentsOnly){
                $requestForFalseNumberNotGeneratedStudent->falseNoToPresentStudentsOnly = true;
            }
            if($settings->properties->batchwiseOrSubjectwise = "subjectwise"){
                $requestForFalseNumberNotGeneratedStudent->orderBy = "SUBJECT_WISE";
            }
            else{
                $requestForFalseNumberNotGeneratedStudent->orderBy = "BATCH_WISE";
            }
            // this case add for avoid the join case
            $requestForFalseNumberNotGeneratedStudent->notFetchMarkDetails = true;
            $requestForFalseNumberNotGeneratedStudent->avoidMapperConditions = true;
            $registeredStudents = $this->getFalseNumberGeneratedStudentDetails($requestForFalseNumberNotGeneratedStudent);
            if(empty($registeredStudents)){
                if ( $searchRequest->isEnableRegeneratingFalseNoForNewStudents && $searchRequest->alreadyGenerated){
                    throw new ExamControllerException(ExamControllerException::NO_STUDENT_IN_THE_BATCH_SUBJECT," No Newly Registered Students !");
                }
                else{
                    throw new ExamControllerException(ExamControllerException::NO_STUDENT_IN_THE_BATCH_SUBJECT," No Students Registered !");
                }
            }
            $totalNoOfStudents = count($registeredStudents);
            $falseNoNumofdigits = $settings->falseNoNumofdigits;
            $configuration = $settings->properties->configuration;
            $countOfFlNoByRange = $settings->falseNoTotalRangeTo - $settings->falseNoTotalRangeFrom;
            $noOfFalseNumber = 0;
            $noOfFalseNumberString = 0;
            $countOfFlNoGen = 0;
            $falseNoStringCount = 0;
            for($i=1;$i<=$falseNoNumofdigits;$i++){
                if($configuration[$i]->type == 'falseNumber'){
                    $noOfFalseNumber++ ;
                    $falseNumberFormat[$i] = "FalseNumber";
                }
                else if($configuration[$i]->type == 'falseNumberString'){
                    $noOfFalseNumberString++ ;
                    $falseNumberFormat[$i] = "FalseNumberString";
                }
            }
            if($noOfFalseNumber > 0){
                $falseNoNumCount = pow(10, $noOfFalseNumber)-1;
                if($countOfFlNoByRange > $falseNoNumCount){
                    $countOfFlNoGen = $falseNoNumCount;
                }
                else{
                    $countOfFlNoGen = $countOfFlNoByRange;
                }
            }
            if($noOfFalseNumberString > 0){
                // fetch only available false number strings 
                // $falseNoStringCount = pow(10, $noOfFalseNumberString)-1;
                $falseNoStringCount = (count($registeredStudents)) + 100;
            }
            $maximumFalseNumberRange = $countOfFlNoGen + $falseNoStringCount;
            if($noOfFalseNumber == 0 && $noOfFalseNumberString == 0){
                throw new ExamControllerException(ExamControllerException::NO_FALSE_NUMBERS_IN_CONFIGURATION," No False Number in The Configuration. Plese Add False Numbers In The Configuration");
            }
            if($totalNoOfStudents > $maximumFalseNumberRange){
                throw new ExamControllerException(ExamControllerException::NO_FALSE_NUMBERS_IN_CONFIGURATION,"No of students exceeded to false number range. Please change the limit in False Number Settings");
            }
            foreach($registeredStudents as $student){
                $requestForFalseNumberFormat = new \stdClass;
                $requestForFalseNumberFormat->settings = $settings;
                $requestForFalseNumberFormat->student = $student;
                $student->falseNumberFormat = $this->getFalseNumberFormat($requestForFalseNumberFormat);
                $student->studentValuationDetails = json_decode($student->studentValuationDetails);
                $student->subjectValuationDetails = json_decode($student->subjectValuationDetails);
                $student->properties = json_decode($student->properties);
            }
            $requestForGenrateUniqueFalseNumbers = new \stdClass;
            $requestForGenrateUniqueFalseNumbers->totalNoOfFalseNumber = $totalNoOfStudents;
            $requestForGenrateUniqueFalseNumbers->falseNoCount = $countOfFlNoGen;
            $requestForGenrateUniqueFalseNumbers->falseStringCount = $falseNoStringCount;
            $requestForGenrateUniqueFalseNumbers->falseStringLength = $noOfFalseNumberString;
            $requestForGenrateUniqueFalseNumbers->students = $registeredStudents;
            $requestForGenrateUniqueFalseNumbers->falseNoNumofdigits = $settings->falseNoNumofdigits;
            $requestForGenrateUniqueFalseNumbers->noOfFalseNumber = $noOfFalseNumber;
            $requestForGenrateUniqueFalseNumbers->minimumFalseNumberRange = $settings->falseNoTotalRangeFrom ? $settings->falseNoTotalRangeFrom : 0;
            $requestForGenrateUniqueFalseNumbers->shuffleAllExams = $settings->shuffleAllExams;
            $falseNoGeneratedStudents = $this->generateUniqueFalseNumbers($requestForGenrateUniqueFalseNumbers);
            $isIssueForEmptyParameter = false;
            $falseNumberupdateQueryObjArray = [];
            foreach($falseNoGeneratedStudents as $student){
                if(empty($student->studentId) || empty($student->assessmentId) || empty($student->falseNo)){
                    $isIssueForEmptyParameter = true;
                }
                else{
                    $student->properties->falseNo = $student->falseNo;
                    if( $student->alphaNumericCode ){
                        $student->properties->alphaNumericCode = $student->alphaNumericCode;
                    }
                    $falseNumberupdateQueryObj = new \Stdclass();
                    $falseNumberupdateQueryObj->studentId = $student->studentId;
                    $falseNumberupdateQueryObj->examRegistrationType = $student->examType;
                    $falseNumberupdateQueryObj->properties = $student->properties;
                    $falseNumberupdateQueryObj->assessmentId = $student->assessmentId;
                    $falseNumberupdateQueryObj->updatedBy = $GLOBALS['userId'];
                    $falseNumberupdateQueryObjArray[] = $falseNumberupdateQueryObj;
                }
            }
            if($isIssueForEmptyParameter || empty($falseNumberupdateQueryObjArray)){
                throw new ExamControllerException(ExamControllerException::NO_FALSE_NUMBERS_IN_CONFIGURATION," No False Number in The Configuration. Please Add False Numbers In The Configuration");
            }
            else{
                $this->updateStudentAssessmentRegistration($falseNumberupdateQueryObjArray);
            }
            if($searchRequest->isEnableQueueForFalseNoCreation){
                ExamRegistrationService::getInstance()->updateFalseNumberQueueUpdateStatus($searchRequest->examRegistrationId,"SUCCESS");
            }
        }
        catch(\Exception $e){
            ExamRegistrationService::getInstance()->updateFalseNumberQueueUpdateStatus($searchRequest->examRegistrationId,"FAILED",$e->getMessage());
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * update Student Assessment Registration
     * @param  $falseNumberupdateQueryObjArray
     */
    public function updateStudentAssessmentRegistration($falseNumberupdateQueryObjArray){
        $falseNumberupdateQueryObjArray = $this->realEscapeArray($falseNumberupdateQueryObjArray);
        $currentStaffId = $GLOBALS['userId'];
        try {
            foreach($falseNumberupdateQueryObjArray as $updatedValue){
                $properties = !empty($updatedValue->properties) ? "'" . json_encode($updatedValue->properties) . "'" : "NULL";
                $update_query = "UPDATE
                            ec_student_assessment_registration
                        SET
                            properties = $properties,
                            updated_by = '$updatedValue->updatedBy',                               
                            updated_date = 'utc_timestamp()'
                        WHERE
                        am_assessment_id = '$updatedValue->assessmentId' AND student_id =  '$updatedValue->studentId' AND ec_exam_registration_type = '$updatedValue->examRegistrationType'";
                $this->executeQuery($update_query);
            }
            AMSLogger::log_info($this->logger,Events::EC_GENERATE_FALSE_NUMBER,[
                "staff" => new Staff(["id" => $currentStaffId]),
                "request" => $falseNumberupdateQueryObjArray,
                "status" => StatusConstants::SUCCESS
            ]);
        }
        catch (\Exception $e){
            AMSLogger::log_error($this->logger,Events::EC_GENERATE_FALSE_NUMBER,[
                "staff" => new Staff(["id" => $currentStaffId]),
                "request" => $falseNumberupdateQueryObjArray,
                "errorCode" => $e->getCode(),
                "errorMessage" => $e->getMessage(),
                "status" => StatusConstants::FAILED
            ]);
            throw new ExamControllerException($e->getCode(),"Error Saving False No");
        }
    }
     /**
     * get Unique False Numbers
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function generateUniqueFalseNumbers($searchRequest){
        try{
            $students = $searchRequest->students;
            $totalNoOfFalseNumber = $searchRequest->totalNoOfFalseNumber;
            $falseStringCount = $searchRequest->falseStringCount;
            $falseNoCount = $searchRequest->falseNoCount;
            $falseStringLength = $searchRequest->falseStringLength;
            $minimumFalseNumberRange = $searchRequest->minimumFalseNumberRange;
            $falseNoNumofdigits = (int)$searchRequest->falseNoNumofdigits;
            $noOfFalseNumber = (int)$searchRequest->noOfFalseNumber;
            $shuffleAllExams = $searchRequest->shuffleAllExams == 1 ? true : false;
            $generatedFalseNumber = 0;
            $countForFalseNo = 0;
            $countForFalseString = 0;
            $alphaNumericCodeArray = [];
            $searchRuleRequest = new SearchRuleRequest;
            $currentFalseNumbers = [];
            $searchRuleRequest->name = "FALSE_NUMBER_AND_ALPHA_NUMERIC_CODE_SETTINGS";
            $falseNoAndAlphaNumericCodeSettings = reset(RuleService::getInstance()->searchRule($searchRuleRequest));
            if($falseNoCount > 0){
                $numbers = $this->generateNumbers($minimumFalseNumberRange,$falseNoCount,$noOfFalseNumber,$shuffleAllExams);
            }
            if($falseStringLength > 0){
                $faseNumberStringArray = $this->generateRandomString($falseStringCount,$falseStringLength);
            }
            // this case for same false number against student and semester 
            $isSameFalseNumberForSemester = $falseNoAndAlphaNumericCodeSettings->rule->isSameFalseNumberForSemester == '1' ? true : false;
            $isFalseNumbersUnique = $falseNoAndAlphaNumericCodeSettings->rule->isFalseNumbersUnique == '0' ? false : true;
            $enableReShuffleInSubjects = $falseNoAndAlphaNumericCodeSettings->rule->enableReShuffleInSubjects == '1' ? true : false;
            $alphaNumbericCodeTemplate = $falseNoAndAlphaNumericCodeSettings->rule->alphaNumericCodeTemplate;
            if($isSameFalseNumberForSemester){
                $falseNoRegForStudentTerm = new \stdClass;
                $falseNoRegForStudentTerm ->studentId = array_unique(array_column($students, 'studentId'));
                $falseNoRegForStudentTerm->academicTermId = array_unique(array_column($students, 'academicTermId'));
                $mappedFalseNumbers = $this->getAllFalseNumberByStudentsAndTerm($falseNoRegForStudentTerm);
                foreach($students as $key =>$student){
                    if($mappedFalseNumbers[$student->studentId.$student->academicTermId]){
                        $student->falseNo = $mappedFalseNumbers[$student->studentId.$student->academicTermId];
                        $generatedFalseNumber ++;
                    }
                    else{
                        $singleFalseNumber = "";
                        $positionForFalseNo = 0;
                        $positionForFalseString = 0;
                        $falseNumberAlreadyExist = false;
                        while($countForFalseNo <= count($numbers) || $countForFalseString <= count($faseNumberStringArray)){
                            $isFalseNumberEntered = false;
                            $isFalseStringEntered = false;
                            for($k=1;$k<=$falseNoNumofdigits;$k++){
                                if ($student->falseNumberFormat[$k] == "FalseNumber"){
                                    $countForFalseNoForNumber = $countForFalseNo ;
                                    if(empty($numbers[$countForFalseNoForNumber])){
                                        $countForFalseNoForNumber = rand(0, count($numbers) -1 );
                                    }
                                    $singleFalseNumber = $singleFalseNumber . substr($numbers[$countForFalseNoForNumber], $positionForFalseNo,1);
                                    $positionForFalseNo ++;
                                    $isFalseNumberEntered = true;
                                }
                                else if ($student->falseNumberFormat[$k] == "FalseNumberString"){
                                    $countForFalseNoForString = $countForFalseString ;
                                    if(empty($faseNumberStringArray[$countForFalseNoForString])){
                                        $countForFalseNoForString = rand(0, count($faseNumberStringArray) -1 );
                                    }
                                    $singleFalseNumber = $singleFalseNumber . substr($faseNumberStringArray[$countForFalseNoForString], $positionForFalseString,1);
                                    $positionForFalseString ++;
                                    $isFalseStringEntered = true;
                                }
                                else{
                                    $singleFalseNumber = $singleFalseNumber . $student->falseNumberFormat[$k];
                                }
                            }
                            $falseNumberAlreadyExist = $this->checkFalseNumberAlreadyExist($singleFalseNumber);
                            if(!$falseNumberAlreadyExist && !in_array($singleFalseNumber,$currentFalseNumbers)){
                                $student->falseNo = $singleFalseNumber;
                                //Generate alpha numeric code
                                if($falseNoAndAlphaNumericCodeSettings->rule->enableAlphaNumericCode){
                                    switch ($alphaNumbericCodeTemplate) {
                                        case 'Template_1': 
                                            // SCEK college
                                            $student->alphaNumericCode = "";
                                            while(!$student->alphaNumericCode){
                                                $generateAlphaNumericCode = reset($this->generateRandomString(1,$falseNoAndAlphaNumericCodeSettings->rule->alphaNumericCodeLength));
                                                $alreadyExist = $this->checkAlphaNumericCodeAlreadyExist($generateAlphaNumericCode);
                                                if(!in_array($generateAlphaNumericCode,  $alphaNumericCodeArray) && !$alreadyExist){
                                                    $alphaNumericCodeArray[] = $generateAlphaNumericCode;
                                                    $student->alphaNumericCode  = $generateAlphaNumericCode;
                                                }
                                            }
                                            break;
                                        case 'Template_2': 
                                            $student->alphaNumericCode = "";
                                            $student->examYear2Digit = substr($student->examYear,-2);
                                            $student->RES = $student->examType == 'REGULAR' ? 'R' : 'S';
                                            $student->courseTypeConstant = $student->courseType == 'UG' ? 'U': 'P';
                                            $semesterNames = CommonExamService::getInstance()->getDifferentSemesterName($student->academicTermName);
                                            $student->semNumber = $semesterNames->semNumber;
                                            $student->slot = $student->subjectSlot;
                                            $student->randomString = $student->falseNo;
                                            $student->alphaNumericCode = $student->examYear2Digit . $student->departmentSpecialization . "-" . $student->RES . $student->courseTypeConstant . $student->semNumber . $student->slot . "-" . $student->randomString;
                                            $alreadyExist = $this->checkAlphaNumericCodeAlreadyExist($student->alphaNumericCode);
                                            if( $alreadyExist){
                                                $student->alphaNumericCode  = false;
                                                $countForFalseNo = $isFalseNumberEntered ? $countForFalseNo + 1 : $countForFalseNo;
                                                $countForFalseString = $isFalseStringEntered ? $countForFalseString + 1 : $countForFalseString;
                                                $singleFalseNumber = "";
                                                $positionForFalseNo = 0;
                                                $positionForFalseString = 0;
                                                $student->falseNo = $singleFalseNumber = '';
                                                break;
                                            }
                                            break;
                                        default:
                                            // randoam string generator
                                            $student->alphaNumericCode = "";
                                            while(!$student->alphaNumericCode){
                                                $generateAlphaNumericCode = reset($this->generateRandomString(1,$falseNoAndAlphaNumericCodeSettings->rule->alphaNumericCodeLength));
                                                $alreadyExist = $this->checkAlphaNumericCodeAlreadyExist($generateAlphaNumericCode);
                                                if(!in_array($generateAlphaNumericCode,  $alphaNumericCodeArray) && !$alreadyExist){
                                                    $alphaNumericCodeArray[] = $generateAlphaNumericCode;
                                                    $student->alphaNumericCode  = $generateAlphaNumericCode;
                                                }
                                            }
                                            break;
                                    }
                                    if($student->alphaNumericCode){
                                        $mappedFalseNumbers[$student->studentId.$student->academicTermId] = $student->falseNo;
                                        $currentFalseNumbers[] = $singleFalseNumber;
                                        $generatedFalseNumber ++;
                                        break;
                                    }
                                }
                                else{
                                    $mappedFalseNumbers[$student->studentId.$student->academicTermId] = $student->falseNo;
                                    $currentFalseNumbers[] = $singleFalseNumber;
                                    $generatedFalseNumber ++;
                                    break;
                                }
                            }
                            else{
                                $countForFalseNo = $isFalseNumberEntered ? $countForFalseNo + 1 : $countForFalseNo;
                                $countForFalseString = $isFalseStringEntered ? $countForFalseString + 1 : $countForFalseString;
                                $singleFalseNumber = "";
                                $positionForFalseNo = 0;
                                $positionForFalseString = 0;
                            }
                        }
                    }
                }
            }
            else{ 
                foreach($students as $key =>$student){
                    $singleFalseNumber = "";
                    $positionForFalseNo = 0;
                    $positionForFalseString = 0;
                    $falseNumberAlreadyExist = false;
                    while($countForFalseNo <= count($numbers) || $countForFalseString <= count($faseNumberStringArray)){
                        $isFalseNumberEntered = false;
                        $isFalseStringEntered = false;
                        for($k=1;$k<=$falseNoNumofdigits;$k++){
                            if ($student->falseNumberFormat[$k] == "FalseNumber"){
                                $countForFalseNoForNumber = $countForFalseNo ;
                                if(empty($numbers[$countForFalseNoForNumber])){
                                    $countForFalseNoForNumber = rand(0, count($numbers) -1 );
                                }
                                $singleFalseNumber = $singleFalseNumber . substr($numbers[$countForFalseNoForNumber], $positionForFalseNo,1);
                                $positionForFalseNo ++;
                                $isFalseNumberEntered = true;
                            }
                            else if ($student->falseNumberFormat[$k] == "FalseNumberString"){
                                $countForFalseNoForString = $countForFalseString ;
                                if(empty($faseNumberStringArray[$countForFalseNoForString])){
                                    $countForFalseNoForString = rand(0, count($faseNumberStringArray) -1 );
                                }
                                $singleFalseNumber = $singleFalseNumber . substr($faseNumberStringArray[$countForFalseNoForString], $positionForFalseString,1);
                                $positionForFalseString ++;
                                $isFalseStringEntered = true;
                            }
                            else{
                                $singleFalseNumber = $singleFalseNumber . $student->falseNumberFormat[$k];
                            }
                        }
                        $falseNumberAlreadyExist = $isFalseNumbersUnique ? $this->checkFalseNumberAlreadyExist($singleFalseNumber) : null;
                        if(!$falseNumberAlreadyExist && !in_array($singleFalseNumber,$currentFalseNumbers)){
                            $student->falseNo = $singleFalseNumber;
                            //Generate alpha numeric code
                            if($falseNoAndAlphaNumericCodeSettings->rule->enableAlphaNumericCode){
                                switch ($alphaNumbericCodeTemplate) {
                                    case 'Template_1': 
                                        // SCEK college
                                        $student->alphaNumericCode = "";
                                        while(!$student->alphaNumericCode){
                                            $generateAlphaNumericCode = reset($this->generateRandomString(1,$falseNoAndAlphaNumericCodeSettings->rule->alphaNumericCodeLength));
                                            $alreadyExist = $this->checkAlphaNumericCodeAlreadyExist($generateAlphaNumericCode);
                                            if(!in_array($generateAlphaNumericCode,  $alphaNumericCodeArray) && !$alreadyExist){
                                                $alphaNumericCodeArray[] = $generateAlphaNumericCode;
                                                $student->alphaNumericCode  = $generateAlphaNumericCode;
                                            }
                                        }
                                        break;
                                    case 'Template_2': 
                                        $student->alphaNumericCode = "";
                                        $student->examYear2Digit = substr($student->examYear,-2);
                                        $student->RES = $student->examType == 'REGULAR' ? 'R' : 'S';
                                        $student->courseTypeConstant = substr($student->courseType, 0, 1);
                                        $student->slot = $student->subjectSlot;
                                        $student->randomString =  $student->falseNo;
                                        $student->alphaNumericCode = $student->examYear2Digit . $student->departmentSpecialization . "-" . $student->RES . $student->courseTypeConstant . $student->academicTermOrderNo . $student->slot . "-" . $student->randomString;
                                        // not required since we are adding last 5 digit of false number
                                        // $alreadyExist = $this->checkAlphaNumericCodeAlreadyExist($student->alphaNumericCode);
                                        // if( $alreadyExist){
                                        //     $student->alphaNumericCode  = false;
                                        //     $countForFalseNo = $isFalseNumberEntered ? $countForFalseNo + 1 : $countForFalseNo;
                                        //     $countForFalseString = $isFalseStringEntered ? $countForFalseString + 1 : $countForFalseString;
                                        //     $singleFalseNumber = "";
                                        //     $positionForFalseNo = 0;
                                        //     $positionForFalseString = 0;
                                        //     $student->falseNo = $singleFalseNumber = '';
                                        //     break;
                                        // }
                                        break;
                                    case 'Template_32': 
                                        $student->alphaNumericCode = "";
                                        $student->RES = $student->examType == 'REGULAR' ? 'R' : 'S';
                                        $student->courseTypeConstant = substr($student->courseType, 0, 1);
                                        $student->randomString = "";
                                        $splitFalseNo = str_split($student->falseNo, 2);
                                        foreach ($splitFalseNo as $part) {
                                            $student->randomString .= $part . rand(0, 9);
                                        }
                                        $student->alphaNumericCode = $student->courseTypeConstant.$student->RES . "-" . $student->randomString;
                                        break;
    
                                    default:
                                        // randoam string generator
                                        $student->alphaNumericCode = "";
                                        while(!$student->alphaNumericCode){
                                            $generateAlphaNumericCode = reset($this->generateRandomString(1,$falseNoAndAlphaNumericCodeSettings->rule->alphaNumericCodeLength));
                                            $alreadyExist = $this->checkAlphaNumericCodeAlreadyExist($generateAlphaNumericCode);
                                            if(!in_array($generateAlphaNumericCode,  $alphaNumericCodeArray) && !$alreadyExist){
                                                $alphaNumericCodeArray[] = $generateAlphaNumericCode;
                                                $student->alphaNumericCode  = $generateAlphaNumericCode;
                                            }
                                        }
                                        break;
                                }
                                if( $student->alphaNumericCode){
                                    $currentFalseNumbers[] = $singleFalseNumber;
                                    $generatedFalseNumber ++;
                                    break;
                                }
                                
                            }
                            else{
                                $currentFalseNumbers[] = $singleFalseNumber;
                                $generatedFalseNumber ++;
                                break;
                            }
                        }
                        else{
                            $countForFalseNo = $isFalseNumberEntered ? $countForFalseNo + 1 : $countForFalseNo;
                            $countForFalseString = $isFalseStringEntered ? $countForFalseString + 1 : $countForFalseString;
                            $singleFalseNumber = "";
                            $positionForFalseNo = 0;
                            $positionForFalseString = 0;
                        }
                    }
                }
            }
            if($generatedFalseNumber != $totalNoOfFalseNumber){
                throw new ExamControllerException(ExamControllerException::NO_FALSE_NUMBERS_IN_CONFIGURATION," No False Number in The Configuration. Plese Add False Numbers In The Configuration");
            }
            if ($enableReShuffleInSubjects){
                $subjectWiseArray = [];
                $assignedFalseNumber = [];
                foreach($students as $student){
                    $subjectWiseArray[$student->subjectId][] = $student->falseNo;
                }
                foreach($subjectWiseArray as $subjectId => $subjectWiseFalseNo){
                    shuffle($subjectWiseArray[$subjectId]);
                }
                foreach($students as $student){
                    $student->falseNo = array_shift($subjectWiseArray[$student->subjectId]);
                }
            }
            return($students);
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * generate Random String
     * @author Krishnajith
     * @param  $minimumFalseNumberRange , $maximumFalseNumberRange
     * @throws ExamControllerException
     */
    function generateRandomString($countOfFalseNumberString,$length){
        try{
            // for ($i = 0; $i <= $countOfFalseNumberString ; $i++) {
            //     $singleFlNoString =  substr(str_shuffle(str_repeat($x = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);
            //     $falseNoStringArray[] = $singleFlNoString;
            // }
            $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            $charactersLength = strlen($characters);
            $falseNoStringArray = [];
            for ($i = 0; $i < $countOfFalseNumberString; $i++) {
                $randomString = '';
                for ($j = 0; $j < $length; $j++) {
                    $randomString .= $characters[random_int(0, $charactersLength - 1)];
                }
                $falseNoStringArray[] = $randomString;
            }
            return $falseNoStringArray;
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * generate Numbers
     * @author Krishnajith
     * @param  $minimumFalseNumberRange , $maximumFalseNumberRange
     * @throws ExamControllerException
     */
    public function generateNumbers($minimumFalseNumberRange,$maximumFalseNumberRange,$falseNoNumofdigits,$shuffleAllExams = false){
        try{
            $numbers = range($minimumFalseNumberRange, $minimumFalseNumberRange + $maximumFalseNumberRange);
            if($shuffleAllExams){
                shuffle($numbers);
            }
            foreach($numbers as $number){
                $paddedNumbers[] = str_pad($number,$falseNoNumofdigits,'0',STR_PAD_LEFT);
            }
            return $paddedNumbers;
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get All False Numbers
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function getAllFalseNumbers(){
        try{
            $falseNumberArray = [];
            $query = "SELECT
                        falseNo AS falseNo
                    FROM 
                        `ec_student_assessment_registration` 
                    WHERE 
                        falseNo IS NOT NULL";
            $falseNumbers = $this->executeQueryForList($query);
            foreach($falseNumbers as $falseNumberObj){
                $falseNumberArray[] = $falseNumberObj->falseNo;
            }
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($falseNumberArray);
    }
     /**
     * get False Number Format
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function getFalseNumberFormat($searchRequest){
        try{
            $settings = $searchRequest->settings;
            $student = $searchRequest->student;
            $falseNoNumofdigits = $settings->falseNoNumofdigits;
            $minimumFalseNumberRange = $settings->falseNoTotalRangeFrom;
            $maximumFalseNumberRange = $settings->falseNoTotalRangeTo;
            $CountOfFlNoByRange =  $maximumFalseNumberRange - $minimumFalseNumberRange;
            $configuration = $settings->properties->configuration;
            $falseNumberFormat = [];
            for($i=1;$i<=$falseNoNumofdigits;$i++){
                if($configuration[$i]->type == 'constant'){
                    $falseNumberFormat[$i] = $configuration[$i]->text;
                }
                else if($configuration[$i]->type == 'semesterNumber'){
                    $semeserName = $student->academicTermName;
                    $semeserNumber = substr($semeserName, -1);
                    $falseNumberFormat[$i] = $semeserNumber;
                }
                else if($configuration[$i]->type == 'falseNumber'){
                    $falseNumberFormat[$i] = "FalseNumber";
                }
                else if($configuration[$i]->type == 'currentYearLastDigit'){
                    $yearLastDigit = $this->getCurrentYearLastDigit();
                    $falseNumberFormat[$i] = $yearLastDigit;
                }
                else if($configuration[$i]->type == 'currentYearSecondLastDigit'){
                    $yearSecondLastDigit = $this->getCurrentYearSecondLastDigit();
                    $falseNumberFormat[$i] = $yearSecondLastDigit;
                }
                else if($configuration[$i]->type == 'falseNumberString'){
                    $falseNumberFormat[$i] = "FalseNumberString";
                }
                else if($configuration[$i]->type == 'departmentCode'){
                    $falseNumberFormat[$i] = $student->departmentCode;
                }
                else if($configuration[$i]->type == 'examSlot'){
                    $falseNumberFormat[$i] = $student->subjectSlot;
                }
                else if($configuration[$i]->type == 'courseType'){
                    if($student->courseTypeName == CourseTypeConstants::UG ){
                        $courseType = "U";
                    }
                    elseif($student->courseTypeName == CourseTypeConstants::PG ){
                        $courseType = "P";
                    }
                    $falseNumberFormat[$i] = $courseType;
                }
                else if($configuration[$i]->type == 'examType'){
                    if($student->examType == ExamRegistrationTypeConstants::REGULAR ){
                        $examType = "R";
                    }
                    elseif($student->examType == ExamRegistrationTypeConstants::SUPPLEMENTARY ){
                        $examType = "S";
                    }
                    elseif($student->examType == ExamRegistrationTypeConstants::IMPROVEMENT ){
                        $examType = "I";
                    }
                    $falseNumberFormat[$i] = $examType;
                }
                else if($configuration[$i]->type == 'examDateDigit'){
                    $examDate = $student->assessmentDate ? date('d', strtotime($student->assessmentDate)) : '00';
                    $falseNumberFormat[$i] = $examDate;
                }
                else if($configuration[$i]->type == 'examMonthDigit'){
                    $examDate = $student->assessmentDate ? date('m', strtotime($student->assessmentDate)) : '00';
                    $falseNumberFormat[$i] = $examDate;
                }
                
            }
            return $falseNumberFormat;
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
     /**
     * Check alpha numeric code already exist
     * @throws ExamControllerException
     */
    public function checkAlphaNumericCodeAlreadyExist($numericCode){
        try{
            $query = "SELECT
                        properties ->> '$.alphaNumericCode' AS alphaNumericCode
                    FROM 
                        `ec_student_assessment_registration` 
                    WHERE 
                        properties ->> '$.alphaNumericCode' = '$numericCode'";
            $result = $this->executeQueryForObject($query);
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $result;
    }
    
    /**
     * Check if False Number code already exist
     * @throws ExamControllerException
     */
    public function checkFalseNumberAlreadyExist($falseNo){
        try{
            $query = "SELECT
                        falseNo AS falseNo
                    FROM 
                        `ec_student_assessment_registration` 
                    WHERE 
                        falseNo = '$falseNo'";
            $result = $this->executeQueryForObject($query);
        }
        catch(\Exception $e){
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return $result;
    }
     /**
     * get FalseNumber Batch Report with packet
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function getFalseNumberBatchReportWithPacket($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        try{
            if(empty($searchRequest->examRegistrationId)){
                throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invailed Request For False Number");
            }
            $response = new \stdClass;
            $request = new \stdClass;
            $request->examRegistrationId = $searchRequest->examRegistrationId;
            $request->groupId = $searchRequest->groupId;
            $request->academicPaperSubjectId = $searchRequest->academicPaperSubjectId;
            $request->assessmentId = $searchRequest->assessmentId;
            $request->assessmentId = stripslashes($searchRequest->assessmentId);
            $request->packetNo = $searchRequest->packetNo;
            $request->reportType = $searchRequest->reportType;
            $falsenemberGeneratedStudents = $this->getFalseNumberGeneratedStudentDetails($request);
            if(empty($falsenemberGeneratedStudents)){
                $response->isFalseNumberNotGenerated = true;
            }
            else{
                foreach( $falsenemberGeneratedStudents as $student){
                    $customFields = AmsCustomFieldsService::getInstance()->getAmsCustomFieldValue(AmsCustomFieldsEntities::STUDENT, $student->studentId, []);
                    if( $customFields ){
                        $student->ktuCode = CommonExamService::getInstance()->getCustomFieldObjectList($customFields)->studentData->KTU_CODE;
                    }
                }
                $response->isFalseNumberNotGenerated = false;
                $additionalDetails = new \stdClass; 
                $additionalDetails->collegeData = CommonExamService::getInstance()->getCollegeDetails();
                $requestForExamRegistration = new SearchExamRegistrationRequest;
                $requestForExamRegistration->id = $request->examRegistrationId;
                $examRegistration = ExamRegistrationService::getInstance()->searchExamRegistration($requestForExamRegistration);
                $requestForsubject = new \stdClass; 
                $requestForsubject->examRegistrationId = $request->examRegistrationId;
                $requestForsubject->academicPaperSubjectIds = $request->academicPaperSubjectId;
                $requestForsubject->assessmentId = $request->assessmentId;
                $subjectDetails = ExamRegistrationSubjectService::getInstance()->getExamregistrationSubjectDetails($requestForsubject);
                
                if(!empty($examRegistration)){
                    $additionalDetails->examRegistrationName = reset($examRegistration)->name;
                    $additionalDetails->examRegistrationType = reset($examRegistration)->type; 
                }
                if(!empty($subjectDetails)){
                    $additionalDetails->subjectName = $subjectDetails->subjectName;
                    $additionalDetails->subjectCode = $subjectDetails->subjectCode;
                }
                $templateName = 'BatchWiseFalseNumberReportWithPacket';
                $responseHtml = TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/FalseNumberReports/$templateName.twig"), [ 'students'=>$falsenemberGeneratedStudents ,'additionalDetails'=>$additionalDetails]);
                $prtContent = NULL;
                $prtContent .= '<html><head>';
                $prtContent .= "";
                $prtContent .= '</head><title>False Number Generated List</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' => "5mm",
                    'margin-left' => "10mm",
                    'margin-right' => "10mm",
                    'margin-bottom' => "5mm",
                    // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                    'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
                );
            $response->dispalyHtmlData = $responseHtml;
            $response->printData = PdfUtil::renderPdf($prtContent, $options);
            }
            return  $response;
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
    }
    
    /**
     * get All False Numbers by student and term
     * @author Krishnajith
     * @param  $searchRequest
     * @throws ExamControllerException
     */
    public function getAllFalseNumberByStudentsAndTerm($searchRequest){
        $searchRequest = $this->realEscapeObject($searchRequest);
        $falseNumberGeneratedStudentTerm = [];
        try{
            if(!empty($searchRequest->academicTermId)) {
                $academicTermIdString = is_array($searchRequest->academicTermId) ? "'" . implode("','",$searchRequest->academicTermId) . "'" : "'".$searchRequest->academicTermId."'";
                $whereQuery .= " AND eerb.properties ->> '$.academicTermId' IN ( $academicTermIdString )";
            }
            if(!empty($searchRequest->studentId)) {
                $studentIdString = is_array($searchRequest->studentId) ? "'" . implode("','",$searchRequest->studentId) . "'" : "'".$searchRequest->studentId."'";
                $whereQuery .= " AND esar.student_id IN ( $studentIdString )";
            }
          
            $query = "SELECT DISTINCT
                        esar.falseNo AS falseNo,
                        esar.student_id AS studentId,
                        eerb.properties ->> '$.academicTermId' AS academicTermId
                    FROM
                        ec_student_assessment_registration esar
                    INNER JOIN am_assessment aa ON
                        esar.am_assessment_id = aa.id  
                    INNER JOIN ec_exam_registration_subject eers ON
                        aa.id = eers.am_assessment_id
                    INNER JOIN ec_exam_registration_batch eerb ON
                        eers.ec_exam_registration_batch_id = eerb.id
                    WHERE 
                        aa.properties_value ->>'$.assessmentDate' IS NOT NULL 
                        AND (esar.properties ->> '$.syllabusSubType' != 'MOOC' OR esar.properties ->> '$.syllabusSubType' IS NULL)
                        AND esar.falseNo IS NOT NULL 
                        AND esar.properties ->> '$.registrationStatus' = 'REGISTERED'
                        AND esar.properties ->> '$.feeStatus' = 'PAID' ";
            $falseNumberGeneratedStudents =  $this->executeQueryForList($query.$whereQuery);
            foreach($falseNumberGeneratedStudents as $student){
                $falseNumberGeneratedStudentTerm[$student->studentId.$student->academicTermId] = $student->falseNo;
            }
        }
        catch(\Exception $e)
        {
            throw new ExamControllerException($e->getCode(),$e->getMessage());
        }
        return($falseNumberGeneratedStudentTerm);
    }
    
  
    /**
     * Embed QR codes with false numbers on answer sheet
     *
     * @param object $request
     * @return base64 encoded pdf
     * @author Renjith Roy <renjithroy@linways.com>
     */
    
     public function embedQRAnswerSheet($request)
     {
        $request = $this->realEscapeObject($request);
        $format = $request->format;
        $totalCopies = (int)$request->totalCopies;
        $MAX_COPIES = 100;
        if(empty($format) || empty($totalCopies)){
            throw new ExamControllerException(ExamControllerException::EMPTY_PARAMETERS,"Invalid Request");
        }
        
        if($totalCopies < 1 || $totalCopies > $MAX_COPIES){
            throw new ExamControllerException(ExamControllerException::INVALID_PARAMETERS,"Invalid Total Copies");
        }
        
        // Temporary pdf files maybe left behind by wkhtmltopdf if it is not properly terminated (because of issues like memory exhaustion)
        $this->cleanUpTmpFiles();
        
        try{
            $baseUrl = "http://".$_SERVER['HTTP_HOST'];
            $collegeCode = $GLOBALS['COLLEGE_CODE'];
            
            // Set answer sheet images and total copies required
            $answerSheetImage1 = $baseUrl."/libcommon/images/college/$collegeCode/AnswerSheetTemplates/$format/Page1.jpg";
            $answerSheetImage2 = $baseUrl."/libcommon/images/college/$collegeCode/AnswerSheetTemplates/$format/Page2.jpg";
            
            $twigFunctions = [
                new TwigFunction('getQr', [TwigCustomFunctions::class, 'getQr']),
            ];
            
            $answerSheetHTMLWithQRs = [];
            
            for($i = 0; $i < $totalCopies; $i++) {
                
                // Each iteration will generate a set of two different answer sheets with same qr code with a unique false no
                $falseNo = $this->generateUniqueFalseNo();
                
                // Render answer sheet 1 with qr codes
                $answerSheetHTMLWithQRs[] = 
                TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/answerSheet/$format/Page1.twig"), [ 'answerSheetImage'=>$answerSheetImage1 ,'falseNo'=>$falseNo ], null, $twigFunctions);
                
                // Render answer sheet 2 with qr codes
                $answerSheetHTMLWithQRs[] = 
                TwigRenderer::renderTemplateFileToHtml(realpath(DOCUMENT_ROOT."../examcontroller-api/src/com/linways/web/templates/answerSheet/$format/Page2.twig"), [ 'answerSheetImage'=>$answerSheetImage2 ,'falseNo'=>$falseNo], null, $twigFunctions);
            }
            
            if(empty($answerSheetHTMLWithQRs)){
                throw new ExamControllerException(ExamControllerException::ANSWER_SHEET_GENERATION_FAILED,"Failed to generate answer sheet");
            }
            
            return $this->generateAnswerSheetPDF($answerSheetHTMLWithQRs);
                    
        } catch (\Exception $e) {
            throw new ExamControllerException($e->getCode(), $e->getMessage());
        }
     }
     
     /**
      * Generate answer sheet pdf from html elements array
      *
      * @param array $answerSheetHTMLWithQRs
      * @return base64 encoded pdf
      * @author Renjith Roy <renjithroy@linways.com>
      */
     private function generateAnswerSheetPDF($answerSheetHTMLWithQRs){
        try{
            ob_clean();
            $options = array(
                'orientation' => "portrait",
                'page-width'     => "420mm", // A3 size
                'page-height'    => "297mm", // A3 size
                'dpi'         => 400,
                'margin-bottom' => "0",
                'margin-top' => "0",
                'margin-left' => "0",
                'margin-right' => "0",
                'disable-smart-shrinking',
                // 'binary' => "/usr/local/bin/wkhtmltopdf", // For Mac
                'user-style-sheet' => realpath(DOCUMENT_ROOT . "/libcommon/bootstrap/css/bootstrap.min.css")
            );
            
            $pdf = new Pdf($options);
            $pdf->ignoreWarnings = true; 
            
            foreach($answerSheetHTMLWithQRs as $answerSheetHTML){
                $pdf->addPage($answerSheetHTML);
            }
            
            $content = $pdf->toString();
            // Check if there are any errors in the PDF generation
            if($pdf->getError()){
                throw new ExamControllerException(ExamControllerException::PDF_GENERATION_FAILED,"Failed to generate answer sheet");
            }
            
            if(!$content){
                throw new ExamControllerException(ExamControllerException::PDF_GENERATION_FAILED,"Failed to generate answer sheet");
            }
                        
            return base64_encode($content);
        } catch (\Exception $e) {
            throw new ExamControllerException($e->getCode(), $e->getMessage());
        } finally{
            $this->cleanUpTmpFiles();
        }
     }
     
     /**
      * Clean up all files whose name includes 'wkhtmlto' in tmp directory
      *
      * @author Renjith Roy <renjithroy@linways.com>
      */
     private function cleanUpTmpFiles(){
        $tmpDir = sys_get_temp_dir();
        $files = glob($tmpDir . '/*wkhtmlto*');
        foreach($files as $file){
            if(is_file($file)){
                unlink($file);
            }
        }
     }
     
     /**
      * Generate unique false no
      *
      * @return string
      * @author Renjith Roy <renjithroy@linways.com>
      */
     public function generateUniqueFalseNo() {
        
        try{
            // Generate a 10 digit random hex string
            $falseNo = bin2hex(random_bytes(5));
            
            // Check if false no already exists
            $falseNoExists = $this->executeQueryForObject("SELECT id FROM ec_answer_sheet_false_no WHERE false_no = '$falseNo'");
            
            // If false no already exists, recursively call the function until a unique false no is generated
            if(!empty($falseNoExists)) {
                return $this->generateUniqueFalseNo();
            }
            
            $id = SecurityUtils::getRandomString();
            // Store each generated false no in database to avoid duplicates
            $this->executeQuery("INSERT INTO ec_answer_sheet_false_no (id, false_no) VALUES ('$id', '$falseNo')");
            
            return $falseNo;
        } catch (\Exception $e) {
            throw new ExamControllerException($e->getCode(), $e->getMessage());
        }
     }
    
     /**
      * Get answer sheet formats
      *
      * @return array
      * @author Renjith Roy <renjithroy@linways.com>
      */
     public function getAnswerSheetFormats(){
        try{
            $query = "SELECT value AS id, name AS text FROM ec_answer_sheet_format";
            return $this->executeQueryForList($query);
        } catch (\Exception $e) {
            throw new ExamControllerException($e->getCode(), $e->getMessage());
        }
     }
    
     /**
      * Get base64 encoded image
      *
      * @param string $imageUrl
      * @return string
      * @author Renjith Roy <renjithroy@linways.com>
      */
     public function getBase64Image($imageUrl) {
        try{
            $imageData = file_get_contents($imageUrl);
            $base64 = base64_encode($imageData);
            $mimeType = 'image/jpeg';
            return "data:$mimeType;base64,$base64";
        } catch (\Exception $e) {
            throw new ExamControllerException($e->getCode(), $e->getMessage());
        }
    }
 
}