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 / 33
CRAP
0.00% covered (danger)
0.00%
0 / 894
AssessmentComponentRuleService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 33
27722.00
0.00% covered (danger)
0.00%
0 / 894
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 __clone
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 1
 getInstance
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 5
 saveAssessmentComponentRule
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 20
 updateAssessmentComponentRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 14
 createAssessmentComponentRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 getAssessmentComponentRule
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 29
 getRuleAssignedForABatch
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 22
 assignAssessmentComponentRuleToBatches
0.00% covered (danger)
0.00%
0 / 1
380.00
0.00% covered (danger)
0.00%
0 / 135
 checkExamMarkEnteredForAssigningBatch
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 25
 updateExamsForBatch
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 23
 createNewExamsForBatch
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 25
 updateInternalMarkSettings
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 insertInternalMarkSettings
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 calculateRuleForABatch
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 45
 getStudentsForRuleCalculation
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 10
 calculateRuleForEachStudent
0.00% covered (danger)
0.00%
0 / 1
992.00
0.00% covered (danger)
0.00%
0 / 133
 getStudentMarkDetails
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 17
 getAttendancePercent
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 35
 calculateIndividualRule
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 30
 calculateDetailedRuleForStudent
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 52
 calculateRulePseudoSubject
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 44
 getStudentChildExamTypeMarksByExamTypeId
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 19
 getStudentMarksbyRequest
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 18
 getApproveExamMarkDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getApproveStatusExamMarkDetails
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getBatchAsignedForComponent
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getRuleAssignedForABatchByRuleId
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 23
 updateBatchAssessmentComponentRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getDistinctSemetersFromComponentAssignedBatches
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getComponentDetailsByBatchIdsAndSemIds
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 revisedInternalMarkCalculation
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 20
 calculateRuleForABatchAllSubjects
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 43
<?php
namespace com\linways\core\ams\professional\service;
use stdClass;
use com\linways\core\ams\professional\logging\Events;
use com\linways\core\ams\professional\util\CommonUtil;
use com\linways\core\ams\professional\logging\AMSLogger;
use com\linways\core\ams\professional\service\ExamService;
use com\linways\core\ams\professional\service\MarkService;
use com\linways\core\ams\professional\dto\SettingsConstents;
use com\linways\core\ams\professional\service\CommonService;
use com\linways\core\ams\professional\logging\entities\Batch;
use com\linways\core\ams\professional\logging\entities\Staff;
use com\linways\core\ams\professional\service\StudentService;
use com\linways\core\ams\professional\service\SubjectService;
use com\linways\core\ams\professional\service\SubBatchService;
use com\linways\core\ams\professional\service\AttendanceService;
use com\linways\core\ams\professional\constant\SettingsConstants;
use com\linways\core\ams\professional\dto\AssessmentComponentRule;
use com\linways\core\ams\professional\request\SearchSubjectRequest;
use com\linways\core\ams\professional\request\GetExamDetailsRequest;
use com\linways\core\ams\professional\exception\ProfessionalException;
use com\linways\core\ams\professional\request\CalculateAssessmentRuleRequest;
use com\linways\core\ams\professional\request\ComponentRuleExamCreateRequest;
use com\linways\core\ams\professional\request\GetRuleAssignedForABatchRequest;
use com\linways\core\ams\professional\request\GetAssessmentComponentRuleRequest;
use com\linways\core\ams\professional\mapper\AssessmentComponentRuleServiceMapper;
use com\linways\core\ams\professional\request\AssignAssessmentComponentRuleToBatchRequest;
use com\linways\core\ams\professional\request\CalculateComponentRuleForEachStudentRequest;
class AssessmentComponentRuleService extends BaseService
{
    // /Condition 1 - Presence of a static member variable
    private static $_instance = null;
    
    // /Condition 2 - Locked down the constructor
    private function __construct()
    {
        $this->mapper = AssessmentComponentRuleServiceMapper::getInstance()->getMapper();
        $this->logger = AMSLogger::getLogger();
    }
    // Prevent any oustide instantiation of this class
    
    // /Condition 3 - Prevent any object or instance of that class to be cloned
    private function __clone()
    {}
    // Prevent any copy of this object
    
    // /Condition 4 - Have a single globally accessible static method
    public static function getInstance()
    {
        if (!is_object(self::$_instance)) // or if( is_null(self::$_instance) ) or if( self::$_instance == null )
            self::$_instance = new self();
        
        return self::$_instance;
    }
    /**
     * save assessment component rule
     * @param AssessmentComponentRule $request
     * @return null
     */
    public function saveAssessmentComponentRule(AssessmentComponentRule $request)
    {
        $request = $this->realEscapeObject($request);
        //Name should not be empty
        if(empty($request->name))
            throw new ProfessionalException(ProfessionalException::INVALID_ASSESSMENT_COMPONENT_NAME,"Name cannot be empty");
        //Rule should not be empty
        if(empty($request->rule))
            throw new ProfessionalException(ProfessionalException::INVALID_ASSESSMENT_COMPONENT_RULE,"Invalid rule");
        try{
            //Checking id in request.If yes update rule else create new rule
            if($request->ruleId)
            {   
                $this->updateAssessmentComponentRule($request);
            } else 
            {
                $this->createAssessmentComponentRule($request);
            }
        }catch(\Exception $e)
        {
            error_log("CODE :".$e->getCode()." MESSAGE :".$e->getMessage());
            throw new ProfessionalException(ProfessionalException::ERROR_ASSESSMENT_COMPONENT_RULE_CREATE,"Error saving internal marks component rule");
        }
    }
    /**
     * update assessment component rule
     * @param AssessmentComponentRule $request
     * @return null
     */
    private function updateAssessmentComponentRule(AssessmentComponentRule $request)
    {
        $request = $this->realEscapeObject($request);
        $query = "UPDATE assessment_component_rule SET name='$request->name',rule='".(json_encode($request->rule))."',updated_by='$request->updatedBy',updated_date=UTC_TIMESTAMP() WHERE id='$request->ruleId'";  
        
        try{
            $this->executeQuery($query);
            AMSLogger::log_info($this->logger,Events::INTERNAL_MARKS_COMPONENT_UPDATED, [
                "adminID" => $request->updatedBy,
                "ruleID" => $request->ruleId
                ]);
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * create new assessment component rule
     * @param AssessmentComponentRule $request
     * @return null
     */
    private function createAssessmentComponentRule(AssessmentComponentRule $request)
    {
        $query = "INSERT INTO assessment_component_rule (name,rule,created_by,created_date,updated_by,updated_date) VALUES ('$request->name','".(json_encode($request->rule))."','$request->createdBy',UTC_TIMESTAMP(),'$request->updatedBy',UTC_TIMESTAMP())";
        try{
            $request->ruleId = $this->executeQueryForObject($query,true);
            AMSLogger::log_info($this->logger,Events::INTERNAL_MARKS_COMPONENT_CREATED, [
                "adminID" => $request->createdBy,
                "ruleID" => $request->ruleId
                ]);
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get assessment rule with or without assigned batches
     * @param GetAssessmentComponentRuleRequest $request
     * @return AssessmentComponentRule $response
     */
    public function getAssessmentComponentRule(GetAssessmentComponentRuleRequest $request)
    {
        $request = $this->realEscapeObject($request);
        $condQuery = "";
        $batchesFields = "";
        $batchesJoinQuery = "";
        if(!empty($request->ruleId))
        {
            $condQuery .= " AND acr.id='$request->ruleId'";
        }
        if(!empty($request->includeAssignedBatches))
        {
            $batchesFields .= ",acrb.id AS assessment_component_rule_assigned_batches_id,acrb.batch_id,acrb.sem_id,acrb.rule as assignedRule";
            $batchesJoinQuery .= " LEFT JOIN assessment_component_rule_assigned_batches acrb ON acr.id=acrb.assessment_component_rule_id ";
        }
        $query = "SELECT acr.id,acr.name,acr.rule$batchesFields FROM assessment_component_rule acr $batchesJoinQuery WHERE 1=1 $condQuery";
        try{
            $response = $this->executeQueryForList($query,$this->mapper[AssessmentComponentRuleServiceMapper::GET_ASSESSMENT_COMPONENT_RULE]);
            foreach($response as $key => $rule)
            {
                $rule->rule = json_decode($rule->rule);
                $response [$key] = $rule;
            }
            return $response;
        }catch(\Exception $e)
        {
            error_log("CODE :".$e->getCode()." MESSAGE :".$e->getMessage());
            throw new ProfessionalException(ProfessionalException::ERROR_FETCHING_ASSESSMENT_COMPONENT_RULE,"Cannot fetch rule! Please contact administrator");
        }
    }
    public function getRuleAssignedForABatch(GetRuleAssignedForABatchRequest $request)
    {
        $request = $this->realEscapeObject($request);
        $query = "SELECT acr.id,acr.name,acrb.batch_id as batchId,acrb.sem_id as semId,acrb.rule,acrb.subjectwise_rule as subjectWiseRule
                    FROM    
                    assessment_component_rule_assigned_batches acrb
                    INNER JOIN 
                    assessment_component_rule acr ON acrb.assessment_component_rule_id = acr.id
                    WHERE
                    acrb.batch_id = '$request->batchId' AND acrb.sem_id = '$request->semesterId';";
        try{
            $response = $this->executeQueryForObject($query);
            if(empty($response)){
                return null;
            }
            $response->rule = json_decode($response->rule);
            $response->subjectWiseRule = json_decode($response->subjectWiseRule);
            return $response;        
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * assign component rule to batches
     * @param AssignAssessmentComponentRuleToBatchRequest $request
     * @return null
     */
    public function assignAssessmentComponentRuleToBatches(AssignAssessmentComponentRuleToBatchRequest $request)
    {
        $request = $this->realEscapeObject($request);
        $failedBatches = array();//batches which failed to assign rule
        //Atleast one batch should be selected
        if(count($request->batches) === 0)
        {
            throw new ProfessionalException(ProfessionalException::INVALID_BATCH_ID,"Please select atleast one batch");
        }
        try{
            //Get component rule
            $getRuleRequest = new GetAssessmentComponentRuleRequest();
            $getRuleRequest->ruleId = $request->ruleId;
            $getRuleRequest->includeAssignedBatches = false;
            $ruleComponent = $this->getAssessmentComponentRule($getRuleRequest)[0];
        }catch(\Exception $e)
        {
            error_log("CODE :".$e->getCode()." MESSAGE :".$e->getMessage());
            throw new ProfessionalException($e->getCode(),"Cannot assign rule to batches! Please contact administrator");
        }
        //Assign table for batches assigned to a rule.Rule will be stored here.Will execute for all batches which successfully created or updated exams with the given rule
        $query = "INSERT INTO assessment_component_rule_assigned_batches (assessment_component_rule_id,batch_id,sem_id,rule,subjectwise_rule,created_by,created_date,updated_by,updated_date) VALUES ";
        $valuesQuery = "";
        
        //Loop through batches and assign rule to each batch
        foreach($request->batches as $batch)
        {
            //Subjectwise rule object.If rule may be seperate for each subjects in future.So we save rule against each subject for individual rule calculation.
            $subjectWiseRule = [];
            //Flag for checking failed batch.If true no need to execute below codes.
            $skipBatch = false;
            //#################################################################################################
            
                // foreach($ruleComponent->rule->examTypes as $examType) {
                    //Check if mark entered for exam of a batch in a sem for an exam type.If mark entered for any one exam,rule cannot be changed for that batch.
                    //
                    // if($this->checkExamMarkEnteredForAssigningBatch($batch->batchId,$batch->semesterId,$examType))
                    // {
                    //     $failedBatches [] = $batch;
                    //     $skipBatch = true;
                    //     break;
                    // }
                // }
                // if($skipBatch)
                // {
                    // continue;
                // }
            
            //#################################################################################################
            try{
                $this->executeQuery("START TRANSACTION");
                foreach($ruleComponent->rule->examTypes as $examType) {
                    foreach($examType->subjectCategories as $subjectCategory) {
                        //Unset the create exam component request at beginning of loop
                        $componentRuleExamCreateRequest = null;                        
                            
                        //Create exam request for batch in a sem for an exam type
                        $componentRuleExamCreateRequest = new ComponentRuleExamCreateRequest();
                        $componentRuleExamCreateRequest->batchId = $batch->batchId;
                        $componentRuleExamCreateRequest->semesterId = $batch->semesterId;
                        $componentRuleExamCreateRequest->examName = $subjectCategory->examName;
                        $componentRuleExamCreateRequest->maxMark = $subjectCategory->maxMark;
                        $componentRuleExamCreateRequest->examTypeId = $examType->examTypeId;
                        $componentRuleExamCreateRequest->subjectCategoryId = $subjectCategory->subjectCategoryId;
                        $componentRuleExamCreateRequest->createdBy = $request->createdBy;
                        // Update the Exam Marks for previously created Exams
                        $componentRuleExamCreateRequest->updateExamMarks = $request->updateExamMarks;
                        //Update already created exams for subjects in an exam type in a batch and its semester with new rule and name
                        $this->updateExamsForBatch($componentRuleExamCreateRequest);
                        //Create exams for other subjects
                        $this->createNewExamsForBatch($componentRuleExamCreateRequest);  
                        
                        $getSubjectsRequest = new SearchSubjectRequest();
                        $getSubjectsRequest->batchID = $batch->batchId;
                        $getSubjectsRequest->semID = $batch->semesterId;
                        $getSubjectsRequest->subjectCategoryIdList = [$subjectCategory->subjectCategoryId];
                        $subjects = SubjectService::getInstance()->searchSubjects($getSubjectsRequest)->subjects;
                        unset($getSubjectsRequest);
                        $ruleComponentExamTypes = $ruleComponent->rule->examTypes;
                        foreach($subjects as $subject)
                        {
                            $subCatId = $subject->subjectCatId;
                            if(!$subjectWiseRule[$subject->id])
                            {
                                $subjectWiseRule[$subject->id] = new \StdClass();
                                $subjectWiseRule[$subject->id]->examTypes = [];
                                $subjectWiseRule[$subject->id]->ruleCalculate = in_array($subjectCategory->subjectCategoryId,$ruleComponent->rule->subjectCategoryHavingRuleCalculation);
                                $subjectWiseRule[$subject->id]->rules = $ruleComponent->rule->rules;
                                $subjectWiseRule[$subject->id]->maxInternalMarks = $ruleComponent->rule->totalMaxInternalMark->{$subjectCategory->subjectCategoryId};
                                if($subjectWiseRule[$subject->id]->ruleCalculate){
                                    $subjectWiseRule[$subject->id]->subjectCategoryHavingRuleCalculation[] = $subjectCategory->subjectCategoryId;
                                }
                                else{
                                    $subjectWiseRule[$subject->id]->subjectCategoryHavingRuleCalculation = [];
                                }
                            }
                            $subjectWiseRule[$subject->id]->examTypes[$examType->examTypeId] = (object) ["examName" => $subjectCategory->examName,"maxMark" => $subjectCategory->maxMark,"convertedMaxMark" => $subjectCategory->convertedMaxMark];
                            $subjectWiseRuleExamType = $subjectWiseRule[$subject->id]->examTypes[$examType->examTypeId];
                            $subjectWiseRuleExamType->markType = $subjectCategory->markType?$subjectCategory->markType:'1'; 
                            if($subjectCategory->markType == '2'){
                                $subjectWiseRuleExamType->markRule = $subjectCategory->markRule;
                            }
                            $subExamType = new stdClass();
                            $subExamType->uniqueId = $examType->uniqueId;
                            $subExamType->examTypeId = $examType->examTypeId;
                            $subExamType->subjectCategories = [];
                            
                            $catExist = false;
                            foreach($examType->subjectCategories as $indx =>$subCat){
                                if($subCat->subjectCategoryId == $subCatId){
                                    $catExist = true;
                                    $subExamType->subjectCategories[] = $subCat;
                                }
                                else{
                                    continue;
                                }
                            }
                            if($catExist != false && $subExamType->subjectCategories != []){
                                $subjectWiseRule[$subject->id]->ruleExamTypes[] = $subExamType;
                            }
                            
                            
                            //$subjectRuleExamTypes = $ruleComponentExamTypes;
                            // foreach($subjectRuleExamTypes as $key=> $exmTypes){
                            //     $catExist = false;
                            //     foreach($exmTypes->subjectCategories as $indx =>$subCat){
                            //         if($subCat->subjectCategoryId == $subCatId){
                            //             $catExist = true;
                            //             continue;
                            //         }
                            //         else{
                            //             unset($exmTypes->subjectCategories[$indx]);
                            //         }
                            //     }
                            //     if($catExist == false){
                            //         unset($subjectRuleExamTypes[$key]);
                            //     }
                            // }
                            // $subjectWiseRule[$subject->id]->ruleExamTypes = $subjectRuleExamTypes;
                            // unset($subjectRuleExamTypes);
                        }
                        unset($subjects);
                    }
                    foreach($ruleComponent->rule->totalMaxInternalMark as $subjectCategoryId => $totalInternalMark) {
                        $internalMarkSettingsRequest = new \StdClass();
                        $internalMarkSettingsRequest->batchId = $batch->batchId;
                        $internalMarkSettingsRequest->semesterId = $batch->semesterId;
                        $internalMarkSettingsRequest->subjectCategoryId = $subjectCategoryId;
                        $internalMarkSettingsRequest->maxInternalMarks = $totalInternalMark;
                        // $this->updateInternalMarkSettings($internalMarkSettingsRequest);
                        $this->insertInternalMarkSettings($internalMarkSettingsRequest);
                        unset($internalMarkSettingsRequest);
                    }
                    unset($subjectCategoryId);
                    unset($totalInternalMark);
                }
                $valuesQuery .= "('$request->ruleId','$batch->batchId','$batch->semesterId','".json_encode($ruleComponent->rule)."','".json_encode($subjectWiseRule)."','$request->createdBy',UTC_TIMESTAMP(),'$request->updatedBy',UTC_TIMESTAMP()),";
                $this->executeQuery("COMMIT");
                AMSLogger::log_info($this->logger,Events::INTERNAL_MARKS_COMPONENT_ASSIGNED_TO_BATCH_SUCCESS, [
                    "adminID" => $request->createdBy,
                    "ruleID" => $request->ruleId,
                    "Batch" => new Batch(["id" => $batch->batchId]),
                    "Semester" => $batch->semesterId
                    ]);
            }catch(\Exception $e)
            {
                $this->executeQuery("ROLLBACK");
                AMSLogger::log_info($this->logger,Events::INTERNAL_MARKS_COMPONENT_ASSIGNED_TO_BATCH_ERROR, [
                    "adminID" => $request->createdBy,
                    "ruleID" => $request->ruleId,
                    "Batch" => new Batch(["id" => $batch->batchId]),
                    "Semester" => $batch->semesterId,
                    "Message" => $e->getMessage()
                    ]);
                $failedBatches [] = $batch;
            }   
            unset($subjectWiseRule);
        }
        
        try{
            if($valuesQuery !== "") {
                $query .= " ".(rtrim($valuesQuery,",")). " ON DUPLICATE KEY UPDATE assessment_component_rule_id = VALUES(assessment_component_rule_id),rule = VALUES(rule),updated_by = VALUES(updated_by),updated_date = VALUES(updated_date),subjectwise_rule = VALUES(subjectwise_rule)";
            
                $this->executeQuery($query);
            }
            return $failedBatches;
        }catch(\Exception $e)
        {
            error_log("CODE :".$e->getCode()." MESSAGE :".$e->getMessage());
            throw new ProfessionalException($e->getCode(),"Cannot assign rule to batches! Please contact administrator");
        }
    }
    private function checkExamMarkEnteredForAssigningBatch($batchId,$semId,$examType)
    {
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $examType = $this->realEscapeObject($examType);
        foreach($examType->subjectCategories as $subjectCategory) {
        
            $query = "SELECT DISTINCT e.examID
                    FROM 
                    student_marks sm
                    INNER JOIN
                    exam e ON sm.examID=e.examID
                    INNER JOIN subjects s ON e.subjectID = s.subjectID
                    WHERE 
                    sm.batchID='$batchId' AND sm.semID='$semId' AND sm.examTypeID='$examType->examTypeId' AND e.examTotalMarks!='$subjectCategory->maxMark' AND s.subjectCatID='$subjectCategory->subjectCategoryId'";
        
            try{
                $examId = $this->executeQueryForList($query);
                if(!empty($examId)) {
                    return true;
                }
            }catch(\Exception $e)
            {
                throw new ProfessionalException($e->getCode(),$e->getMessage());
            }
        }
        return false;
    }  
    
    private function updateExamsForBatch(ComponentRuleExamCreateRequest $request)
    {
        $setCond = "";
        if($request->updateExamMarks){
            $setCond .= "e.examTotalMarks = '$request->maxMark',";
        }
        $query = "UPDATE 
                  exam e
                  INNER JOIN
                  exam_type et ON e.examTypeID=et.typeID
                  INNER JOIN subjects s ON e.subjectID=s.subjectID
                  SET
                  $setCond 
                  e.examName = '$request->examName'
                  WHERE
                  s.subjectCatID='$request->subjectCategoryId' AND
                  e.batchID = '$request->batchId' AND e.semID = '$request->semesterId' AND e.examTypeID = '$request->examTypeId';";
        
        
        
        try{
            $this->executeQuery($query);
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    
    private function createNewExamsForBatch(ComponentRuleExamCreateRequest $request)
    {
        $query = "INSERT INTO exam 
                  (examName,batchID,subjectID,semID,subbatchID,examTotalMarks,examTypeID,examregID,supply_examreg_id,created_by) 
                  SELECT DISTINCT '$request->examName',sbsr.batchID,sbsr.subjectID,sbsr.semID,IFNULL(sbsbs.subbatchID, 0),'$request->maxMark','$request->examTypeId',NULL,NULL,'$request->createdBy'
                  FROM
                    sbs_relation sbsr
                    INNER JOIN subjects s ON sbsr.subjectID=s.subjectID
                  LEFT JOIN subbatch_sbs sbsbs ON
                    sbsr.sbsID = sbsbs.sbsID
                  WHERE
                  s.subjectCatID='$request->subjectCategoryId'
                  AND IFNULL(sbsbs.subbatchID, 0)
                  NOT IN (SELECT IFNULL(sbsbs.subbatchID, 0) FROM
                         exam
                         WHERE
                         batchID = '$request->batchId' AND semID = '$request->semesterId' AND examTypeID = '$request->examTypeId
                         AND (subbatchID = IF(sbsbs.subbatchID IS NULL,0,sbsbs.subbatchID) OR subbatchID=0) AND subjectID = sbsr.subjectID
                    ) AND sbsr.batchID = '$request->batchId' AND sbsr.semID = '$request->semesterId';";
        
        try{
            $this->executeQuery($query);
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * @deprecated
     */
    private function updateInternalMarkSettings($request)
    {
        $query = "UPDATE internal_marks_settings ims inner join subjects s on ims.subjectID=s.subjectID SET ims.maxInternalMarks='$request->maxInternalMarks' WHERE ims.batchID='$request->batchId' AND ims.semID='$request->semesterId' AND s.subjectcatID='$request->subjectCategoryId';";
        try{
            $this->executeQuery($query);
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    private function insertInternalMarkSettings($request)
    {
        $insertInternalMarkSettingsQuery = "INSERT INTO internal_marks_settings (batchID,semID,subjectID,maxInternalMarks) SELECT DISTINCT sbsr.batchID,sbsr.semID,sbsr.subjectID,'$request->maxInternalMarks' FROM sbs_relation sbsr inner join subjects s on sbsr.subjectID=s.subjectID WHERE sbsr.batchID='$request->batchId' AND sbsr.semID='$request->semesterId' and s.subjectcatID='$request->subjectCategoryId' ON DUPLICATE KEY UPDATE maxInternalMarks='$request->maxInternalMarks';";
        try{
            $this->executeQuery($insertInternalMarkSettingsQuery);
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function calculateRuleForABatch(CalculateAssessmentRuleRequest $request)
    {
        $request = $this->realEscapeObject($request);
        //Rule is calculated against a exam in a batch.So these parameters should not be empty.
        if(empty($request->batchId) || empty($request->semesterId) || empty($request->subjectId))
        {
            throw new ProfessionalException(ProfessionalException::INVALID_PARAMETER,"Invalid request given!");
        }
        try{
            //Get student details in the given batch
            $studentDetails = $this->getStudentsForRuleCalculation($request);
            //Get rule assigned for batch in a sem
            $getRuleRequest = new GetRuleAssignedForABatchRequest();
            $getRuleRequest->batchId = $request->batchId;
            $getRuleRequest->semesterId = $request->semesterId;
            $componentRule = $this->getRuleAssignedForABatch($getRuleRequest);   
            $examTypeRules = $componentRule->rule->examTypes;
            $examMarkRules = $componentRule->rule->examMarkRules;
            
            $attendanceRequest = new stdClass();
            $attendanceRequest->ruleBatchId = $request->batchId;
            $attendanceRequest->batchId = $request->batchId;
            $attendanceRequest->ruleSemId = $request->semesterId;
            $attendanceRequest->subjectId = $request->subjectId;
            $attendanceRequest->semId = $request->semesterId;
            $studentAttendanceDetails = AttendanceService::getInstance()->getStudentsAttendanceByRequest($attendanceRequest);
            foreach($studentDetails as $student)
            {
                $studentAttendance = CommonUtil::objArraySearch($studentAttendanceDetails, "studentID", $student->studentID);
                if($studentAttendance->studentID){
                    $student->ATTENDANCE = $studentAttendance->hour_percentage;
                }else{
                    $student->ATTENDANCE = $this->getAttendancePercent($student->studentID,$request->semesterId,$request->subjectId,$request->batchId);
                }
                $calculateRuleForEachStudentRequest = null;
                $calculateRuleForEachStudentRequest = new CalculateComponentRuleForEachStudentRequest();
                $calculateRuleForEachStudentRequest->student = $student;
                $calculateRuleForEachStudentRequest->rule = $componentRule->subjectWiseRule->{$request->subjectId};
                $calculateRuleForEachStudentRequest->semesterId = $componentRule->semId;
                $calculateRuleForEachStudentRequest->subjectId = $request->subjectId;
                $calculateRuleForEachStudentRequest->examTypeRules = $examTypeRules;
                $calculateRuleForEachStudentRequest->batchId = $request->batchId;
                $student->internalMarkDetails = $this->calculateRuleForEachStudent($calculateRuleForEachStudentRequest);
            }
        }catch(\Exception $e)
        {
            throw new ProfessionalException(ProfessionalException::ERROR_CALCULATING_COMPONENT_RULE,"Error in calculating rule!Please contact administrator");
        }
        return ["studentList" => $studentDetails,"rule" => $componentRule->subjectWiseRule->{$request->subjectId},"examMarkRules" =>$examMarkRules];
    }
    private function getStudentsForRuleCalculation(CalculateAssessmentRuleRequest $request)
    {
        try{
            $sortBy = CommonService::getInstance()->getSettings(SettingsConstants::INTERNAL_MARK_COMPONENT_SETTINGS,SettingsConstants::INTERNAL_MARK_COMPONENT_STUDENT_SORT_BY);
            $studentDetails = StudentService::getInstance()->getStudentDetailsByBatchSemIdAndSubbatchId($request->batchId,$request->semesterId,($request->subbatchId?$request->subbatchId:0),$sortBy);
            return $studentDetails;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    private function calculateRuleForEachStudent(CalculateComponentRuleForEachStudentRequest $request)
    {
        $internalMarkDetails = [];
        
        //push each rule calculated mark to $totalInternalMarksArray to calculate total internal mark
        $totalInternalMarksArray = [];
        // $totalInternalMarks = 0;
        $precision = CommonService::getInstance()->getSettings(SettingsConstents::INTERNAL_MARK_SETTINGS,SettingsConstants::MARK_ROUND_PRECISION);
        foreach($request->rule->examTypes as $examTypeId => $examType)
        {
            $request->examTypeId = $examTypeId;
            $markDetails = $this->getStudentMarkDetails($request);
            foreach($markDetails as $key => $markDetail) {
                $examType->maxMark = $markDetail->maxMark;
                $studentRetestMark = new stdClass();
                $ruleMaxMark = 0;
                if( $markDetail->maxMark)
                {
                    if($markDetail->mark > 0)
                    {
                        $normalised = false;
                        if($examType->subjectWiseRuleEnabled == '1'){
                            if($examType->markType == '1'){
                                $markDetail->normalizedMark = round(($markDetail->mark/$markDetail->maxMark) * $examType->convertedMaxMark,$precision);
                                $normalised = true;
                            }
                            if($examType->markType == '2'){
                                $innerRules = $examType->markRule->rule->MARKRULE->innerRules;
                                $markRule = $examType->markRule->rule->MARKRULE->innerRules;
                                foreach($markRule as $markRule){
                                    $maxValue = array_map('floatval',array_column($innerRules,'val1'));
                                    $maxValue = $maxValue[0];
                                    $markPercent = ($markDetail->mark/$markDetail->maxMark)*100;
                                    $norMark = $this->calculateIndividualRule($markPercent,$markRule,true);
                                    if($norMark != NULL){
                                        $normalised = true;
                                        $markDetail->normalizedMark = round($norMark,$precision);
                                        break;
                                    }
                                    //if($ruleMaxMark 
                                    
                                }
                                if(!$normalised){
                                    $markDetail->normalizedMark = 0;
                                    $normalised = true;
                                }
                                //break;
                                
                            }
                        }
                        if(!$normalised){
                            foreach($request->examTypeRules as $markRules){
                                if($markRules->examTypeId == $examTypeId){
                                    foreach($markRules->subjectCategories as $rule){
                                        if($rule->markType == '1' && $rule->subjectCategoryId == $examType->markRule->subjectCategoryId){
                                            continue;
                                        }
                                        if($rule->markType == '2' && $rule->subjectCategoryId == $examType->markRule->subjectCategoryId){
                                            $innerRules = $rule->markRule->rule->MARKRULE->innerRules;
                                            $markRule = $rule->markRule->rule->MARKRULE->innerRules;
                                            foreach($markRule as $markRule){
                                                $maxValue = array_map('floatval',array_column($innerRules,'val1'));
                                                $maxValue = $maxValue[0];
                                                $markPercent = ($markDetail->mark/$markDetail->maxMark)*100;
                                                $norMark = $this->calculateIndividualRule($markPercent,$markRule,true);
                                                if($norMark != NULL){
                                                    $normalised = true;
                                                    $markDetail->normalizedMark = round($norMark,$precision);
                                                    break;
                                                }
                                                //if($ruleMaxMark 
                                                
                                            }
                                            break;
                                            
                                        }
                                    }
                                }
                                if($normalised){
                                    break;
                                }
                            }
                        }
                        if(!$normalised) //for converted mark
                            $markDetail->normalizedMark = round($markDetail->mark/$markDetail->maxMark * $examType->convertedMaxMark,$precision);
                        // else
                        //     $markDetail->normalizedMark = round($norMark,4);
                    }
                    else
                    {
                        $markDetail->normalizedMark = 0;
                        $childMarkRequest = new stdClass();
                        $childMarkRequest->studentID = $request->student->studentID;
                        $childMarkRequest->examTypeId = $request->examTypeId;
                        $childMarkRequest->subjectId = $request->subjectId;
                        $childMarkRequest->semesterId = $request->semesterId;
                        $childMarkRequest->examID = $markDetail->examID;
                        $childMarkRequest->publishByStaff = CommonService::getInstance()->getSettings(SettingsConstents::INTERNAL_MARK_SETTINGS,SettingsConstants::PUBLISH_MARKS_BY_STAFF) === "1";
                        $childMarkRequest->batchId = $request->batchId;
                        $studentRetestMark = $this->getStudentChildExamTypeMarksByExamTypeId($childMarkRequest);
                        if($studentRetestMark)
                        {
                            $markDetail->childMark = $studentRetestMark->mark;
                            $markDetail->childExamID = $studentRetestMark->examID;
                            $markDetail->childExamNormalizedMark = $studentRetestMark->mark > 0 ? round($studentRetestMark->mark/$studentRetestMark->maxMark * $examType->convertedMaxMark,$precision):0; 
                            $markDetail->childAddMarks = $studentRetestMark->addMarks;
                        }
                    }
                }
                if(!$studentRetestMark)
                {
                    $markDetail->childExamID = NULL;
                    $markDetail->childExamNormalizedMark = NULL;
                }
                $internalMarkDetails [$markDetail->examID] = $markDetail;
                $totalInternalMarksArray [$markDetail->examID] = (float)$markDetail->normalizedMark;
            }
            unset($markDetails);
            $request->examTypeId = null;
        }
        if($request->rule->ruleCalculate) {
            foreach($request->rule->rules as $r)
            {
                $internalMarkDetails[$r->code."MARK"] = 0;
                usort($r->innerRules,function ($a,$b) {
                    return $a->val1 > $b->val1;
                });
                $maxValue = array_map('floatval',array_column($r->innerRules,'val1'));
                rsort($maxValue);
                $maxValue = $maxValue[0];
                foreach($r->innerRules as $innerRule)
                {
                    $mark = 0;
                    $mark = $this->calculateIndividualRule($request->student->{$r->code},$innerRule,($innerRule->val2 && $innerRule->val1 == $maxValue));
                    if($mark > $internalMarkDetails[$r->code."MARK"])
                    {
                        $internalMarkDetails[$r->code."MARK"] = $mark;
                    }
                    unset($mark);
                }
                $totalInternalMarksArray [$r->code."MARK"] = (float) $internalMarkDetails[$r->code."MARK"];
                unset($maxValue);
            }
        }
        // total internal marks
        $internalMarkDetails ['totalInternalMarks'] = array_sum($totalInternalMarksArray);
        return $internalMarkDetails;
    }
    private function getStudentMarkDetails(CalculateComponentRuleForEachStudentRequest $request)
    {
        $cond = "";
        $cond .= ($request->batchId)?" AND sm.batchID = $request->batchId ":"";
        $query = 
        "SELECT sm.marksObtained as mark,e.examTotalMarks as maxMark,e.examID,nm.markID as alreadyNormalised,nm.normalisedMark-nm.marksObtained AS addMarks 
            FROM student_marks sm 
            INNER JOIN exam e on sm.examID=e.examID 
            LEFT JOIN normalise_marks nm ON sm.semID=nm.semID AND sm.subjectID=nm.subjectID AND sm.studentID=nm.studentID 
        WHERE sm.semID='$request->semesterId' AND sm.studentID='".$request->student->studentID."' AND  sm.subjectID='$request->subjectId' AND sm.examTypeID='$request->examTypeId' and e.examRegID IS NULL AND e.supply_examreg_id IS NULL $cond";
        try{
            $markDetails = $this->executeQueryForList($query);
            return $markDetails;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    private function getAttendancePercent($studentId,$semesterId,$subjectId,$batchId)
    {
        $studentDetails = StudentService::getInstance()->getStudentDetailsById($studentId);
        $attendanceRule = AttendanceService::getInstance()->getAttendanceRule($batchId, $semesterId);
        $cond=[];
        if(!empty($attendanceRule))
        {
            if($attendanceRule->dateOfjoining==1 && $studentDetails->joiningSemId==$semesterId && $studentDetails->studentJoindate)
            {
                $attendanceRule->classStartsFrom=$studentDetails->studentJoindate;
            }
            
            if($attendanceRule->classStartsFrom && $attendanceRule->classEnds)
            {
                $cond[] = "att.attendanceDate BETWEEN '$attendanceRule->classStartsFrom' AND '$attendanceRule->classEnds'";
            }
            else if($attendanceRule->classStartsFrom)
            {
                $cond[] = "att.attendanceDate >= '$attendanceRule->classStartsFrom'";
            }
            else if($attendanceRule->classEnds)
            {
                $cond[] = "att.attendanceDate <= '$attendanceRule->classEnds'";
            }
        }
        $totalHoursQuery = "SELECT count(att.semID) AS totalHours FROM attendance att, sbs_relation sbsr WHERE att.sbsID = sbsr.sbsID and att.semID = '$semesterId' and att.studentID = '$studentId' and sbsr.subjectID = '$subjectId".(!empty($cond)?"AND ".implode(' AND ', $cond):"");
        $absentHoursQuery = "SELECT count(att.isAbsent) AS totalAbsentHours from attendance att, sbs_relation sbsr where att.semID = '$semesterId' and att.studentID = '$studentId' and att.isAbsent = 1 and att.sbsID = sbsr.sbsID and sbsr.subjectID = '$subjectId".(!empty($cond)?"AND ".implode(' AND ', $cond):"");
        try{
            $totalHours = $this->executeQueryForObject($totalHoursQuery)->totalHours;
            $totalAbsentHours = $this->executeQueryForObject($absentHoursQuery)->totalAbsentHours;
            $attPercentage = (($totalHours) && ($totalAbsentHours >= 0))?(($totalHours - $totalAbsentHours)/$totalHours)*100:0;
            return $attPercentage;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    private function calculateIndividualRule($studentValue,$innerRule,$isMaxValue)
    {
        switch($innerRule->operator)
        {
            case "BTW":
                if(!$isMaxValue) {
                    if($studentValue >= $innerRule->val1 && $studentValue < $innerRule->val2)
                    {
                        return $innerRule->mark;
                    }
                } else {
                    if($studentValue >= $innerRule->val1 && $studentValue <= $innerRule->val2)
                    {
                        return $innerRule->mark;
                    }
                }
                break;
            case "GTE":
                if($studentValue >= $innerRule->val1)
                {
                    return $innerRule->mark;
                }
                break;
            case "LTE":
                if($studentValue <= $innerRule->val1)
                {
                    return $innerRule->mark;
                }
                break;
        }
    }
    public function calculateDetailedRuleForStudent(CalculateAssessmentRuleRequest $request)
    {
        $request = $this->realEscapeObject($request);
        try{
            $subjects = SubjectService::getInstance()->getSubjectsByStudent($request->studentId,$request->batchId,$request->semesterId);
            $student = StudentService::getInstance()->getStudentDetailsById($request->studentId);
            $student->studentID = $student->id;
            //Get rule assigned for batch in a sem
            $getRuleRequest = new GetRuleAssignedForABatchRequest();
            $getRuleRequest->batchId = $request->batchId;
            $getRuleRequest->semesterId = $request->semesterId;
            $componentRule = $this->getRuleAssignedForABatch($getRuleRequest);   
            
            $subjectInternals = [];
            $examList = [];
            $publishedSubjects = [];
            foreach($subjects as $subject) {
                //If only published subjects should be viewed set this flag as true
                if($request->publishedSubjectsOnly)
                {
                    if(!MarkService::getInstance()->isNormalisedMarksPublished($request->batchId,$request->semesterId,$subject->subjectId))
                    {
                        continue;
                    }   
                }
                $publishedSubjects [] = $subject;//If publish subjects flag is set false,all subjects are considered published.
                $student->ATTENDANCE = $this->getAttendancePercent($request->studentId,$request->semesterId,$subject->subjectId,$request->batchId);
                        
                $calculateRuleForEachStudentRequest = null;
                $calculateRuleForEachStudentRequest = new CalculateComponentRuleForEachStudentRequest();
                $calculateRuleForEachStudentRequest->student = $student;
                $calculateRuleForEachStudentRequest->rule = $componentRule->subjectWiseRule->{$subject->subjectId};
                $calculateRuleForEachStudentRequest->semesterId = $componentRule->semId;
                $calculateRuleForEachStudentRequest->subjectId = $subject->subjectId;
                $calculateRuleForEachStudentRequest->batchId = $request->batchId;
                $subjectInternals [$subject->subjectId] = $this->calculateRuleForEachStudent($calculateRuleForEachStudentRequest);
                $getExamDetailsRequest = new GetExamDetailsRequest();
                $getExamDetailsRequest->batchId = $request->batchId;    
                $getExamDetailsRequest->semesterId = $request->semesterId;
                $getExamDetailsRequest->subjectId = $subject->subjectId;
                $getExamDetailsRequest->isAproved = $request->publishByStaff;
                $getSubbatchRequest = new \StdClass();
                $getSubbatchRequest->batchId = $request->batchId;
                $getSubbatchRequest->semesterId = $request->semesterId;
                $getSubbatchRequest->subjectId = $subject->subjectId;
                $getSubbatchRequest->studentId = $request->studentId;
                $getExamDetailsRequest->subbatchId = SubBatchService::getInstance()->getSubbatchOfAStudentForASubject($getSubbatchRequest);
                unset($getSubbatchRequest);
                $examList[$subject->subjectId] = ExamService::getInstance()->getExamDetailsForABatch($getExamDetailsRequest);
            }
            $student->internalMarkDetails = $subjectInternals;
            return ["studentDetails" => $student,"rule" => $componentRule,"subjects" => $publishedSubjects,"examList" => $examList];
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function calculateRulePseudoSubject($pssubId,$staffId)
    {
        $pssubId = $this->realEscapeString($pssubId);
        $staffId = $this->realEscapeString($staffId);
        try{
            $batches = BatchService::getInstance()->getBatchesAssignedToPseudoSubjectForAStaff($pssubId,$staffId);
            $normaliseMarkEditAfterApproval = CommonService::getInstance()->getSettings(SettingsConstants::INTERNAL_MARK_SETTINGS,SettingsConstants::NORMALIZE_MARKS_EDIT_AFTER_APPROVAL) === "1";
            $internalMarksBatchList = [];
            foreach($batches as $batch)
            {
                
                $isApproved = MarkService::getInstance()->isNormalisedMarksApproved($batch->batchID, $batch->semID, $batch->subjectID);
                if($isApproved && !$normaliseMarkEditAfterApproval)
                {
                    continue;
                }
                
                $getCalculatedRuleRequest = new CalculateAssessmentRuleRequest();
                $getCalculatedRuleRequest->batchId = $batch->batchID;
                $getCalculatedRuleRequest->semesterId = $batch->semID;
                $getCalculatedRuleRequest->subjectId = $batch->subjectID;
                $getCalculatedRuleRequest->subbatchId = $batch->subbatchID;
                $internalMarks = $this->calculateRuleForABatch($getCalculatedRuleRequest);
                $getExamDetailsRequest = new GetExamDetailsRequest();
                $getExamDetailsRequest->batchId = $batch->batchID;
                $getExamDetailsRequest->semesterId = $batch->semID;
                $getExamDetailsRequest->subjectId = $batch->subjectID;
                $getExamDetailsRequest->subbatchId = $batch->subbatchID;
                $examList = ExamService::getInstance()->getExamDetailsForABatch($getExamDetailsRequest);
                if(count($internalMarksBatchList[$batch->batchID]) > 0)
                {
                    $internalMarksBatchList[$batch->batchID]['studentList'] = array_merge($internalMarksBatchList[$batch->batchID]['studentList'],$internalMarks['studentList']);
                    // ($internalMarksBatchList[$batch->batchID])->examList = array_merge(($internalMarksBatchList[$batch->batchID])->examList,$examList);exams are created for both subbatches.so no merging needed
                } else {
                    $internalMarksBatchList[$batch->batchID]['batch'] = $batch;
                    $internalMarksBatchList[$batch->batchID]['studentList'] = $internalMarks['studentList'];
                    $internalMarksBatchList[$batch->batchID]['rule'] = $internalMarks['rule'];
                    $internalMarksBatchList[$batch->batchID]['examList'] = $examList;
                }
                unset($inernalMarks);
                unset($examList);
            }   
            return $internalMarksBatchList;         
        }catch(\Exception $e)
        {
            throw new ProfessionalException(ProfessionalException::ERROR_CALCULATING_COMPONENT_RULE,"Error in calculating rule!Please contact administrator");
        }
    }
    public function getStudentChildExamTypeMarksByExamTypeId($request)
    {
        $request = $this->realEscapeObject($request);
        $condition = "";
        $condition .= $request->publishByStaff?" AND aem.isAproved = 1 ":"";
        $condition .= $request->batchId?" AND sm.batchID = $request->batchId ":"";
        $query = "SELECT sm.marksObtained AS mark,e.examTotalMarks AS maxMark,e.examID,nm.markID AS alreadyNormalised,nm.normalisedMark-nm.marksObtained AS addMarks FROM exam_type et
        INNER JOIN student_marks sm ON sm.examTypeID = et.typeID
        INNER JOIN exam e ON e.examID = sm.examID
        LEFT JOIN aprove_exam_marks aem ON aem.batchID = e.batchID AND aem.semID = e.semID AND e.examID = aem.examId
        LEFT JOIN normalise_marks nm ON sm.semID=nm.semID AND sm.subjectID=nm.subjectID AND sm.studentID=nm.studentID
        where et.parent_exam_typeID = ".$request->examTypeId." and sm.subjectID = ".$request->subjectId." AND sm.studentID=".$request->studentID." AND sm.semID=".$request->semesterId." $condition ;";
        try{
            $markDetails = $this->executeQueryForObject($query);
            return $markDetails;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function getStudentMarksbyRequest($request)
    {
        $request = $this->realEscapeObject($request);
        $condition = "";
        if($request->staffId){
            $condition .=" AND staffID =$request->staffId";
        }
        if ($request->examId) {
            $condition .= " AND examID =$request->examId";
        }
        $query = "SELECT studentID, marksObtained from student_marks where batchID =$request->batchId AND semID =$request->semId AND subjectID =$request->subjectId AND examTypeID =$request->examTypeId $condition";
        try{
            $markDetails = $this->executeQueryForList($query);
            return $markDetails;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function getApproveExamMarkDetails($request)
    {
        $request = $this->realEscapeObject($request);
       
        $query = "SELECT isAproved from aprove_exam_marks where batchID =$request->batchId AND semID =$request->semID AND examId =$request->examId AND examTypeID =$request->examTypeId AND staffID =$request->staffId";
        try{
            $response = $this->executeQueryForObject($query)->isAproved;
            return $response;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function getApproveStatusExamMarkDetails($request)
    {
        $request = $this->realEscapeObject($request);
       
        $query = "SELECT aem.isAproved from aprove_exam_marks aem inner join exam ex on(ex.examID = aem.examId and ex.semID = aem.semID and ex.examTypeID = aem.examTypeID and ex.batchID = aem.batchID ) where ex.semID =$request->semID and ex.batchID =$request->batchId and ex.subjectID =$request->subjectId and ex.examTypeID =$request->examTypeId and aem.staffID =$request->staffId GROUP BY aem.staffId;";
        try{
            $response = $this->executeQueryForObject($query)->isAproved;
            return $response;
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function getBatchAsignedForComponent($ruleId)
    {
        $ruleId = $this->realEscapeObject($ruleId);
        $query = "SELECT bt.batchID, bt.batchName, acrab.sem_id
        from assessment_component_rule_assigned_batches acrab inner join batches bt on (acrab.batch_id = bt.batchID) where acrab.assessment_component_rule_id=$ruleId";
        try{
            $response = $this->executeQueryForList($query);
            if(empty($response)){
                return null;
            }
            return $response;        
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function getRuleAssignedForABatchByRuleId($batchId, $ruleId)
    {
        $ruleId = $this->realEscapeObject($ruleId);
        $batchId = $this->realEscapeObject($batchId);
        $query = "SELECT acr.id,acr.name,acrb.batch_id as batchId,acrb.sem_id as semId,acrb.rule,acrb.subjectwise_rule as subjectWiseRule
                    FROM    
                    assessment_component_rule_assigned_batches acrb
                    INNER JOIN 
                    assessment_component_rule acr ON acrb.assessment_component_rule_id = acr.id
                    WHERE
                    acrb.batch_id = '$batchId' AND acrb.assessment_component_rule_id = '$ruleId';";
        try{
            $response = $this->executeQueryForObject($query);
            if(empty($response)){
                return null;
            }
            $response->rule = json_decode($response->rule);
            $response->subjectWiseRule = json_decode($response->subjectWiseRule);
            return $response;        
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
        /**
     * update batch assessment component rule
     * @return null
     */
    public function updateBatchAssessmentComponentRule($request)
    {
        $request = $this->realEscapeObject($request);
        $query = "UPDATE assessment_component_rule_assigned_batches SET subjectwise_rule='".(json_encode($request->rule))."',updated_by='$request->updatedBy',updated_date=UTC_TIMESTAMP() WHERE assessment_component_rule_id='$request->ruleId' and batch_id='$request->batchId";  
        
        try{
            $this->executeQuery($query);
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get distinct semesters from component assigned batchIds
     * @param batchIds
     */
    public function getDistinctSemetersFromComponentAssignedBatches($batchIds)
    {
        $batchIds = $this->realEscapeObject($batchIds);
        $query = "SELECT DISTINCT s.semID , s.semName FROM assessment_component_rule_assigned_batches  acrab INNER JOIN semesters s ON (s.semID = acrab.sem_id )WHERE batch_id in ($batchIds) ORDER BY s.semID ASC";
        try{
            $response = $this->executeQueryForList($query);
            return $response;        
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    /**
     * get component details by batchIds and semIds
     * @param batchIds
     */
    public function getComponentDetailsByBatchIdsAndSemIds($batchIds, $semIds)
    {
        $batchIds = $this->realEscapeObject($batchIds);
        $query="SELECT acrab.sem_id as semId, bt.batchName, acrab.subjectwise_rule as subjectWiseRule, acrab.assessment_component_rule_id as componentRuleId,
                acrab.id as assignedBatchRuleId
                FROM assessment_component_rule_assigned_batches acrab INNER JOIN batches bt ON (acrab.batch_id = bt.batchID) WHERE acrab.batch_id IN ($batchIds) AND acrab.sem_id IN ($semIds) ORDER BY bt.batchStartYear, acrab.sem_id ASC";
        try{
            $response = $this->executeQueryForList($query);
            return $response;        
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function revisedInternalMarkCalculation($request)
    {
        
        try{
            $student = new stdClass();
            $student->test = 1;
            $student->ATTENDANCE = $this->getAttendancePercent($request->std->studentID,$request->semesterId,$request->subjectId,$request->batchId);
            
            $calculateRuleForEachStudentRequest = null;
            $calculateRuleForEachStudentRequest = new CalculateComponentRuleForEachStudentRequest();
            $calculateRuleForEachStudentRequest->student = $request->std;
            $calculateRuleForEachStudentRequest->rule = $request->componentRule->subjectWiseRule->{$request->subjectId};
            $calculateRuleForEachStudentRequest->semesterId = $request->componentRule->semId;
            $calculateRuleForEachStudentRequest->subjectId = $request->subjectId;
            $calculateRuleForEachStudentRequest->examTypeRules = $request->examTypeRules;
            $calculateRuleForEachStudentRequest->batchId = $request->batchId;
            $student->internalMarkDetails = $this->calculateRuleForEachStudent($calculateRuleForEachStudentRequest);
            return $student->internalMarkDetails['totalInternalMarks'];        
        }catch(\Exception $e)
        {
            throw new ProfessionalException($e->getCode(),$e->getMessage());
        }
    }
    public function calculateRuleForABatchAllSubjects(CalculateAssessmentRuleRequest $request)
    {
        $request = $this->realEscapeObject($request);
        //Rule is calculated against a exam in a batch.So these parameters should not be empty.
        if(empty($request->batchId) || empty($request->semesterId))
        {
            throw new ProfessionalException(ProfessionalException::INVALID_PARAMETER,"Invalid request given!");
        }
        try{
            //Get student details in the given batch
            $studentDetails = $this->getStudentsForRuleCalculation($request);
            //Get rule assigned for batch in a sem
            $getRuleRequest = new GetRuleAssignedForABatchRequest();
            $getRuleRequest->batchId = $request->batchId;
            $getRuleRequest->semesterId = $request->semesterId;
            $componentRule = $this->getRuleAssignedForABatch($getRuleRequest);   
            $examTypeRules = $componentRule->rule->examTypes;
            $examMarkRules = $componentRule->rule->examMarkRules;
            
            
            foreach($studentDetails as $student)
            {
                $subjectsAssignedtoStudent = SubjectService::getInstance()->getSubjectsByStudent($student->studentID,$request->batchId,$request->semesterId);
                $subjectIds = array_map(function ($obj) use ($index) {
                                return $obj->{subjectId};
                            }, $subjectsAssignedtoStudent);
                $student->subjectCount = count($subjectIds);
                $student->studentAssignedSubjectIds = $subjectIds;
                foreach($componentRule->subjectWiseRule as $subjectId => $rule){
                    if(!in_array($subjectId,$subjectIds)){
                        continue;
                    }
                    $student->ATTENDANCE[$subjectId] = $this->getAttendancePercent($student->studentID,$request->semesterId,$subjectId,$request->batchId);
                
                    $calculateRuleForEachStudentRequest = null;
                    $calculateRuleForEachStudentRequest = new CalculateComponentRuleForEachStudentRequest();
                    $calculateRuleForEachStudentRequest->student = $student;
                    $calculateRuleForEachStudentRequest->rule = $rule;
                    $calculateRuleForEachStudentRequest->semesterId = $componentRule->semId;
                    $calculateRuleForEachStudentRequest->subjectId = $subjectId;
                    $calculateRuleForEachStudentRequest->examTypeRules = $examTypeRules;
                    $calculateRuleForEachStudentRequest->batchId = $request->batchId;
                    $student->internalMarkDetails[$subjectId] = $this->calculateRuleForEachStudent($calculateRuleForEachStudentRequest);
                }
            }
        }catch(\Exception $e)
        {
            throw new ProfessionalException(ProfessionalException::ERROR_CALCULATING_COMPONENT_RULE,"Error in calculating rule!Please contact administrator");
        }
        return ["studentList" => $studentDetails,"rule" => $componentRule->subjectWiseRule,"examMarkRules" =>$examMarkRules];
    }
}