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 / 83
CRAP
0.00% covered (danger)
0.00%
0 / 2669
AssessmentService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 83
375156.00
0.00% covered (danger)
0.00%
0 / 2669
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 2
 __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 / 6
 addInternalAssessment
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 25
 getInternalAssessments
0.00% covered (danger)
0.00%
0 / 1
1056.00
0.00% covered (danger)
0.00%
0 / 99
 updateInternalAssessment
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 33
 getInternalAssessmentById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 deleteInternalAssessmentById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getInternalAssessmentColumnMarks
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 56
 getRulewiseStudentAttendanceMarks
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 29
 getRulewiseStudentAttendanceHours
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 63
 getRulewiseStudentAttendanceHoursPresent
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 63
 getRulewiseStudentAttendanceHoursAbsent
0.00% covered (danger)
0.00%
0 / 1
210.00
0.00% covered (danger)
0.00%
0 / 63
 addInternalAssessmentColumn
0.00% covered (danger)
0.00%
0 / 1
756.00
0.00% covered (danger)
0.00%
0 / 109
 addAttendanceRules
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 16
 addInternalAssessmentAttendanceFieldRule
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 18
 updateInternalAssessmentColumn
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 44
 updateAttendanceRules
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 14
 updateInternalAssessmentAttendanceFieldRule
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 14
 getInternalAssessmentColumnById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 generateNextColumnNoById
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 getInternalAssessmentExamRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 addInternalAssessmentExamRule
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 18
 updateInternalAssessmentExamRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getInternalAssessmentAssignmentRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 addInternalAssessmentAssignmentRule
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 18
 updateInternalAssessmentAssignmentRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getInternalAssessmentAttendanceRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 getInternalAssessmentGenderwiseAttendanceRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 addInternalAssessmentAttendanceMarkRule
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 28
 updateInternalAssessmentAttendanceMarkRule
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 41
 getInternalAssessmentFormulaRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 addInternalAssessmentFormulaRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 updateInternalAssessmentFormulaRule
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getRulewiseStudentExamMarks
0.00% covered (danger)
0.00%
0 / 1
1122.00
0.00% covered (danger)
0.00%
0 / 124
 getRulewiseStudentAssignmentMarks
0.00% covered (danger)
0.00%
0 / 1
870.00
0.00% covered (danger)
0.00%
0 / 108
 getRulewiseStudentAttendanceByMarkRule
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 72
 getRulewiseStudentGenderwiseAttendanceByMarkRule
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 72
 getFormulawiseStudentMarks
0.00% covered (danger)
0.00%
0 / 1
506.00
0.00% covered (danger)
0.00%
0 / 98
 getVariableValues
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 23
 getAssessmentReport
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 38
 getAssessmentColumns
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 14
 updateColumnDetailsById
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 26
 saveStudentColumnMarks
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 31
 deleteStudentColumnMarks
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 13
 generateAssessmentNumber
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 20
 getAssessmentGroupByColumnId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 deleteAssessmentColumnGroupById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 deleteAssessmentColumnById
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 19
 getAssessmentColumnDetailsById
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 1
 validateInternalAssessmentFormula
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 15
 getFormlaDependentColumns
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 16
 getFormlaDependentColumnIds
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 16
 getColumnNoById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 recalculateMarksByAssessmentId
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 15
 getInernalAssessmentColums
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 addInternalAssessmentMarkByStudentId
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 20
 getInternalAssessmentMarkByStudentId
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 20
 reCalculateMarkByStudentId
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 34
 getAttendanceDates
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 publishInternalAssessmentById
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getColumnStatus
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 13
 createInternalAssessmentColumn
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 16
 createInternalAssessmentColumnGroup
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 getInternalAssessmentColumnByGroupId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 updateInternalAssessmentExamRuleByGroupId
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 26
 updateInternalAssessmentAssignmentRuleByGroupId
0.00% covered (danger)
0.00%
0 / 1
56.00
0.00% covered (danger)
0.00%
0 / 26
 insertInernalAssessmentColumnExamMarksByGroupId
0.00% covered (danger)
0.00%
0 / 1
930.00
0.00% covered (danger)
0.00%
0 / 180
 insertInernalAssessmentColumnOnlineExamMarks
0.00% covered (danger)
0.00%
0 / 1
1056.00
0.00% covered (danger)
0.00%
0 / 175
 insertInernalAssessmentColumnAssignmentMarksByGroupId
0.00% covered (danger)
0.00%
0 / 1
930.00
0.00% covered (danger)
0.00%
0 / 88
 deleteInternalAssessmentColumnByGroupId
0.00% covered (danger)
0.00%
0 / 1
72.00
0.00% covered (danger)
0.00%
0 / 31
 addRemoveInternalAssessmentExamColumnOnUpdate
0.00% covered (danger)
0.00%
0 / 1
650.00
0.00% covered (danger)
0.00%
0 / 76
 addRemoveInternalAssessmentAssignmentColumnOnUpdate
0.00% covered (danger)
0.00%
0 / 1
600.00
0.00% covered (danger)
0.00%
0 / 71
 updateInternalAssessmentColumnByGroupId
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 isColumnRuleTypeAttendanceHours
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 15
 getInternalAssessmentColumnByColumnNo
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 getInternalAssessmentExamMarkRange
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getInternalAssessmentAssignmentMarkRange
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 getConsolidatedAssessmentReport
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 23
 getAssignedBatchesOrSubjectsInInternalAssessment
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 9
 updateMaxMarksInExams
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 51
 getCustomReportOfStudentBatch
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 27
 checkAttendancRuleIsGenderWise
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 10
<?php
namespace com\linways\core\ams\professional\service;
use com\linways\core\ams\professional\dto\InternalAssessmentAttendanceRuleType;
use com\linways\core\ams\professional\dto\InternalAssessmentRuleType;
use com\linways\core\ams\professional\dto\InternalAssessmentStudentColumnMark;
use com\linways\core\ams\professional\exception\ProfessionalException;
use com\linways\core\ams\professional\mapper\AssessmentServiceMapper;
use com\linways\core\ams\professional\service\SemesterService;
use com\linways\core\ams\professional\service\BatchService;
use stdClass;
use com\linways\core\ams\professional\util\CommonUtil;
class AssessmentService extends BaseService {
    // /Condition 1 - Presence of a static member variable
    private static $_instance = null;
    private $mapper           = [];
    // /Condition 2 - Locked down the constructor
    private function __construct() {
        $this->mapper = AssessmentServiceMapper::getInstance()->getMapper();
    }
    // 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;
    }
    /**
     * Add internal assessment details
     *
     * @param InternalAssessment $internalAssessment
     * @throws ProfessionalException
     * @return NULL
     */
    public function addInternalAssessment($internalAssessment) {
        // Insert internalAssessment
        $internalAssessment = $this->realEscapeObject($internalAssessment);
        $sql                = "INSERT INTO internal_assessment (assessmentNo, batchId, semId, subjectId, subbatchId, totalMark, name, createdBy, createdDate, updatedBy, updatedDate) VALUES ($internalAssessment->assessmentNo$internalAssessment->batchId$internalAssessment->semId$internalAssessment->subjectId$internalAssessment->subbatchId$internalAssessment->totalMark, '$internalAssessment->name', $internalAssessment->createdBy, utc_timestamp(), $internalAssessment->updatedBy, utc_timestamp());";
        
        // Insert internalAssessment for PseudoSubjects
        if($internalAssessment->psId){
            $sql                = "INSERT INTO internal_assessment (assessmentNo, subjectId,totalMark, name, createdBy, createdDate, updatedBy, updatedDate,psId) VALUES ($internalAssessment->assessmentNo$internalAssessment->subjectId,$internalAssessment->totalMark, '$internalAssessment->name', $internalAssessment->createdBy, utc_timestamp(), $internalAssessment->updatedBy, utc_timestamp(),'$internalAssessment->psId');";
        }
        try
        {
            $assessmentId = $this->executeQueryForObject($sql, TRUE);
            //Custom reports->Internal Assessment - Assign batches
            if(!empty($internalAssessment->batchIds) || !empty($internalAssessment->subjectIds)) {
                $batches = [
                    "deptId" => $internalAssessment->deptId,
                    "batchIds" => $internalAssessment->batchIds,
                    "subjectIds" => $internalAssessment->subjectIds
                ];
                $batches = json_encode($batches);
                $sql_assign_batches = "INSERT INTO internal_assessment_assigned_batches (internal_assessment_id, batches, createdBy, createdDate, updatedBy, updatedDate) VALUES ($assessmentId,'$batches',$internalAssessment->createdBy, utc_timestamp(), $internalAssessment->updatedBy, utc_timestamp())";
                $this->executeQueryForObject($sql_assign_batches);
            }
            return $assessmentId;
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return null;
    }
    /**
     * Get internal assessments of by batchId, semId, subjectId, subbatchId
     *
     * @param int $batchId
     * @param int $semId
     * @param int $subjectId
     * @param int $subbatchId
     * @return InternalAssessment[]
     */
    public function getInternalAssessments($batchId, $semId, $subjectId, $subbatchId,$psId =null) {
        $internalAssessments = [];
        $batchId    = $this->realEscapeString($batchId);
        $semId      = $this->realEscapeString($semId);
        $subjectId  = $this->realEscapeString($subjectId);
        $subjectCheck = $subjectId ? "AND ia.subjectId = '$subjectId'":"";
        $subbatchId = $this->realEscapeString($subbatchId);
        $sql = "SELECT ia.id, ia.assessmentNo,
                              ia.name,
                              ia.batchId,
                              ia.semId,
                              ia.subjectId,
                              ia.subbatchId,
                              ia.totalMark,
                              ia.createdBy,
                              ia.createdDate,
                              ia.updatedBy,
                              ia.updatedDate,
                              ia.isActive,
                              ia.isPublished,
                              sa.staffName 
                              FROM internal_assessment ia JOIN staffaccounts sa ON ( ia.createdBy = sa.staffId ) 
                              WHERE (
                                        ( ia.batchId = '$batchId' AND ia.semId = '$semId$subjectCheck AND ia.subbatchId = '$subbatchId' ) 
                                            OR 
                                        ( ia.batchId IS NULL AND ia.semId IS NULL AND ia.subjectId IS NULL )
                                    ) 
                                AND ia.isActive = 1 order by ia.assessmentNo";
        if($psId){
            $psBatches = PseudoSubjectService ::getInstance()->getsubbatchIDsAndbatchIDs($psId);
            $batchIds = implode(",",array_map(function($o) { return $o->batchID;}, $psBatches));
            if(!empty($batchIds)){
                $psCond = "OR ( ia.subjectId = '$subjectId' and ia.batchId in ($batchIds))";
            }
            $sql = "SELECT ia.id, ia.assessmentNo, ia.name, ia.batchId, ia.semId, ia.subjectId, ia.subbatchId, ia.totalMark, ia.createdBy, ia.createdDate, ia.updatedBy, ia.updatedDate, ia.isActive, ia.isPublished, sa.staffName FROM internal_assessment ia JOIN staffaccounts sa ON ( ia.createdBy = sa.staffId ) WHERE ( ia.psId = '$psId' AND ia.subjectId = '$subjectId' ) OR ( ia.batchId IS NULL AND ia.semId IS NULL AND ia.subjectId IS NULL ) $psCond AND ia.isActive = 1 order by ia.assessmentNo";
        }
        
        // $sql = "SELECT id, assessmentNo, name, batchId, semId, subjectId, subbatchId, totalMark, createdBy, createdDate, updatedBy, updatedDate, isActive, isPublished FROM internal_assessment WHERE batchId = '$batchId' AND semId = '$semId' AND subjectId = '$subjectId' AND subbatchId = '$subbatchId' AND isActive = 1 order by assessmentNo";
        try {
            $internalAssessments = $this->executeQueryForList($sql, $this->mapper[AssessmentServiceMapper::GETINTERNALASSESSMENTS]);
            $key = 0;
            foreach($internalAssessments as $internalAssessment){
                $batchesAssigned = $this->getAssignedBatchesOrSubjectsInInternalAssessment($internalAssessment->id)->batches;
                if(!empty($batchesAssigned)){
                    $assignedBatches = json_decode($batchesAssigned);
                    if($assignedBatches->deptId){
                        $internalAssessments[$key]->departmentName = DepartmentService::getInstance()->getDepartmentNameById($assignedBatches->deptId);
                    }
                    if(!empty($assignedBatches->batchIds)){
                        $batchNames = BatchService::getInstance()->getConcatenatedBatchNameByBatchIds($assignedBatches->batchIds);
                        $internalAssessments[$key]->batchNames = $batchNames;
                    }
                    if(!empty($assignedBatches->subjectIds)){
                        $subjectNames = SubjectService::getInstance()->getConcatenatedSubjectNameBySubjectIds($assignedBatches->subjectIds);
                        $internalAssessments[$key]->subjectNames = $subjectNames;
                    }
                    if(is_Numeric($batchId) || is_Numeric($psId)){
                        if($psId){
                            $findBatch = false;
                            $findDept = false;
                            $findSubject = false;
                            foreach($psBatches as $psBatch){
                                $deptId = DepartmentService::getInstance()->getDepartmentByBatchId($psBatch->batchID)->deptID;
                                if(empty($assignedBatches->deptId) || $assignedBatches->deptId == $deptId){
                                    $findDept = true;
                                }
                                if((is_array($assignedBatches->batchIds) && in_array($psBatch->batchID,$assignedBatches->batchIds)) || empty($assignedBatches->batchIds)){ 
                                    $findBatch = true;
                                }
                                if((is_array($assignedBatches->subjectIds) && in_array($subjectId,$assignedBatches->subjectIds)) || empty($assignedBatches->subjectIds)){ 
                                    $findSubject = true;
                                }
                            }
                            if(!$findBatch || !$findDept || !$findSubject){
                                unset($internalAssessments[$key]);
                            }
                        }
                        else{
                            $deptId = DepartmentService::getInstance()->getDepartmentByBatchId($batchId)->deptID;
                            if($assignedBatches->deptId != ""){
                                if($assignedBatches->deptId != $deptId){
                                    unset($internalAssessments[$key]);
                                }
                            }  
                            else{
                                if(is_array($assignedBatches->batchIds) && !in_array($batchId,$assignedBatches->batchIds)){ 
                                    unset($internalAssessments[$key]);
                                }
                                if(is_array($assignedBatches->subjectIds) && !in_array($subjectId,$assignedBatches->subjectIds) && !empty($subjectId)){ 
                                    unset($internalAssessments[$key]);
                                }
                            }
                        }
                    }
                }
                $key++;
            }
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessments;
    }
    /**
     * update internal assessment using id
     *
     * @param InternalAssessment $internalAssessment
     * @throws ProfessionalException
     * @return object|NULL|\com\linways\base\util\$objectList[]|NULL
     */
    public function updateInternalAssessment($internalAssessment) {
        $internalAssessment = $this->realEscapeObject($internalAssessment);
        $sql = "UPDATE internal_assessment SET name='$internalAssessment->name', updatedBy=$internalAssessment->updatedBy, updatedDate=utc_timestamp() WHERE id=$internalAssessment->id";
        try {
            $this->executeQuery($sql);
            $batchesAssigned = $this->getAssignedBatchesOrSubjectsInInternalAssessment($internalAssessment->id)->batches;
            $batches = [
                "deptId" => $internalAssessment->deptId,
                "batchIds" => $internalAssessment->batchIds,
                "subjectIds" => $internalAssessment->subjectIds
            ];
            $batches = json_encode($batches);
            if($batchesAssigned){
                if($internalAssessment->deptId || $internalAssessment->batchIds){
                    $sql_assign_batches = "UPDATE internal_assessment_assigned_batches SET batches= '$batches' WHERE internal_assessment_id  = $internalAssessment->id";
                }
                else{
                    $sql_assign_batches = "";
                    $sql_del = "DELETE FROM internal_assessment_assigned_batches WHERE internal_assessment_id  = $internalAssessment->id";
                    $this->executeQuery($sql_del);
                }
            }
            else{
                if($internalAssessment->deptId || $internalAssessment->batchIds){
                    $sql_assign_batches = "INSERT INTO internal_assessment_assigned_batches (internal_assessment_id, batches, createdBy, createdDate, updatedBy, updatedDate) VALUES ($internalAssessment->id,'$batches',$internalAssessment->createdBy, utc_timestamp(), $internalAssessment->updatedBy, utc_timestamp())";
                }
            }
            $this->executeQueryForObject($sql_assign_batches);
                
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return null;
    }
    /**
     * Get internal assessment by id
     * return $internalAssessment
     */
    public function getInternalAssessmentById($internalAssessmentId) {
        $internalAssessment   = null;
        $internalAssessmentId = $this->realEscapeString($internalAssessmentId);
        $sql = "SELECT id,assessmentNo,batchId,semId,subjectId,subbatchId,totalMark,createdBy,createdDate,updatedBy,updatedDate,name,psId
     FROM internal_assessment    WHERE id = $internalAssessmentId ";
        try {
            $internalAssessment = $this->executeQueryForObject($sql, false, $this->mapper[AssessmentServiceMapper::GETINTERNALASSESSMENTBYID]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessment;
    }
    /**
     * Delete internal assessment by id
     * return $internalAssessment
     */
    public function deleteInternalAssessmentById($internalAssessmentId) {
        $internalAssessmentId = $this->realEscapeString($internalAssessmentId);
        $sql = "DELETE FROM internal_assessment WHERE id = $internalAssessmentId ";
        try {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Add InternalAssessmentColumn and corresponding rule.
     *
     * @param InternalAssessmentColumn $internalAssessmentColumn
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @return InternalAssessmentStudentColumnMark[]
     */
    public function getInternalAssessmentColumnMarks($internalAssessmentColumnId, $internalAssessmentReq, $batchId = null, $semId = null, $subjectId = null ,$pssuid = null, $genderwise = null) {
        $internalAssessmentColumnId           = $this->realEscapeString($internalAssessmentColumnId);
        $internalAssessmentStudentColumnMarks = [];
        $internalAssessmentColumn             = $this->getInternalAssessmentColumnById($internalAssessmentColumnId);
        $internalAssessment                   = $this->getInternalAssessmentById($internalAssessmentColumn->internalAssessmentId);
        // Save corresponding rule to specific table by switching columnType of internalAssessmentColumn
        switch ($internalAssessmentColumn->ruleType) {
            case InternalAssessmentRuleType::EXAM:
                $rules = $this->getInternalAssessmentExamRule($internalAssessmentColumnId);
                $groupId = $this->getAssessmentGroupByColumnId($internalAssessmentColumnId);
                $this->insertInernalAssessmentColumnExamMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId, $batchId, $semId, $subjectId,$pssuid);
                // // Add InternalAssessmentExamRule from $rule object
                // $this->addInternalAssessmentExamRule ( $rules, $internalAssessmentColumn->id );
                // Evaluate exam marks of each student if rule is successfully saved.
                // $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentExamMarks($rules, $internalAssessment, $internalAssessmentColumn, $internalAssessmentReq);
                break;
            case InternalAssessmentRuleType::ASSIGNMENT:
                $rules = $this->getInternalAssessmentAssignmentRule($internalAssessmentColumnId);
                if(!$rules->markRange){
                    $rules->markRange = $this->getInternalAssessmentAssignmentMarkRange($internalAssessmentColumnId);
                }
                $groupId = $this->getAssessmentGroupByColumnId($internalAssessmentColumnId);
                if($pssuid){
                    $batchList = PseudoSubjectService ::getInstance()->getsubbatchIDsAndbatchIDs($pssuid);
                    foreach($batchList as $batch){
                        $batchId = $batch->batchID;
                        $semId = $batch->semID;
                        $this->insertInernalAssessmentColumnAssignmentMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId , $batchId, $semId, $subjectId);
                    }
                }
                else{
                    $this->insertInernalAssessmentColumnAssignmentMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId , $batchId, $semId, $subjectId);
                }
                // Add InternalAssessmentAssignmentRule from $rule object
                // $this->addInternalAssessmentAssignmentRule ( $rules, $internalAssessmentColumn->id );
                // Evaluate assignment marks of each student if rule is successfully saved.
                // $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentAssignmentMarks($rules, $internalAssessment, $internalAssessmentColumn->id, $internalAssessmentReq);
                break;
            case InternalAssessmentRuleType::ATTENDANCE:
                if($genderwise)
                {
                    $rules = $this->getInternalAssessmentGenderwiseAttendanceRule($internalAssessmentColumnId);
                }
                else
                {
                    $rules = $this->getInternalAssessmentAttendanceRule($internalAssessmentColumnId);
                }
                // Add InternalAssessmentAttendanceRule from $rule object
                // $this->addInternalAssessmentAttendanceRule ( $rules, $internalAssessmentColumn->id );
                // Evaluate attendance marks of each student if rule is successfully saved.
                $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentAttendanceMarks($rules, $internalAssessmentColumn->id, $internalAssessment, $internalAssessmentReq,$genderwise);
                break;
            case InternalAssessmentRuleType::FORMULA:
                $rules = $this->getInternalAssessmentFormulaRule($internalAssessmentColumnId);
                // Add InternalAssessmentFormulaRule from $rule object
                // $this->addInternalAssessmentFormulaRule ( $rules, $internalAssessmentColumn->id );
                // Evaluate attendance marks of each student if rule is successfully saved.
                $internalAssessmentStudentColumnMarks = $this->getFormulawiseStudentMarks($rules, $internalAssessment, $internalAssessmentColumn, $internalAssessmentReq);
                break;
            case InternalAssessmentRuleType::FIELD:
                break;
            case InternalAssessmentRuleType::ONLINE_EXAM:
                $rules = $this->getInternalAssessmentExamRule($internalAssessmentColumnId);
                $groupId = $this->getAssessmentGroupByColumnId($internalAssessmentColumnId);
                $this->insertInernalAssessmentColumnOnlineExamMarks ( $internalAssessmentColumn, $rules, $groupId, $batchId, $semId, $subjectId,$pssuid);
                break;
            default:
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_NO_RULE_DEFINED, "Invalid Rule for column:$internalAssessmentColumn->columnName");
                break;
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get attedance rule marks
     *
     * @throws ProfessionalException
     */
    public function getRulewiseStudentAttendanceMarks($rules, $internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq, $genderwise) {
        $internalAssessment         = $this->realEscapeObject($internalAssessment);
        $internalAssessmentReq      = $this->realEscapeObject($internalAssessmentReq);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        // Switch between attendance rules
        switch ($rules->ruleType) {
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_MARK:
                if($genderwise)
                {
                    $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentGenderwiseAttendanceByMarkRule($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq);
                }
                else
                {
                    $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentAttendanceByMarkRule($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq);
                }
                break;
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS:
                $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentAttendanceHours($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq);
                break;
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_PRESENT:
                $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentAttendanceHoursPresent($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq);
                break;
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_ABSENT:
                $internalAssessmentStudentColumnMarks = $this->getRulewiseStudentAttendanceHoursAbsent($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq);
                break;
            default:
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_NO_RULE_DEFINED, "Invalid Rule for column:$internalAssessmentColumn->columnName");
                break;
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get Rulewise Student Attendance hours
     *
     * @param int $internalAssessmentColumnId
     * @param InternalAssessment $internalAssessment
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @return InternalAssessmentStudentColumnMark[]
     *
     */
    public function getRulewiseStudentAttendanceHours($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq) {
        $internalAssessment         = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $internalAssessmentStudentColumnMarks = [];
        $fromDate                             = NULL;
        $toDate                               = NULL;
        $attCond                              = "";
        $studentDetails                       = null;
        $psId = $internalAssessment->psId? $internalAssessment->psId:$internalAssessmentReq->psId;
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumnId, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId,$psId);
        // Evaluate totalmark of column
        $sql           = "SELECT MAX(marks) as maxMark, fromDate, toDate FROM internal_assessment_attendance_rule WHERE internalAssessmentColumnId=$internalAssessmentColumnId";
        $attRuleResult = $this->executeQueryForObject($sql);
        $totalMark = $attRuleResult->maxMark;
        $fromDate  = $attRuleResult->fromDate;
        $toDate    = $attRuleResult->toDate;
        // Update total mark of assessment column.
        $this->updateColumnDetailsById($internalAssessmentColumnId, $totalMark, $internalAssessmentReq);
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId;
        }
        // Retrieving students of given batchId
        
        if (!empty($internalAssessment->batchId) && !empty($internalAssessment->semId)) {
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            if($isCurrentSem)
            {
                $sql_students = "select sa.studentID, sa.studentName,sa.rollNo, regNo from  studentaccount sa inner join batches ba on  ba.batchID = sa.batchID  inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where sa.batchID= $internalAssessment->batchId and joinedSem.orderNo <= sem.orderNo ORDER BY sa.rollNo";
            }
            else
            {
                
                $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
                
                $sql_students = "select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from studentaccount sa inner join batches ba on sa.batchID =  ba.batchID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where ba.batchID = $internalAssessment->batchId and joinedSem.orderNo <= $semDetails->orderNo union select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from failed_students fs left join studentaccount sa on fs.studentID= sa.studentID inner join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where previousBatch = $internalAssessment->batchId and fsem.orderNo > $semDetails->orderNo and joinedSem.orderNo <= $semDetails->orderNo order by rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
            }
        if($psId){
            $studentDetails = StudentService::getInstance()->getStudentsAssignedToApseudoSub($psId);
        }
        if ($studentDetails != NULL) {
            if (!empty($fromDate) && !empty($toDate)) {
                $attCond = " AND att.attendanceDate BETWEEN '$fromDate' AND '$toDate'";
            }
            foreach ($studentDetails as $studentDetail) {
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumnId;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                $sql = "SELECT
                    COUNT(att.hour) AS hours FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID AND att.semID=$internalAssessment->semId $attCond";
                if($psId){
                    $sql = "SELECT
                    COUNT(att.hour) AS hours FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID $attCond";
                }
                $hours = $this->executeQueryForObject($sql)->hours;
                $internalAssessmentStudentColumnMark->marks = $hours;
                // Saving column Marks
                if($psId){
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $hours,$studentDetail->batchID,$internalAssessmentReq->subjectId);
                }
                else{
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $hours, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                }
                
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
            }
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get Rulewise Student Attendance hours present
     *
     * @param int $internalAssessmentColumnId
     * @param InternalAssessment $internalAssessment
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @return InternalAssessmentStudentColumnMark[]
     *
     */
    public function getRulewiseStudentAttendanceHoursPresent($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq) {
        $internalAssessment         = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $internalAssessmentStudentColumnMarks = [];
        $fromDate                             = NULL;
        $toDate                               = NULL;
        $attCond                              = "";
        $studentDetails                       = null;
        $psId = $internalAssessment->psId? $internalAssessment->psId:$internalAssessmentReq->psId;
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumnId, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId,$psId);
        // Evaluate totalmark of column
        $sql           = "SELECT MAX(marks) as maxMark, fromDate, toDate FROM internal_assessment_attendance_rule WHERE internalAssessmentColumnId=$internalAssessmentColumnId";
        $attRuleResult = $this->executeQueryForObject($sql);
        $totalMark = $attRuleResult->maxMark;
        $fromDate  = $attRuleResult->fromDate;
        $toDate    = $attRuleResult->toDate;
        // Update total mark of assessment column.
        $this->updateColumnDetailsById($internalAssessmentColumnId, $totalMark, $internalAssessmentReq);
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId;
        }
        // Retrieving students of given batchId
        if (!empty($internalAssessment->batchId) && !empty($internalAssessment->semId)) {
            
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            if($isCurrentSem)
            {
                $sql_students = "select sa.studentID, sa.studentName,sa.rollNo, regNo from  studentaccount sa inner join batches ba on  ba.batchID = sa.batchID  inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where sa.batchID= $internalAssessment->batchId and joinedSem.orderNo <= sem.orderNo ORDER BY sa.rollNo";
            }
            else
            {
                
                $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
                
                $sql_students = "select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from studentaccount sa inner join batches ba on sa.batchID =  ba.batchID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where ba.batchID = $internalAssessment->batchId and joinedSem.orderNo <= $semDetails->orderNo union select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from failed_students fs left join studentaccount sa on fs.studentID= sa.studentID inner join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where previousBatch = $internalAssessment->batchId and fsem.orderNo > $semDetails->orderNo and joinedSem.orderNo <= $semDetails->orderNo order by rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
        }
        if($psId){
            $studentDetails = StudentService::getInstance()->getStudentsAssignedToApseudoSub($psId);
        }
        
        if ($studentDetails != NULL) {
            if (!empty($fromDate) && !empty($toDate)) {
                $attCond = " AND att.attendanceDate BETWEEN '$fromDate' AND '$toDate'";
            }
            foreach ($studentDetails as $studentDetail) {
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumnId;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                $sql = "SELECT (
                    COUNT(CASE WHEN  att.isAbsent=0 OR att.isAbsent=2 THEN 1 END)) AS hoursPresent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID AND att.semID=$internalAssessment->semId $attCond";
                if($psId){
                    $sql = "SELECT (
                        COUNT(CASE WHEN  att.isAbsent=0 OR att.isAbsent=2 THEN 1 END)) AS hoursPresent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID $attCond";
                }
                $hoursPresent = $this->executeQueryForObject($sql)->hoursPresent;
                
                $internalAssessmentStudentColumnMark->marks = $hoursPresent;
                // Saving column Marks
                if($psId){
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $hoursPresent, $studentDetail->batchID, $internalAssessmentReq->subjectId);
                }
                else{
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $hoursPresent, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                    
                }
                
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
            }
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get Rulewise Student Attendance hours present
     *
     * @param int $internalAssessmentColumnId
     * @param InternalAssessment $internalAssessment
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @return InternalAssessmentStudentColumnMark[]
     *
     */
    public function getRulewiseStudentAttendanceHoursAbsent($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq) {
        $internalAssessment         = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $internalAssessmentStudentColumnMarks = [];
        $fromDate                             = NULL;
        $toDate                               = NULL;
        $attCond                              = "";
        $studentDetails                       = null;
        $psId = $internalAssessment->psId? $internalAssessment->psId:$internalAssessmentReq->psId;
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumnId, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId,$psId);
        // Evaluate totalmark of column
        $sql           = "SELECT MAX(marks) as maxMark, fromDate, toDate FROM internal_assessment_attendance_rule WHERE internalAssessmentColumnId=$internalAssessmentColumnId";
        $attRuleResult = $this->executeQueryForObject($sql);
        $totalMark = $attRuleResult->maxMark;
        $fromDate  = $attRuleResult->fromDate;
        $toDate    = $attRuleResult->toDate;
        // Update total mark of assessment column.
        $this->updateColumnDetailsById($internalAssessmentColumnId, $totalMark, $internalAssessmentReq);
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId;
        }
        // Retrieving students of given batchId
        if (!empty($internalAssessment->batchId) && !empty($internalAssessment->semId)) {
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            if($isCurrentSem)
            {
                $sql_students = "select sa.studentID, sa.studentName,sa.rollNo, regNo from  studentaccount sa inner join batches ba on  ba.batchID = sa.batchID  inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where sa.batchID= $internalAssessment->batchId and joinedSem.orderNo <= sem.orderNo ORDER BY sa.rollNo";
            }
            else
            {
                $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
                
                $sql_students = "select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from studentaccount sa inner join batches ba on sa.batchID =  ba.batchID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where ba.batchID = $internalAssessment->batchId and joinedSem.orderNo <= $semDetails->orderNo union select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from failed_students fs left join studentaccount sa on fs.studentID= sa.studentID inner join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where previousBatch = $internalAssessment->batchId and fsem.orderNo > $semDetails->orderNo and joinedSem.orderNo <= $semDetails->orderNo order by rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
        }
        if($psId){
            $studentDetails = StudentService::getInstance()->getStudentsAssignedToApseudoSub($psId);
        }
        
        if ($studentDetails != NULL) {
            if (!empty($fromDate) && !empty($toDate)) {
                $attCond = " AND att.attendanceDate BETWEEN '$fromDate' AND '$toDate'";
            }
            foreach ($studentDetails as $studentDetail) {
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumnId;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                $sql = "SELECT (
                    COUNT(CASE WHEN  att.isAbsent!=0 AND att.isAbsent!=2 THEN 1 END)) AS hoursAbsent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID AND att.semID=$internalAssessment->semId $attCond";
                if($psId){
                    $sql = "SELECT (
                        COUNT(CASE WHEN  att.isAbsent!=0 AND att.isAbsent!=2 THEN 1 END)) AS hoursAbsent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID $attCond";
                }
                $hoursAbsent = $this->executeQueryForObject($sql)->hoursAbsent;
                $internalAssessmentStudentColumnMark->marks = $hoursAbsent;
                // Saving column Marks
                if($psId){
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $hoursAbsent, $studentDetail->batchID, $internalAssessmentReq->subjectId);
                }
                else{
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $hoursAbsent, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                }
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
            }
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * Add InternalAssessmentColumn and corresponding rule.
     *
     * @param InternalAssessmentColumn $internalAssessmentColumn
     * @param obj rules | object array rules
     * @return $internalAssessmentColumnId
     */
    public function addInternalAssessmentColumn($internalAssessmentColumn, $rules = null, $groupId = null) {
        $internalAssessmentColumnId = null;
        if ($internalAssessmentColumn->ruleType == InternalAssessmentRuleType::FORMULA) {
            // $isFormulaValid = $this->validateInternalAssessmentFormula($rules->formula);
            $isFormulaValid = true;
            if (!$isFormulaValid) {
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_INVALID_FORMULA, "Invalid formula");
            }
        }
        if (empty($internalAssessmentColumn->passPercent)) {
            $internalAssessmentColumn->passPercent = 0;
        }
        $rules = $this->realEscapeObject($rules);
        // Save corresponding rule to specific table by switching columnType of internalAssessmentColumn
        switch ($internalAssessmentColumn->ruleType) {
            case InternalAssessmentRuleType::EXAM:
                if ( empty ( $groupId ) ) {
                    $groupId = $this->createInternalAssessmentColumnGroup();
                    $numberOfColumns = $rules->isExamAvg == 1 ? 1 : $rules->examBestOf;
                } else {
                    $sql = "SELECT COUNT(id) as columnCount FROM internal_assessment_column WHERE groupId = $groupId";
                    try {
                        $columnCount = $this->executeQueryForObject($sql)->columnCount;
                    }
                    catch (\Exception $e) {
                        throw new ProfessionalException($e->getCode(), $e->getMessage());
                    }
                    $numberOfColumns = abs ( $rules->examBestOf - $columnCount);
                }
                for ( $i = 0; $i < $numberOfColumns; $i++ ) {
                    $internalAssessmentColumnId = $this->createInternalAssessmentColumn ($internalAssessmentColumn, $groupId);
                    // Add InternalAssessmentExamRule from $rule object
                    $this->addInternalAssessmentExamRule($rules, $internalAssessmentColumnId);
                    if($numberOfColumns==1){
                        $internalAssessmentColumn->id = $internalAssessmentColumnId;
                    }
                }
                $this->insertInernalAssessmentColumnExamMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId );
                break;
            case InternalAssessmentRuleType::ASSIGNMENT:
                if ( empty ( $groupId ) ) {
                    $groupId = $this->createInternalAssessmentColumnGroup();
                    $numberOfColumns = $rules->isassignmentAvg == 1 ? 1 : $rules->assignmentBestOf;
                } else {
                    $sql = "SELECT COUNT(id) as columnCount FROM internal_assessment_column WHERE groupId = $groupId";
                    try {
                        $columnCount = $this->executeQueryForObject($sql)->columnCount;
                    }
                    catch (\Exception $e) {
                        throw new ProfessionalException($e->getCode(), $e->getMessage());
                    }
                    $numberOfColumns = abs ( $rules->assignmentBestOf - $columnCount);
                }
                for ( $i = 0; $i < $numberOfColumns; $i++ ) {
                    $internalAssessmentColumnId = $this->createInternalAssessmentColumn ($internalAssessmentColumn, $groupId);
                    // Add InternalAssessmentAssignmentRule from $rule object
                    $this->addInternalAssessmentAssignmentRule($rules, $internalAssessmentColumnId);
                    if($numberOfColumns==1){
                        $internalAssessmentColumn->id = $internalAssessmentColumnId;
                    }
                }
                if($internalAssessmentColumn->psId){
                    $batchList = PseudoSubjectService ::getInstance()->getsubbatchIDsAndbatchIDs($internalAssessmentColumn->psId);
                    foreach($batchList as $batch){
                        $batchId = $batch->batchID;
                        $semId = $batch->semID;
                        $subjectId = $internalAssessmentColumn->subjectId;
                        $this->insertInernalAssessmentColumnAssignmentMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId,$batchId,$semId,$subjectId );
                    }    
                }
                else{
                    $this->insertInernalAssessmentColumnAssignmentMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId );
                }
                break;
            case InternalAssessmentRuleType::ATTENDANCE:
                $internalAssessmentColumnId = $this->createInternalAssessmentColumn ($internalAssessmentColumn);
                // Add InternalAssessmentAttendanceRule from $rule object
                $this->addAttendanceRules($rules, $internalAssessmentColumnId);
                break;
            case InternalAssessmentRuleType::FORMULA:
                $internalAssessmentColumnId = $this->createInternalAssessmentColumn ($internalAssessmentColumn);
                // Add InternalAssessmentFormulaRule from $rule object
                $this->addInternalAssessmentFormulaRule($rules, $internalAssessmentColumnId);
                break;
            case InternalAssessmentRuleType::FIELD:
                $internalAssessmentColumnId = $this->createInternalAssessmentColumn ($internalAssessmentColumn);
                break;
            case InternalAssessmentRuleType::ONLINE_EXAM:
                if ( empty ( $groupId ) ) {
                    $groupId = $this->createInternalAssessmentColumnGroup();
                    $numberOfColumns = $rules->isExamAvg == 1 ? 1 : $rules->examBestOf;
                } else {
                    $sql = "SELECT COUNT(id) as columnCount FROM internal_assessment_column WHERE groupId = $groupId";
                    try {
                        $columnCount = $this->executeQueryForObject($sql)->columnCount;
                    }
                    catch (\Exception $e) {
                        throw new ProfessionalException($e->getCode(), $e->getMessage());
                    }
                    $numberOfColumns = abs ( $rules->examBestOf - $columnCount);
                }
                for ( $i = 0; $i < $numberOfColumns; $i++ ) {
                    $internalAssessmentColumnId = $this->createInternalAssessmentColumn ($internalAssessmentColumn, $groupId);
                    // Add InternalAssessmentExamRule(online exams) from $rule object
                    $this->addInternalAssessmentExamRule($rules, $internalAssessmentColumnId);
                    if($numberOfColumns==1){
                        $internalAssessmentColumn->id = $internalAssessmentColumnId;
                    }
                }
                $this->insertInernalAssessmentColumnOnlineExamMarks ( $internalAssessmentColumn, $rules, $groupId );
            break;
            default:
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_NO_RULE_DEFINED, "Invalid Rule for column:$internalAssessmentColumn->columnName");
                break;
        }
        return $internalAssessmentColumnId;
    }
    /**
     * Add attedance rules
     *
     * @throws ProfessionalException
     */
    public function addAttendanceRules($rules, $internalAssessmentColumnId) {
        $rules                      = $this->realEscapeObject($rules);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        // Switch between attendance rules
        switch ($rules->ruleType) {
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_MARK:
                $this->addInternalAssessmentAttendanceMarkRule($rules, $internalAssessmentColumnId);
                break;
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS:
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_PRESENT:
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_ABSENT:
                $this->addInternalAssessmentAttendanceFieldRule($rules, $internalAssessmentColumnId);
                break;
            default:
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_NO_RULE_DEFINED, "Invalid Rule for column:$internalAssessmentColumn->columnName");
                break;
        }
    }
    /**
     * Add attendance rule
     *
     * @param InternalAssessmentAttendanceRule $internalAssessmentAttendanceRule
     * @param int $internalAssessmentColumnId
     */
    public function addInternalAssessmentAttendanceFieldRule($internalAssessmentAttendanceRule, $internalAssessmentColumnId) {
        $internalAssessmentAttendanceRule = $this->realEscapeObject($internalAssessmentAttendanceRule);
        $internalAssessmentColumnId       = $this->realEscapeString($internalAssessmentColumnId);
        $sqlField                         = "";
        $sqlInput                         = "";
        if (!empty($internalAssessmentAttendanceRule->fromDate) && !empty($internalAssessmentAttendanceRule->toDate)) {
            $sqlField = ", fromDate, toDate";
            $sqlInput = " , '$internalAssessmentAttendanceRule->fromDate', '$internalAssessmentAttendanceRule->toDate'";
        }
        $sql = "INSERT INTO internal_assessment_attendance_rule (internalAssessmentColumnId, ruleType $sqlField) VALUES($internalAssessmentColumnId, '$internalAssessmentAttendanceRule->ruleType$sqlInput)";
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Add InternalAssessmentColumn and corresponding rule.
     *
     * @param InternalAssessmentColumn $internalAssessmentColumn
     * @param
     *            obj rules | object array rules
     * @return bool
     */
    public function updateInternalAssessmentColumn($internalAssessmentColumn, $rules = null) {
        if ($internalAssessmentColumn->ruleType == InternalAssessmentRuleType::FORMULA) {
            // $isFormulaValid = $this->validateInternalAssessmentFormula($rules->formula);
            $isFormulaValid = true;
            if (!$isFormulaValid) {
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_INVALID_FORMULA, "Invalid formula");
            }
        }
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $rules = $this->realEscapeObject($rules);
        // Insert InternalAssessmentColumn details. If ruletype of this column is not InternalAssessmentRuleType::FORMULA, totalMarks will be null and must be saved as 0. Otherwise save the totalMarks as it is.
        $sql = "UPDATE internal_assessment_column SET columnName = '".$internalAssessmentColumn->columnName."', totalMark = '".$internalAssessmentColumn->totalMark."', passPercent = '".$internalAssessmentColumn->passPercent."', updatedBy = ".$internalAssessmentColumn->updatedBy.", updatedDate = utc_timestamp() WHERE id = ".$internalAssessmentColumn->id."";
        try {
            $this->executeQuery($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        // Save corresponding rule to specific table by switching columnType of internalAssessmentColumn
        switch ($internalAssessmentColumn->ruleType) {
            case InternalAssessmentRuleType::EXAM:
                $groupId = getAssessmentGroupByColumnId($internalAssessmentColumn->id);
                $groupId = empty ( $groupId ) ? $this->createInternalAssessmentColumnGroup() : $groupId;
                $this->addRemoveInternalAssessmentExamColumnOnUpdate ( $internalAssessmentColumn, $rules );
                $this->updateInternalAssessmentColumnByGroupId ( $internalAssessmentColumn, $groupId );
                $this->updateInternalAssessmentExamRuleByGroupId ( $rules, $groupId );
                break;
            case InternalAssessmentRuleType::ASSIGNMENT:
                $groupId = getAssessmentGroupByColumnId($internalAssessmentColumn->id);
                $groupId = empty ( $groupId ) ? $this->createInternalAssessmentColumnGroup() : $groupId;
                $this->addRemoveInternalAssessmentAssignmentColumnOnUpdate ( $internalAssessmentColumn, $rules );
                $this->updateInternalAssessmentColumnByGroupId ( $internalAssessmentColumn, $groupId );
                $this->updateInternalAssessmentAssignmentRuleByGroupId ( $rules, $groupId );
                break;
            case InternalAssessmentRuleType::ATTENDANCE:
                // Update InternalAssessmentAttendanceRule from $rule object
                $this->updateAttendanceRules($rules);
                break;
            case InternalAssessmentRuleType::FORMULA:
                // Update InternalAssessmentFormulaRule from $rule object
                $this->updateInternalAssessmentFormulaRule($rules);
                break;
            case InternalAssessmentRuleType::FIELD:
                break;
            default:
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_NO_RULE_DEFINED, "Invalid Rule for column:$internalAssessmentColumn->columnName");
                break;
        }
        return $internalAssessmentColumnId;
    }
    /**
     * Update attedance rules
     *
     * @throws ProfessionalException
     */
    public function updateAttendanceRules($rules) {
        // Switch between attendance rules
        switch ($rules->ruleType) {
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_MARK:
                $this->updateInternalAssessmentAttendanceMarkRule($rules);
                break;
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS:
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_PRESENT:
            case InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_ABSENT:
                $this->updateInternalAssessmentAttendanceFieldRule ( $rules );
                break;
            default:
                throw new ProfessionalException(ProfessionalException::ASSESSMENT_NO_RULE_DEFINED, "Invalid Rule for column:$internalAssessmentColumn->columnName");
                break;
        }
    }
    /**
     * update assessment rule for attendance
     *
     * @param InternalAssessmentAttendanceRule $internalAssessmentAttendanceRule
     */
    public function updateInternalAssessmentAttendanceFieldRule($internalAssessmentAttendanceRule) {
        $internalAssessmentAttendanceRule = $this->realEscapeObject($internalAssessmentAttendanceRule);
        if (!empty($internalAssessmentAttendanceRule->fromDate) && !empty($internalAssessmentAttendanceRule->toDate)) {
            $sqlField = ", fromDate = '$internalAssessmentAttendanceRule->fromDate', toDate = '$internalAssessmentAttendanceRule->toDate'";
        }
        $sql = "UPDATE internal_assessment_attendance_rule SET ruleType='$internalAssessmentAttendanceRule->ruleType$sqlField WHERE  internalAssessmentColumnId=$internalAssessmentAttendanceRule->internalAssessmentColumnId";
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Add InternalAssessmentColumn and corresponding rule.
     *
     * @param InternalAssessmentColumn $internalAssessmentColumn
     * @param
     *            obj rules | object array rules
     * @return InternalAssessmentStudentColumnMark[]
     */
    public function getInternalAssessmentColumnById($internalAssesmentColumnId) {
        $internalAssessmentColumn  = null;
        $internalAssesmentColumnId = $this->realEscapeString($internalAssesmentColumnId);
        $sql = "SELECT id, internalAssessmentId, columnNo, columnName, ruleType, totalMark, passPercent, createdBy, updatedBy, updatedDate, createdDate, groupId FROM internal_assessment_column WHERE id = $internalAssesmentColumnId;";
        try {
            $internalAssessmentColumn = $this->executeQueryForObject($sql, false, $this->mapper[AssessmentServiceMapper::GET_ASSESSMENT_COLUMNS]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessmentColumn;
    }
    /**
     * Generate coloumnNo for an assessment
     *
     * @param int $internalAssessmentId
     * @return $newColumnNo
     */
    public function generateNextColumnNoById($internalAssessmentId) {
        $internalAssessmentId = $this->realEscapeString($internalAssessmentId);
        $newColumnNo = NULL;
        $sql         = "SELECT columnNo FROM internal_assessment_column WHERE internalAssessmentId=$internalAssessmentId ORDER BY id DESC limit 1";
        try
        {
            $columnNo    = $this->executeQueryForObject($sql)->columnNo;
            $newColumnNo = $columnNo?++$columnNo:'A';
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $newColumnNo;
    }
    /**
     * get assessment rule for exam
     *
     * @param int $internalAssessmentColumnId
     */
    public function getInternalAssessmentExamRule($internalAssessmentColumnId) {
        $internalAssessmentExamRule = null;
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "SELECT id,internalAssessmentColumnId, examTypeIDs, examMark, examBestOf, isExamAvg, ordinalNo FROM internal_assessment_exam_rule WHERE internalAssessmentColumnId = $internalAssessmentColumnId";
        try
        {
            $internalAssessmentExamRule = $this->executeQueryForObject($sql, false, $this->mapper[AssessmentServiceMapper::GETINTERNALASSESSMENTEXAMRULE]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessmentExamRule;
    }
    /**
     * Add assessment rule for exam
     *
     * @param InternalAssessmentExamRule $internalAssessmentExamRule
     * @param int $internalAssessmentColumnId
     */
    public function addInternalAssessmentExamRule($internalAssessmentExamRule, $internalAssessmentColumnId) {
        $internalAssessmentExamRule = $this->realEscapeObject($internalAssessmentExamRule);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "INSERT INTO internal_assessment_exam_rule (internalAssessmentColumnId, examTypeIDs, examMark, examBestOf, isExamAvg, ordinalNo) VALUES($internalAssessmentColumnId, '$internalAssessmentExamRule->examTypeIDs', $internalAssessmentExamRule->examMark$internalAssessmentExamRule->examBestOf$internalAssessmentExamRule->isExamAvg$internalAssessmentExamRule->ordinalNo)";
        try
        {
            $this->executeQuery($sql);
            foreach($internalAssessmentExamRule->markRange as $range){
                if(($range['from']!="") && ($range['to']!="") && ($range['mark']!="")){
                    $sqlMarkRange = "INSERT INTO internalAssessmentExamMarkRange(internalAssessmentColumnId,percentFrom,percentTo,marks) VALUES($internalAssessmentColumnId,$range[from],$range[to],$range[mark])";
                    $this->executeQuery($sqlMarkRange);
                }
                
            } 
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * update assessment rule for exam
     *
     * @param InternalAssessmentExamRule $internalAssessmentExamRule
     */
    public function updateInternalAssessmentExamRule($internalAssessmentExamRule) {
        $internalAssessmentExamRule = $this->realEscapeObject($internalAssessmentExamRule);
        $sql = "UPDATE internal_assessment_exam_rule SET examTypeIDs='$internalAssessmentExamRule->examTypeIDs', examMark=$internalAssessmentExamRule->examMark, examBestOf=$internalAssessmentExamRule->examBestOf, isExamAvg=$internalAssessmentExamRule->isExamAvg, ordinalNo=$internalAssessmentExamRule->ordinalNo WHERE internalAssessmentColumnId=$internalAssessmentExamRule->internalAssessmentColumnId";
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * get assessment rule for assignment
     *
     * @param int $internalAssessmentColumnId
     *
     * @return InternalAssessmentAssignmentRule
     */
    public function getInternalAssessmentAssignmentRule($internalAssessmentColumnId) {
        $internalAssessmentAssignmentRule = null;
        $internalAssessmentColumnId       = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "SELECT   id,internalAssessmentColumnId, assignmentNos, assignmentMark, assignmentBestOf, isassignmentAvg, ordinalNo FROM internal_assessment_assignment_rule WHERE internalAssessmentColumnId = $internalAssessmentColumnId";
        try
        {
            $internalAssessmentAssignmentRule = $this->executeQueryForObject($sql, false, $this->mapper[AssessmentServiceMapper::GETINTERNALASSESSMENTASSIGNMENTRULE]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessmentAssignmentRule;
    }
    /**
     * Add assessment rule for assignment
     *
     * @param InternalAssessmentAssignmentRule $internalAssessmentAssignmentRule
     * @param int $internalAssessmentColumnId
     */
    public function addInternalAssessmentAssignmentRule($internalAssessmentAssignmentRule, $internalAssessmentColumnId) {
        $internalAssessmentAssignmentRule = $this->realEscapeObject($internalAssessmentAssignmentRule);
        $internalAssessmentColumnId       = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "INSERT INTO internal_assessment_assignment_rule (internalAssessmentColumnId, assignmentNos, assignmentMark, assignmentBestOf, isassignmentAvg, ordinalNo) VALUES($internalAssessmentColumnId, '$internalAssessmentAssignmentRule->assignmentNos', $internalAssessmentAssignmentRule->assignmentMark$internalAssessmentAssignmentRule->assignmentBestOf$internalAssessmentAssignmentRule->isassignmentAvg$internalAssessmentAssignmentRule->ordinalNo)";
        try
        {
            $this->executeQuery($sql);
            foreach($internalAssessmentAssignmentRule->markRange as $range){
                if(($range['from']!="") && ($range['to']!="") && ($range['mark']!="")){
                    $sqlMarkRange = "INSERT INTO internal_assessment_assignment_mark_range(internalAssessmentColumnId,percentFrom,percentTo,marks) VALUES($internalAssessmentColumnId,$range[from],$range[to],$range[mark])";
                    $this->executeQuery($sqlMarkRange);
                }
                
            } 
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * update assessment rule for assignment
     *
     * @param InternalAssessmentAssignmentRule $internalAssessmentAssignmentRule
     * @param int $internalAssessmentColumnId
     */
    public function updateInternalAssessmentAssignmentRule($internalAssessmentAssignmentRule) {
        $internalAssessmentAssignmentRule = $this->realEscapeObject($internalAssessmentAssignmentRule);
        $sql = "UPDATE internal_assessment_assignment_rule SET assignmentNos='$internalAssessmentAssignmentRule->assignmentNos', assignmentMark=$internalAssessmentAssignmentRule->assignmentMark, assignmentBestOf=$internalAssessmentAssignmentRule->assignmentBestOf, isassignmentAvg=$internalAssessmentAssignmentRule->isassignmentAvg, ordinalNo=$internalAssessmentAssignmentRule->ordinalNo WHERE internalAssessmentColumnId=$internalAssessmentAssignmentRule->internalAssessmentColumnId";
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Get assessment rule for attendance
     *
     * @param int $internalAssessmentColumnId
     * @return InternalAssessmentAttendanceRule;
     */
    public function getInternalAssessmentAttendanceRule($internalAssessmentColumnId) {
        $internalAssessmentAttendanceRule = NULL;
        $internalAssessmentColumnId       = $this->realEscapeString($internalAssessmentColumnId);
        // foreach ($internalAssessmentAttendanceRules as $internalAssessmentAttendanceRule)
        // {
        $sql = "SELECT id,internalAssessmentColumnId, fromPerc, toPerc, marks, fromDate, toDate, ruleType from internal_assessment_attendance_rule WHERE internalAssessmentColumnId = $internalAssessmentColumnId";
        try
        {
            $internalAssessmentAttendanceRule = $this->executeQueryForObject($sql, FALSE, $this->mapper[AssessmentServiceMapper::GETINTERNALASSESSMENTATTENDANCERULE]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        // }
        return $internalAssessmentAttendanceRule;
    }
    
    /**
     * Get assessment rule for attendance
     *
     * @param int $internalAssessmentColumnId
     * @return InternalAssessmentAttendanceRule;
     */
    public function getInternalAssessmentGenderwiseAttendanceRule($internalAssessmentColumnId) {
        $internalAssessmentAttendanceRule = NULL;
        $internalAssessmentColumnId       = $this->realEscapeString($internalAssessmentColumnId);
        // foreach ($internalAssessmentAttendanceRules as $internalAssessmentAttendanceRule)
        // {
        $sql = "SELECT id,internalAssessmentColumnId, fromPerc, toPerc, marks, fromDate, toDate, ruleType,gender from internal_assessment_attendance_genderwise_rule WHERE internalAssessmentColumnId = $internalAssessmentColumnId";
        try
        {
            $internalAssessmentAttendanceRule = $this->executeQueryForObject($sql, FALSE, $this->mapper[AssessmentServiceMapper::GETINTERNALASSESSMENTGENDERWISEATTENDANCERULE]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        // }
        return $internalAssessmentAttendanceRule;
    }
    /**
     * Add assessment rule for attendance
     *
     * @param InternalAssessmentAttendanceRule $internalAssessmentAttendanceRule
     * @param int $internalAssessmentColumnId
     */
    public function addInternalAssessmentAttendanceMarkRule($internalAssessmentAttendanceRule, $internalAssessmentColumnId) {
        $internalAssessmentAttendanceRule = $this->realEscapeObject($internalAssessmentAttendanceRule);
        $internalAssessmentColumnId       = $this->realEscapeString($internalAssessmentColumnId);
        $sqlField                         = "";
        $sqlInput                         = "";
        if (!empty($internalAssessmentAttendanceRule->fromDate) && !empty($internalAssessmentAttendanceRule->toDate)) {
            $sqlField = ", fromDate, toDate";
            $sqlInput = " , '$internalAssessmentAttendanceRule->fromDate', '$internalAssessmentAttendanceRule->toDate'";
        }
        foreach ($internalAssessmentAttendanceRule->internalAssessmentAttendanceMarkRules as $internalAssessmentAttendanceMarkRule) {
            $internalAssessmentAttendanceMarkRule->marks = empty($internalAssessmentAttendanceMarkRule->marks)?0:$internalAssessmentAttendanceMarkRule->marks;
            if($internalAssessmentAttendanceMarkRule->gender)
            {
                $internalAssessmentAttendanceMarkRule->gender = strtoupper($internalAssessmentAttendanceMarkRule->gender);
                $sql = "INSERT INTO internal_assessment_attendance_genderwise_rule (internalAssessmentColumnId, ruleType, fromPerc, toPerc, marks,gender $sqlField) VALUES($internalAssessmentColumnId, '$internalAssessmentAttendanceRule->ruleType', $internalAssessmentAttendanceMarkRule->fromPerc$internalAssessmentAttendanceMarkRule->toPerc$internalAssessmentAttendanceMarkRule->marks,'$internalAssessmentAttendanceMarkRule->gender$sqlInput)";
            }
            else{
                $sql = "INSERT INTO internal_assessment_attendance_rule (internalAssessmentColumnId, ruleType, fromPerc, toPerc, marks $sqlField) VALUES($internalAssessmentColumnId, '$internalAssessmentAttendanceRule->ruleType', $internalAssessmentAttendanceMarkRule->fromPerc$internalAssessmentAttendanceMarkRule->toPerc$internalAssessmentAttendanceMarkRule->marks $sqlInput)";
            }
            try
            {
                $this->executeQuery($sql);
            }
             catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
        return true;
    }
    /**
     * update assessment rule for attendance
     *
     * @param InternalAssessmentAttendanceRule $internalAssessmentAttendanceRule
     */
    public function updateInternalAssessmentAttendanceMarkRule($internalAssessmentAttendanceRule) {
        $internalAssessmentAttendanceRule = $this->realEscapeObject($internalAssessmentAttendanceRule);
        if (!empty($internalAssessmentAttendanceRule->fromDate) && !empty($internalAssessmentAttendanceRule->toDate)) {
            $sqlField = ", fromDate = '$internalAssessmentAttendanceRule->fromDate', toDate = '$internalAssessmentAttendanceRule->toDate'";
        }
        $id = 0;
        $existingIds = [];
        foreach ($internalAssessmentAttendanceRule->internalAssessmentAttendanceMarkRules as $internalAssessmentAttendanceMarkRule) {
            $internalAssessmentAttendanceMarkRule->marks = empty($internalAssessmentAttendanceMarkRule->marks)?0:$internalAssessmentAttendanceMarkRule->marks;
            if($internalAssessmentAttendanceMarkRule->gender)
            {
                $internalAssessmentAttendanceMarkRule->gender= strtoupper($internalAssessmentAttendanceMarkRule->gender);
                if(!in_array($internalAssessmentAttendanceMarkRule->id,$existingIds)){
                    $sql = "UPDATE internal_assessment_attendance_genderwise_rule SET ruleType = '$internalAssessmentAttendanceRule->ruleType', fromPerc=$internalAssessmentAttendanceMarkRule->fromPerc, toPerc=$internalAssessmentAttendanceMarkRule->toPerc, marks=$internalAssessmentAttendanceMarkRule->marks $sqlField WHERE  id=$internalAssessmentAttendanceMarkRule->id AND gender ='$internalAssessmentAttendanceMarkRule->gender'";
                }
                
                else{
                    $sql = "INSERT INTO internal_assessment_attendance_genderwise_rule(fromPerc,toPerc,marks,ruleType,internalAssessmentColumnId,gender) values($internalAssessmentAttendanceMarkRule->fromPerc,$internalAssessmentAttendanceMarkRule->toPerc,$internalAssessmentAttendanceMarkRule->marks,'$internalAssessmentAttendanceRule->ruleType',$internalAssessmentAttendanceRule->internalAssessmentColumnId,'$internalAssessmentAttendanceMarkRule->gender')";
                }
                $existingIds[$id] = $internalAssessmentAttendanceMarkRule->id;
                $id++;
            }
            else
            {
                if(!in_array($internalAssessmentAttendanceMarkRule->id,$existingIds)){
                    $sql = "UPDATE internal_assessment_attendance_rule SET ruleType = '$internalAssessmentAttendanceRule->ruleType', fromPerc=$internalAssessmentAttendanceMarkRule->fromPerc, toPerc=$internalAssessmentAttendanceMarkRule->toPerc, marks=$internalAssessmentAttendanceMarkRule->marks $sqlField WHERE  id=$internalAssessmentAttendanceMarkRule->id";
                }
                
                else{
                    $sql = "INSERT INTO internal_assessment_attendance_rule(fromPerc,toPerc,marks,ruleType,internalAssessmentColumnId) values($internalAssessmentAttendanceMarkRule->fromPerc,$internalAssessmentAttendanceMarkRule->toPerc,$internalAssessmentAttendanceMarkRule->marks,'$internalAssessmentAttendanceRule->ruleType',$internalAssessmentAttendanceRule->internalAssessmentColumnId)";
                }
                $existingIds[$id] = $internalAssessmentAttendanceMarkRule->id;
                $id++;
            }
            
            try
            {
                $this->executeQuery($sql);
            }
             catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
        return true;
    }
    /**
     * Get assessment formula
     *
     * @param int $internalAssessmentColumnId
     * @return InternalAssessmentFormula
     */
    public function getInternalAssessmentFormulaRule($internalAssessmentColumnId) {
        $internalAssessmentFormula  = null;
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "SELECT id,internalAssessmentColumnId, formula FROM internal_assessment_formula WHERE internalAssessmentColumnId = $internalAssessmentColumnId";
        try
        {
            $internalAssessmentFormula = $this->executeQueryForObject($sql, false, $this->mapper[AssessmentServiceMapper::GETINTERNALASSESSMENTFORMULARULE]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessmentFormula;
    }
    /**
     * Add assessment formula
     *
     * @param InternalAssessmentFormula $internalAssessmentFormula
     * @param int $internalAssessmentColumnId
     */
    public function addInternalAssessmentFormulaRule($internalAssessmentFormula, $internalAssessmentColumnId) {
        $internalAssessmentFormula  = $this->realEscapeObject($internalAssessmentFormula);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "INSERT INTO internal_assessment_formula (internalAssessmentColumnId, formula) VALUES($internalAssessmentColumnId, '$internalAssessmentFormula->formula')";
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * update assessment formula
     *
     * @param InternalAssessmentFormula $internalAssessmentFormula
     */
    public function updateInternalAssessmentFormulaRule($internalAssessmentFormula) {
        $internalAssessmentFormula = $this->realEscapeObject($internalAssessmentFormula);
        $sql = "UPDATE internal_assessment_formula  SET formula='$internalAssessmentFormula->formula' WHERE internalAssessmentColumnId=$internalAssessmentFormula->internalAssessmentColumnId";
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * get Rulewise Student Exam marks
     *
     * @param InternalAssessmentExamRule $internalAssessmentExamRule
     * @param InternalAssessmentColumn $internalAssessmentColumn
     * @param InternalAssessment $internalAssessment
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @return InternalAssessmentStudentColumnMark[]
     *
     */
    public function getRulewiseStudentExamMarks($internalAssessmentExamRule, $internalAssessment, $internalAssessmentColumn, $internalAssessmentReq) {
        $internalAssessmentExamRule = $this->realEscapeObject($internalAssessmentExamRule);
        $internalAssessment         = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumn   = $this->realEscapeObject($internalAssessmentColumn);
        $internalAssessmentStudentColumnMarks = [];
        $totalColumnMarks                     = 0;
        $totalStudents  = NULL;
        $studentsPassed = NULL;
        $passedPercent  = NULL;
        $studentsFailed = NULL;
        $absenteesNo    = NULL;
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumn->id, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
        // Calculating total mark
        if (($internalAssessmentExamRule->isExamAvg) || ($internalAssessmentExamRule->ordinalNo != 0)) {
            $totalColumnMarks = $internalAssessmentExamRule->examMark;
        } else {
            for ($i = 0; $i < $internalAssessmentExamRule->examBestOf; $i++) {
                $totalColumnMarks += $internalAssessmentExamRule->examMark;
            }
        }
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId;
        }
        // Retrieving students of given batchId
        
        if ($internalAssessment->batchId != NULL && $internalAssessment->semId != NULL) {
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            if ($isCurrentSem) {
                $sql_students = "SELECT studentID, studentName, rollNo, regNo FROM  studentaccount WHERE batchID = ".$internalAssessment->batchId." order by rollNo";
            } else {
                $sql_students = "SELECT sa.studentID, sa.studentName, sa.rollNo, sa.regNo FROM studentaccount sa INNER JOIN batches ba ON sa.batchID =  ba.batchID WHERE ba.batchID = $internalAssessment->batchId  UNION SELECT sa.studentID, sa.studentName, sa.rollNo, sa.regNo FROM failed_students fs LEFT JOIN studentaccount sa ON fs.studentID= sa.studentID WHERE previousBatch = $internalAssessment->batchId AND failedInSemester > $internalAssessment->semId ORDER BY rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
        }
        if ($studentDetails != NULL) {
            $totalStudents = count($studentDetails);
            foreach ($studentDetails as $studentDetail) {
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumn->id;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                // Retrieving marks obtained in given subject
                $sql_ex_mark        = "SELECT t1.examTypeID, t1.subjectID, t1.marksObtained, t1.percentage FROM student_marks t1 WHERE t1.studentID = ".$studentDetail->studentID." AND t1.subjectID = ".$internalAssessment->subjectId." order by t1.examTypeID asc, t1.percentage desc";
                $studentMarkDetails = $this->executeQueryForList($sql_ex_mark);
                $typeIDs = explode(",", $internalAssessmentExamRule->examTypeIDs);
                if ($studentMarkDetails != NULL) {
                    foreach ($studentMarkDetails as $studentMarkDetail) {
                        $stud_exam_mark[$studentMarkDetail->examTypeID]    = $studentMarkDetail->marksObtained;
                        $stud_exam_percent[$studentMarkDetail->examTypeID] = $studentMarkDetail->percentage;
                    }
                    foreach ($typeIDs as $examTypeID) {
                        if ($stud_exam_percent[$examTypeID]) {
                            if ((count($typeIDs) == 1) && ($stud_exam_mark[$examTypeID] == -1)) {
                                $absenteesNo++;
                            }
                            $exam_type_marks[] = ($stud_exam_percent[$examTypeID]*$internalAssessmentExamRule->examMark)/100;
                        } else {
                            $exam_type_marks[] = -1;
                        }
                    }
                    if (is_array($exam_type_marks)) {
                        rsort($exam_type_marks);
                        if ($internalAssessmentExamRule->examBestOf) {
                            if ($internalAssessmentExamRule->isExamAvg) {
                                $sum  = 0;
                                $sum1 = 0;
                                for ($i = 0; $i < $internalAssessmentExamRule->examBestOf; $i++) {
                                    if ($exam_type_marks[$i] >= 0) {
                                        $sum += $exam_type_marks[$i];
                                        $sum1 = 1;
                                    }
                                }
                                $average = $sum/$internalAssessmentExamRule->examBestOf;
                                $total_sub += $average;
                                $internalAssessmentStudentColumnMark->marks = ($sum1)?$average:NULL;
                            } else if ($internalAssessmentExamRule->ordinalNo != 0) {
                                if ($exam_type_marks[$internalAssessmentExamRule->ordinalNo-1] >= 0) {
                                    $internalAssessmentStudentColumnMark->marks = $exam_type_marks[$internalAssessmentExamRule->ordinalNo-1];
                                } else {
                                    $internalAssessmentStudentColumnMark->marks = NULL;
                                }
                            } else {
                                for ($i = 0; $i < $internalAssessmentExamRule->examBestOf; $i++) {
                                    if ($exam_type_marks[$i] >= 0) {
                                        $internalAssessmentStudentColumnMark->marks = $exam_type_marks[$i];
                                    } else {
                                        $internalAssessmentStudentColumnMark->marks = NULL;
                                    }
                                }
                            }
                        } else {
                            $sum  = 0;
                            $sum1 = 0;
                            for ($i = 0; $i < $internalAssessmentExamRule->examBestOf; $i++) {
                                if ($exam_type_marks[$i] >= 0) {
                                    $sum += $exam_type_marks[$i];
                                    $sum1 = 1;
                                }
                            }
                            $average = $sum/count($typeIDs);
                            $total_sub += $average;
                            if ($sum1) {
                                $internalAssessmentStudentColumnMark->marks = $average;
                            } else {
                                $internalAssessmentStudentColumnMark->marks = NULL;
                            }
                        }
                        unset($exam_type_marks);
                        unset($stud_exam_mark);
                        unset($stud_exam_percent);
                    }
                }
                $internalAssessmentStudentColumnMark->marks = empty($internalAssessmentStudentColumnMark->marks)?0:round($internalAssessmentStudentColumnMark->marks, 2);
                if ($internalAssessmentColumn->passPercent != NULL) {
                    if ((($internalAssessmentStudentColumnMark->marks/$totalColumnMarks)*100) >= $internalAssessmentColumn->passPercent) {
                        $studentsPassed++;
                    } else {
                        $studentsFailed++;
                    }
                }
                // Saving column Marks
                $this->saveStudentColumnMarks($internalAssessmentColumn->id, $internalAssessmentStudentColumnMark->studentId, $internalAssessmentStudentColumnMark->marks, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
            }
            // Calculating pass percent and other aspects
            $passedPercent = round(($studentsPassed/$totalStudents)*100, 2);
            // Update total mark of assessment column.
            $this->updateColumnDetailsById($internalAssessmentColumn->id, $totalColumnMarks, $internalAssessmentReq, $studentsPassed, $studentsFailed, $passedPercent, $absenteesNo);
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get Rulewise Student Assignment marks
     *
     * @param InternalAssessmentAssignmentRule $internalAssessmentAssignmentRule
     * @param int $internalAssessmentColumnId
     * @param InternalAssessment $internalAssessment
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @return InternalAssessmentStudentColumnMark[]
     */
    public function getRulewiseStudentAssignmentMarks($internalAssessmentAssignmentRule, $internalAssessment, $internalAssessmentColumnId, $internalAssessmentReq) {
        $internalAssessmentAssignmentRule = $this->realEscapeObject($internalAssessmentAssignmentRule);
        $internalAssessment               = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumnId       = $this->realEscapeString($internalAssessmentColumnId);
        $internalAssessmentStudentColumnMarks = [];
        $totalColumnMarks                     = 0;
        $studentDetails = NULL;
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumnId, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
        // Calculating total mark
        if (($internalAssessmentAssignmentRule->isassignmentAvg) || ($internalAssessmentAssignmentRule->ordinalNo != 0)) {
            $totalColumnMarks = $internalAssessmentAssignmentRule->assignmentMark;
        } else {
            for ($i = 0; $i < $internalAssessmentAssignmentRule->assignmentBestOf; $i++) {
                $totalColumnMarks += $internalAssessmentAssignmentRule->assignmentMark;
            }
        }
        // Update total mark of assessment column.
        $this->updateColumnDetailsById($internalAssessmentColumnId, $totalColumnMarks, $internalAssessmentReq);
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId;
        }
        // Retrieving students of given batchId
        
        if ($internalAssessment->batchId != NULL && $internalAssessment->semId != NULL) {
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            if ($isCurrentSem) {
                $sql_students = "SELECT studentID, studentName, rollNo, regNo FROM  studentaccount WHERE batchID=".$internalAssessment->batchId." order by rollNo";
            } else {
                $sql_students = "select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from studentaccount sa inner join batches ba on sa.batchID =  ba.batchID where ba.batchID = $internalAssessment->batchId  union select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from failed_students fs left join studentaccount sa on fs.studentID= sa.studentID where previousBatch = $internalAssessment->batchId and failedInSemester > $internalAssessment->semId order by rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
        }
        if ($studentDetails != NULL) {
            foreach ($studentDetails as $studentDetail) {
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumnId;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                // Retrieving marks obtained in given subject
                $sql_asgn_mark = "SELECT  t1.subjectID, t1.assiNu, t2.marksObtained, t2.percentage FROM assignment_marks t2, batch_assignment t1 where t1.assignmentID = t2.assignmentID AND t2.studentID=".$studentDetail->studentID." AND t1.subjectID = ".$internalAssessment->subjectId." order by t1.assiNu DESC, t2.percentage desc";
                $studentMarkDetails = $this->executeQueryForList($sql_asgn_mark);
                $typeIDs = explode(",", $internalAssessmentAssignmentRule->assignmentNos);
                if ($studentMarkDetails != NULL) {
                    foreach ($studentMarkDetails as $studentMarkDetail) {
                        $stud_asgn_mark[$studentMarkDetail->assiNu]    = $studentMarkDetail->marksObtained;
                        $stud_asgn_percent[$studentMarkDetail->assiNu] = $studentMarkDetail->percentage;
                    }
                    foreach ($typeIDs as $assigngroupID) {
                        if ($stud_asgn_percent[$assigngroupID]) {
                            $asgn_type_marks[] = ($stud_asgn_percent[$assigngroupID]*$internalAssessmentAssignmentRule->assignmentMark)/100;
                        } else {
                            $asgn_type_marks[] = -1;
                        }
                    }
                    if (is_array($asgn_type_marks)) {
                        rsort($asgn_type_marks);
                        if ($internalAssessmentAssignmentRule->assignmentBestOf) {
                            if ($internalAssessmentAssignmentRule->isassignmentAvg) {
                                $sum  = 0;
                                $sum2 = 0;
                                for ($i = 0; $i < $internalAssessmentAssignmentRule->assignmentBestOf; $i++) {
                                    if ($asgn_type_marks[$i] >= 0) {
                                        $sum += $asgn_type_marks[$i];
                                        $sum2 = 1;
                                    }
                                }
                                $average = $sum/$internalAssessmentAssignmentRule->assignmentBestOf;
                                $total_sub += $average;
                                $internalAssessmentStudentColumnMark->marks = ($sum2)?$average:NULL;
                            } else if ($internalAssessmentAssignmentRule->ordinalNo != 0) {
                                if ($asgn_type_marks[$internalAssessmentAssignmentRule->ordinalNo-1] >= 0) {
                                    $internalAssessmentStudentColumnMark->marks = $asgn_type_marks[$internalAssessmentAssignmentRule->ordinalNo-1];
                                } else {
                                    $internalAssessmentStudentColumnMark->marks = NULL;
                                }
                            } else {
                                for ($i = 0; $i < $internalAssessmentAssignmentRule->assignmentBestOf; $i++) {
                                    if ($asgn_type_marks[$i] >= 0) {
                                        $internalAssessmentStudentColumnMark->marks = $asgn_type_marks[$i];
                                    } else {
                                        $internalAssessmentStudentColumnMark->marks = NULL;
                                    }
                                }
                            }
                        } else {
                            $sum  = 0;
                            $sum2 = 0;
                            for ($i = 0; $i < $internalAssessmentAssignmentRule->assignmentBestOf; $i++) {
                                if ($asgn_type_marks[$i] >= 0) {
                                    $sum += $asgn_type_marks[$i];
                                    $sum2 = 1;
                                }
                            }
                            $average = $sum/count($typeIDs);
                            $total_sub += $average;
                            if ($sum2) {
                                $internalAssessmentStudentColumnMark->marks = $average;
                            } else {
                                $internalAssessmentStudentColumnMark->marks = NULL;
                            }
                        }
                        $internalAssessmentStudentColumnMark->marks = empty($internalAssessmentStudentColumnMark->marks)?0:round($internalAssessmentStudentColumnMark->marks, 2);
                        unset($asgn_type_marks);
                        unset($stud_asgn_mark);
                        unset($stud_asgn_percent);
                    }
                }
                // Saving column Marks
                $this->saveStudentColumnMarks($internalAssessmentColumnId, $internalAssessmentStudentColumnMark->studentId, $internalAssessmentStudentColumnMark->marks, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
            }
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get Rulewise Student Attendance marks
     *
     * @param int $internalAssessmentColumnId
     * @param InternalAssessment $internalAssessment
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @return InternalAssessmentStudentColumnMark[]
     *
     */
    public function getRulewiseStudentAttendanceByMarkRule($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq) {
        $internalAssessment         = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $internalAssessmentStudentColumnMarks = [];
        $totalMark                            = 0;
        $fromDate                             = NULL;
        $toDate                               = NULL;
        $attCond                              = "";
        $studentDetails                       = null;
        $psId = $internalAssessment->psId? $internalAssessment->psId:$internalAssessmentReq->psId;
        
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumnId, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId,$psId);
        // Evaluate totalmark of column
        $sql           = "SELECT MAX(marks) as maxMark, fromDate, toDate FROM internal_assessment_attendance_rule WHERE internalAssessmentColumnId=$internalAssessmentColumnId";
        $attRuleResult = $this->executeQueryForObject($sql);
        $totalMark = $attRuleResult->maxMark;
        $fromDate  = $attRuleResult->fromDate;
        $toDate    = $attRuleResult->toDate;
        // $fromDate = "2017-01-01";
        // $toDate = "2018-01-01";
        // Update total mark of assessment column.
        $this->updateColumnDetailsById($internalAssessmentColumnId, $totalMark, $internalAssessmentReq);
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId;
        }
        // Retrieving students of given batchId
        
        if (!empty($internalAssessment->batchId) && !empty($internalAssessment->semId)) {
            
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            
            if($isCurrentSem)
            {
                $sql_students = "select sa.studentID, sa.studentName,sa.rollNo, regNo from  studentaccount sa inner join batches ba on  ba.batchID = sa.batchID  inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where sa.batchID= $internalAssessment->batchId and joinedSem.orderNo <= sem.orderNo ORDER BY sa.rollNo";
            }
            else
            {
                
                $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
                
                $sql_students = "select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from studentaccount sa inner join batches ba on sa.batchID =  ba.batchID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where ba.batchID = $internalAssessment->batchId and joinedSem.orderNo <= $semDetails->orderNo union select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from failed_students fs left join studentaccount sa on fs.studentID= sa.studentID inner join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where previousBatch = $internalAssessment->batchId and fsem.orderNo > $semDetails->orderNo and joinedSem.orderNo <= $semDetails->orderNo order by rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
            
        }
        if($psId){
            $studentDetails = StudentService::getInstance()->getStudentsAssignedToApseudoSub($psId);
        }
        
        if ($studentDetails != NULL) {
            if (!empty($fromDate) && !empty($toDate)) {
                $attCond = " AND att.attendanceDate BETWEEN '$fromDate' AND '$toDate'";
            }
            foreach ($studentDetails as $studentDetail) {
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumnId;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                $sql = "SELECT (
                    COUNT(CASE WHEN  att.isAbsent=0 OR att.isAbsent=2 THEN 1 END)/
                    COUNT(att.studentID)) * 100 AS attPercent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID AND att.semID=$internalAssessment->semId $attCond";
                if($psId){
                    $sql = "SELECT (
                        COUNT(CASE WHEN  att.isAbsent=0 OR att.isAbsent=2 THEN 1 END)/
                        COUNT(att.studentID)) * 100 AS attPercent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID $attCond";
                }    
                $studAttPerc = $this->executeQueryForObject($sql)->attPercent;
                if (!empty($studAttPerc)) {
                    $sql     = "SELECT marks FROM internal_assessment_attendance_rule WHERE internalAssessmentColumnId=$internalAssessmentColumnId AND $studAttPerc BETWEEN fromPerc AND toPerc";
                    $attMark = $this->executeQueryForObject($sql)->marks;
                } else {
                    $attMark = 0;
                }
                $internalAssessmentStudentColumnMark->marks = round($attMark, 2);
                // Saving column Marks
                if($psId){
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $attMark, $studentDetail->batchID, $internalAssessmentReq->subjectId);
                }
                else{
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $attMark, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                }
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
            }
        }
        return $internalAssessmentStudentColumnMarks;
    }
    public function getRulewiseStudentGenderwiseAttendanceByMarkRule($internalAssessmentColumnId, $internalAssessment, $internalAssessmentReq) {
        $internalAssessment         = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $internalAssessmentStudentColumnMarks = [];
        $totalMark                            = 0;
        $fromDate                             = NULL;
        $toDate                               = NULL;
        $attCond                              = "";
        $studentDetails                       = null;
        $psId = $internalAssessment->psId? $internalAssessment->psId:$internalAssessmentReq->psId;
        
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumnId, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId,$psId);
        // Evaluate totalmark of column
        $sql = "SELECT MAX(marks) as maxMark, fromDate, toDate,gender FROM internal_assessment_attendance_genderwise_rule WHERE internalAssessmentColumnId=$internalAssessmentColumnId";
        $attRuleResult = $this->executeQueryForObject($sql);
        $totalMark = $attRuleResult->maxMark;
        $fromDate  = $attRuleResult->fromDate;
        $toDate    = $attRuleResult->toDate;
        // $fromDate = "2017-01-01";
        // $toDate = "2018-01-01";
        // Update total mark of assessment column.
        $this->updateColumnDetailsById($internalAssessmentColumnId, $totalMark, $internalAssessmentReq);
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId;
        }
        // Retrieving students of given batchId
        
        if (!empty($internalAssessment->batchId) && !empty($internalAssessment->semId)) {
            
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            
            if($isCurrentSem)
            {
                $sql_students = "select sa.studentID, sa.studentName,sa.rollNo, regNo from  studentaccount sa inner join batches ba on  ba.batchID = sa.batchID  inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where sa.batchID= $internalAssessment->batchId and joinedSem.orderNo <= sem.orderNo ORDER BY sa.rollNo";
            }
            else
            {
                
                $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
                
                $sql_students = "select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from studentaccount sa inner join batches ba on sa.batchID =  ba.batchID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where ba.batchID = $internalAssessment->batchId and joinedSem.orderNo <= $semDetails->orderNo union select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from failed_students fs left join studentaccount sa on fs.studentID= sa.studentID inner join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where previousBatch = $internalAssessment->batchId and fsem.orderNo > $semDetails->orderNo and joinedSem.orderNo <= $semDetails->orderNo order by rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
            
        }
        if($psId){
            $studentDetails = StudentService::getInstance()->getStudentsAssignedToApseudoSub($psId);
        }
        
        if ($studentDetails != NULL) {
            if (!empty($fromDate) && !empty($toDate)) {
                $attCond = " AND att.attendanceDate BETWEEN '$fromDate' AND '$toDate'";
            }
            foreach ($studentDetails as $studentDetail) {
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumnId;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                $sql = "SELECT (
                    COUNT(CASE WHEN  att.isAbsent=0 OR att.isAbsent=2 THEN 1 END)/
                    COUNT(att.studentID)) * 100 AS attPercent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID AND att.semID=$internalAssessment->semId $attCond";
                if($psId){
                    $sql = "SELECT (
                        COUNT(CASE WHEN  att.isAbsent=0 OR att.isAbsent=2 THEN 1 END)/
                        COUNT(att.studentID)) * 100 AS attPercent FROM attendance att, sbs_relation sbs WHERE att.sbsID = sbs.sbsID and sbs.subjectID = ".$internalAssessment->subjectId." AND att.studentID = $studentDetail->studentID $attCond";
                }    
                $studAttPerc = $this->executeQueryForObject($sql)->attPercent;
                if (!empty($studAttPerc)) {
                    $sql     = "SELECT marks,gender FROM internal_assessment_attendance_genderwise_rule WHERE internalAssessmentColumnId=$internalAssessmentColumnId AND  $studAttPerc BETWEEN fromPerc AND toPerc";
                    $attMark = $this->executeQueryForList($sql);
                } else {
                    $attMark = 0;
                }
                $internalAssessmentStudentColumnMark->marks = round($attMark, 2);
                // Saving column Marks
                if($psId){
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $attMark, $studentDetail->batchID, $internalAssessmentReq->subjectId, true);
                }
                else{
                    $this->saveStudentColumnMarks($internalAssessmentColumnId, $studentDetail->studentID, $attMark, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId, true);
                }
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
            }
        }
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get Rulewise Student by formula
     *
     * @param InternalAssessmentFormula $internalAssessmentFormula
     * @param InternalAssessmentColumn $internalAssessmentColumn
     * @param InternalAssessment $internalAssessment
     * @return InternalAssessmentStudentColumnMark[]
     *
     */
    public function getFormulawiseStudentMarks($internalAssessmentFormula, $internalAssessment, $internalAssessmentColumn, $internalAssessmentReq) {
        $internalAssessmentFormula            = $this->realEscapeObject($internalAssessmentFormula);
        $internalAssessment                   = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumn             = $this->realEscapeObject($internalAssessmentColumn);
        $internalAssessmentReq                = $this->realEscapeObject($internalAssessmentReq);
        $internalAssessmentStudentColumnMarks = [];
        $formula_temp                         = NULL;
        $variables[]                          = NULL;
        $values[]                             = NULL;
        $mark                                 = 0;
        $totalStudents  = NULL;
        $studentsPassed = NULL;
        $passedPercent  = NULL;
        $studentsFailed = NULL;
        $absenteesNo    = NULL;
        $studentDetails = null;
        $psId = $internalAssessment->psId? $internalAssessment->psId:$internalAssessmentReq->psId;
        // Deleting marks if existing
        $this->deleteStudentColumnMarks($internalAssessmentColumn->id, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId,$psId);
        
        if ($internalAssessment->batchId == NULL && $internalAssessment->semId == NULL) {
            $internalAssessment->batchId   = $internalAssessmentReq->batchId;
            $internalAssessment->semId     = $internalAssessmentReq->semId;
            $internalAssessment->subjectId = $internalAssessmentReq->subjectId?$internalAssessmentReq->subjectId:$internalAssessment->subjectId;
        }
        // Retrieving students of given batchId
        if ($internalAssessment->batchId && $internalAssessment->semId) {
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            if($isCurrentSem)
            {
                $sql_students = "select sa.studentID, sa.studentName,sa.rollNo, regNo from  studentaccount sa inner join batches ba on  ba.batchID = sa.batchID  inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where sa.batchID= $internalAssessment->batchId and joinedSem.orderNo <= sem.orderNo ORDER BY sa.rollNo";
            }
            else
            {
                
                $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
                
                $sql_students = "select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from studentaccount sa inner join batches ba on sa.batchID =  ba.batchID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where ba.batchID = $internalAssessment->batchId and joinedSem.orderNo <= $semDetails->orderNo union select sa.studentID, sa.studentName, sa.rollNo, sa.regNo from failed_students fs left join studentaccount sa on fs.studentID= sa.studentID inner join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where previousBatch = $internalAssessment->batchId and fsem.orderNo > $semDetails->orderNo and joinedSem.orderNo <= $semDetails->orderNo order by rollNo";
            }
            $studentDetails = $this->executeQueryForList($sql_students);
        }
        if($psId){
            $studentDetails = StudentService::getInstance()->getStudentsAssignedToApseudoSub($psId);
        }
        if ($studentDetails != NULL) {
            $variables = array_unique(preg_split("/[-+*\/^%\(\)]/", $internalAssessmentFormula->formula, -1, PREG_SPLIT_NO_EMPTY));
            $variables = array_filter($variables, function ($arrayEntry) {
                    return !is_numeric($arrayEntry);
                });
            usort($variables, function ($a, $b) {
                    return strlen($b)-strlen($a);
                });
            $totalStudents = count($studentDetails);
            foreach ($studentDetails as $studentDetail) {
                $mark = 0;
                $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
                $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $internalAssessmentColumn->id;
                $internalAssessmentStudentColumnMark->studentId                  = $studentDetail->studentID;
                $values[]     = NULL;
                $formula_temp = $internalAssessmentFormula->formula;
                if(!$psId){
                    $values = $this->getVariableValues($studentDetail->studentID, $variables, $internalAssessment->id, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                }
                else{
                    $values = $this->getVariableValues($studentDetail->studentID, $variables, $internalAssessment->id, $studentDetail->batchID, $internalAssessmentReq->subjectId);
                }
                $convertMarks = 1;
                foreach ($variables as $variable) {
                    if ($values[$variable] != NULL) {
                        $formula_temp = str_replace($variable, $values[$variable], $formula_temp);
                        if($this->isColumnRuleTypeAttendanceHours($variable, $internalAssessment->id))
                        {
                            $convertMarks = 0;
                        }
                    }
                }
                // Evaluating formula.
                $mark = eval('return '.$formula_temp.';');
                if ( IS_NAN($mark) || IS_INFINITE($mark) || empty($mark) ) {
                    $mark = 0;
                } else {
                    $mark = round($mark, 2);
                }
                
//                 if($convertMarks)
//                 {
//                     $totalMark = $internalAssessmentFormula->formula;
//                     foreach ($variables as $variable) {
//                         $columnTotalMark = $this->getInternalAssessmentColumnByColumnNo($variable, $internalAssessment->id)->totalMark;
//                         $totalMark = str_replace($variable, $columnTotalMark, $totalMark);
//                     }
                    
//                     $totalMark = eval('return '.$totalMark.';');
//                     $mark = ($mark/$totalMark)* $internalAssessmentColumn->totalMark;
//                 }
                
                $internalAssessmentStudentColumnMark->marks = $mark;
                if ($internalAssessmentStudentColumnMark->marks > $internalAssessmentColumn->totalMark) {
                    $internalAssessmentStudentColumnMark->marks = $internalAssessmentColumn->totalMark;
                }
                // Saving column Marks
                if($psId){
                    $this->saveStudentColumnMarks($internalAssessmentColumn->id, $studentDetail->studentID, $internalAssessmentStudentColumnMark->marks, $studentDetail->batchID, $internalAssessmentReq->subjectId);
                }
                else{
                    $this->saveStudentColumnMarks($internalAssessmentColumn->id, $studentDetail->studentID, $internalAssessmentStudentColumnMark->marks, $internalAssessmentReq->batchId, $internalAssessmentReq->subjectId);
                }
                $internalAssessmentStudentColumnMarks[] = $internalAssessmentStudentColumnMark;
                if ($internalAssessmentColumn->passPercent != NULL) {
                    if ((($internalAssessmentStudentColumnMark->marks/$internalAssessmentColumn->totalMark)*100) >= $internalAssessmentColumn->passPercent) {
                        $studentsPassed++;
                    } else {
                        $studentsFailed++;
                    }
                }
            }
            // Calculating pass percent and other aspects
            $passedPercent = round(($studentsPassed/$totalStudents)*100, 2);
            // Update total mark of assessment column.
            $this->updateColumnDetailsById($internalAssessmentColumn->id, $internalAssessmentColumn->totalMark, $internalAssessmentReq, $studentsPassed, $studentsFailed, $passedPercent, $absenteesNo);
        }
        return $internalAssessmentStudentColumnMarks;
    }
    public function getVariableValues($studentId, $variables, $internalAssessmentId, $batchId, $subjectId) {
        $studentId            = $this->realEscapeString($studentId);
        $variables            = $this->realEscapeArray($variables);
        $internalAssessmentId = $this->realEscapeString($internalAssessmentId);
        $batchId              = $this->realEscapeString($batchId);
        $subjectId            = $this->realEscapeString($subjectId);
        $values               = [];
        foreach ($variables as $variable) {
            $sql = "SELECT clmn_mark.marks FROM internal_assessment_column clmn
            INNER JOIN internal_assessment_student_column_mark clmn_mark ON clmn.id = clmn_mark.internalAssessmentColumnId
            WHERE clmn.internalAssessmentId = $internalAssessmentId AND clmn.columnNo='$variable' AND studentId=$studentId AND clmn_mark.batchId=$batchId AND clmn_mark.subjectId=$subjectId";
            try
            {
                $value = $this->executeQueryForObject($sql)->marks;
                if ($value) {
                    $values[$variable] = $value;
                }
            }
             catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
        return $values;
    }
    /**
     * get student internal assessment marks by assessmentId
     *
     * @param int $assessmentId
     * @throws ProfessionalException
     * @return object|array|\com\linways\base\util\$objectList[]
     */
    public function getAssessmentReport($assessmentId, $semId, $batchId, $subjectId,$pssuid = null,$studentsAssignedToSelectedBatchOnly = true) {
        $assessmentReport = NULL;
        $assessmentDetails = $this->getInternalAssessmentById($assessmentId);
        if ($assessmentDetails->batchId == NULL && $assessmentDetails->semId == NULL && $batchId == NULL) {
            return $assessmentReport;
        }
        $assessmentId = $this->realEscapeString($assessmentId);
        $semId        = $this->realEscapeString($semId);
        $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($batchId, $semId);
        if ($isCurrentSem) {
            $sql = "SELECT sa.studentID, sa.studentName,sa.regNo, sa.rollNo, iac.columnName,iac.columnNo, iam.marks, iac.id, iac.ruleType, iac.totalMark FROM studentaccount sa inner join batches ba on ba.batchID = sa.batchID inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID INNER JOIN internal_assessment ia ON (sa.batchId = IF(ia.batchID <> NULL, ia.batchID, '$batchId' )) LEFT JOIN internal_assessment_column iac ON iac.internalAssessmentId=ia.id LEFT JOIN internal_assessment_student_column_mark iam ON iam.internalAssessmentColumnId=iac.id AND sa.studentID=iam.studentId AND iam.batchId=$batchId AND iam.subjectId=$subjectId WHERE ia.id=$assessmentId and joinedSem.orderNo <= sem.orderNo  ORDER BY sa.rollNo, iac.columnNo";
            
        } else {
            $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($semId);
            
            $sql = "SELECT sa.studentID, sa.studentName,sa.regNo, sa.rollNo, iac.columnName,iac.columnNo, iam.marks, iac.id, iac.ruleType, iac.totalMark FROM studentaccount sa LEFT JOIN failed_students fs on sa.studentID = fs.studentID AND fs.reason <> 'BATCH_SHUFFLE' INNER JOIN internal_assessment ia ON (sa.batchId = IF(ia.batchID <> NULL, ia.batchID, '$batchId' ) or fs.previousBatch = IF(ia.batchID <> NULL, ia.batchID, '$batchId' )) left join semesters fsem on fsem.semID = fs.failedInSemester  inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID LEFT JOIN internal_assessment_column iac ON iac.internalAssessmentId=ia.id LEFT JOIN internal_assessment_student_column_mark iam ON iam.internalAssessmentColumnId=iac.id AND sa.studentID=iam.studentId AND iam.batchId=$batchId AND iam.subjectId=$subjectId WHERE ia.id='$assessmentId'  and (fsem.orderNo > $semDetails->orderNo or fsem.orderNo is null)  and joinedSem.orderNo <= $semDetails->orderNo ORDER BY sa.rollNo, iac.columnNo";
        }
        if($pssuid){
            $studentsAssignedToSelectedBatch = "";
            $joinCondition = " ia.id = $assessmentId ";
            if($studentsAssignedToSelectedBatchOnly) {
                $studentsAssignedToSelectedBatch = " AND iam.batchId=$batchId";
                $joinCondition = " (sa.batchId = IF(ia.batchID <> NULL, ia.batchID, '$batchId' )) ";
            }
            $sql = "SELECT sa.studentID, studentName,sa.regNo, sa.rollNo, ba.batchID,iac.columnName,iac.columnNo, iam.marks, iac.id, iac.ruleType, iac.totalMark 
            FROM pseudosubjects_students pss 
            INNER JOIN studentaccount sa ON pss.studentID = sa.studentID 
            INNER JOIN batches ba ON ba.batchID = sa.batchID 
            INNER JOIN department de ON de.deptID = ba.deptID 
            INNER JOIN internal_assessment ia ON $joinCondition
            LEFT JOIN internal_assessment_column iac ON iac.internalAssessmentId=ia.id LEFT JOIN internal_assessment_student_column_mark iam ON iam.internalAssessmentColumnId=iac.id AND pss.studentID=iam.studentId $studentsAssignedToSelectedBatch AND iam.subjectId=$subjectId  WHERE ia.id=$assessmentId and  pss.pseudosubjectID =$pssuid order by ba.batchID , iac.columnNo";
        }
        try
        {
            $assessmentReport = $this->executeQueryForList($sql, $this->mapper[AssessmentServiceMapper::GET_ASSESSMENT_REPORT]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $assessmentReport;
    }
    /**
     * Get assessment column by assessmentId
     *
     * @param int $assessmentId
     * @param int $batchId
     * @param int $subjectId
     * @throws ProfessionalException
     * @return object|array|\com\linways\base\util\$objectList[]
     */
    public function getAssessmentColumns($assessmentId, $batchId = 0, $subjectId = 0) {
        $assessmentColumn = NULL;
        $assessmentId     = $this->realEscapeString($assessmentId);
        $sql              = "SELECT iam.id, iam.internalAssessmentId, iam.columnNo, iam.columnName, iam.ruleType, iam.passPercent, iams.studentsPassed, iams.studentsFailed, iams.passedPercent, iam.totalMark, iams.absenteesNo, iam.groupId FROM internal_assessment_column iam LEFT JOIN internal_assessment_column_status iams ON iams.internalAssessmentColumnId=iam.id AND iams.batchId=$batchId AND iams.subjectId=$subjectId WHERE iam.internalAssessmentId=$assessmentId ORDER BY columnNo";
        if($batchId==''){
            $sql              = "SELECT iam.id, iam.internalAssessmentId, iam.columnNo, iam.columnName, iam.ruleType, iam.passPercent, iams.studentsPassed, iams.studentsFailed, iams.passedPercent, iam.totalMark, iams.absenteesNo, iam.groupId FROM internal_assessment_column iam LEFT JOIN internal_assessment_column_status iams ON iams.internalAssessmentColumnId=iam.id AND iams.batchId=null AND iams.subjectId=$subjectId WHERE iam.internalAssessmentId=$assessmentId ORDER BY columnNo";
        }
        try {
            $assessmentColumn = $this->executeQueryForList($sql, $this->mapper[AssessmentServiceMapper::GET_ASSESSMENT_COLUMNS]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $assessmentColumn;
    }
    /**
     * Updates total mark of column by columnId
     *
     * @param int $internalAssessmentColumnId
     * @param int $totalMark
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @param int $studentsPassed
     * @param int $studentFailed
     * @param int $passedPercent
     * @param int $absenteesNo
     * @throws ProfessionalException
     * @return boolean
     */
    public function updateColumnDetailsById($internalAssessmentColumnId, $totalMark, $internalAssessmentReq, $studentsPassed = 0, $studentsFailed = 0, $passedPercent = 0, $absenteesNo = 0) {
        $assessmentId   = $this->realEscapeString($internalAssessmentColumnId);
        $totalMark      = $this->realEscapeString($totalMark);
        $studentsPassed = $studentsPassed?$this->realEscapeString($studentsPassed):'NULL';
        $studentsFailed = $studentsFailed?$this->realEscapeString($studentsFailed):'NULL';
        $passedPercent  = $passedPercent?$this->realEscapeString($passedPercent):'NULL';
        $absenteesNo    = $absenteesNo?$this->realEscapeString($absenteesNo):'NULL';
        $columStatus    = [];
        $id             = 0;
        $sql            = "UPDATE internal_assessment_column SET totalMark = $totalMark WHERE id = $internalAssessmentColumnId";
        try
        {
            $this->executeQuery($sql);
            $sql_statusChk = "SELECT id FROM internal_assessment_column_status WHERE internalAssessmentColumnId=$internalAssessmentColumnId AND batchId='$internalAssessmentReq->batchId' AND subjectId=$internalAssessmentReq->subjectId";
            $id            = $this->executeQueryForObject($sql_statusChk)->id;
            if ($id) {
                $sqlStatusIns = "UPDATE internal_assessment_column_status SET studentsPassed = $studentsPassed, studentsFailed = $studentsFailed, passedPercent = $passedPercent, absenteesNo = $absenteesNo   WHERE internalAssessmentColumnId=$internalAssessmentColumnId AND batchID='$internalAssessmentReq->batchId' AND subjectID=$internalAssessmentReq->subjectId";
            } else {
                $sqlStatusIns = "INSERT INTO internal_assessment_column_status(internalAssessmentColumnId, batchId, subjectId, studentsPassed, studentsFailed, passedPercent, absenteesNo) VALUES ($internalAssessmentColumnId, '$internalAssessmentReq->batchId', $internalAssessmentReq->subjectId, '$studentsPassed', '$studentsFailed', '$passedPercent', '$absenteesNo')";
            }
            $this->executeQuery($sqlStatusIns);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Save student column marks
     *
     * @param int $internalAssessmentColumnId
     * @param int $studentId
     * @param int $marks
     * @param int $batchId
     * @param int $subjectId
     * @throws ProfessionalException
     * @return boolean
     */
    public function saveStudentColumnMarks($internalAssessmentColumnId, $studentId, $marks, $batchId, $subjectId,$genderwise = null) {
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $studentId = $this->realEscapeString($studentId);
        if($genderwise)
        {
            $studentGender = StudentService::getInstance()->getStudentDetailsById($studentId)->studentGender;
            $marks = $this->realEscapeArray($marks);
            $selectedMark = 0;
            foreach($marks as $mark)
            {
                if($mark->gender == strtoupper($studentGender))
                {
                    $selectedMark = $mark->marks;
                    break;
                }
            }
            $sql = "INSERT INTO internal_assessment_student_column_mark (internalAssessmentColumnId, studentId, marks, batchId, subjectId) VALUES($internalAssessmentColumnId$studentId$selectedMark$batchId$subjectId)";
        }
        else{
            
                    $marks = $this->realEscapeString($marks);
                    $marks = empty($marks)?0:$marks;
            
                    $sql = "INSERT INTO internal_assessment_student_column_mark (internalAssessmentColumnId, studentId, marks, batchId, subjectId) VALUES($internalAssessmentColumnId$studentId$marks$batchId$subjectId)";
        }
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Delete student column marks by assessment columnId
     *
     * @param int $internalAssessmentColumnId
     * @param int $batchId
     * @param int $subjectId
     * @throws ProfessionalException
     * @return boolean
     */
    public function deleteStudentColumnMarks($internalAssessmentColumnId, $batchId, $subjectId,$psId=null) {
        $sql = "DELETE FROM  internal_assessment_student_column_mark WHERE internalAssessmentColumnId = ".$this->realEscapeString($internalAssessmentColumnId)." AND batchId='$batchId' AND subjectId=$subjectId";
        if($psId){
            $sql = "DELETE FROM  internal_assessment_student_column_mark WHERE internalAssessmentColumnId = ".$this->realEscapeString($internalAssessmentColumnId)." AND subjectId=$subjectId";
        }
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * generate assessment number for new assessment entry
     *
     * @param int $batchId
     * @param int $semId
     * @param int $subjectId
     * @throws ProfessionalException
     * @return number
     */
    public function generateAssessmentNumber($batchId, $semId, $subjectId,$psId=null) {
        $batchId   = $this->realEscapeString($batchId);
        $semId     = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        $assessmentNo = 1;
        $sql          = "select max(assessmentNo)+1 as assessmentNo from internal_assessment WHERE batchId=$batchId AND semId=$semId AND subjectId=$subjectId";
        if($psId){
            $sql          = "select max(assessmentNo)+1 as assessmentNo from internal_assessment WHERE psId = $psId AND subjectId=$subjectId";
        }
        try
        {
            $number = $this->executeQueryForObject($sql)->assessmentNo;
            if ($number) {
                $assessmentNo = $number;
            }
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $assessmentNo;
    }
    /**
     *
     * @param Integer $internalAssessmentColumnId
     * @throws ProfessionalException
     * @return $internalAssessmentColumnGroupId
     */
    public function getAssessmentGroupByColumnId($internalAssessmentColumnId) {
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "SELECT groupId FROM internal_assessment_column WHERE id = ".$internalAssessmentColumnId;
        try {
            $internalAssessmentColumnGroupId = $this->executeQueryForObject($sql)->groupId;
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessmentColumnGroupId;
    }
    /**
     * Delete a group - results in deleting all columns & its rules in that group
     * @param unknown $internalAssessmentColumnGroupId
     * @throws ProfessionalException
     * @return boolean
     */
    public function deleteAssessmentColumnGroupById ( $internalAssessmentColumnGroupId ) {
        $internalAssessmentColumnGroupId = $this->realEscapeString($internalAssessmentColumnGroupId);
        // Deleting the group will delete all the columns corresponds to that group
        $sql = "DELETE FROM internal_assessment_column_group WHERE id = ".$internalAssessmentColumnGroupId;
        try {
            $this->executeQuery($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    /**
     * Delete assessment column by columnId
     *
     * @param int $internalAssessmentColumnId
     * @throws ProfessionalException
     * @return boolean
     */
    public function deleteAssessmentColumnById($internalAssessmentColumnId) {
        // Checking for dependent formula columns. If exists, throw an exception with dependent column names.
        // Otherwise, proceed deletion
        $dependentColumns = $this->getFormlaDependentColumns($internalAssessmentColumnId)->columnNo;
        if (!empty($dependentColumns)) {
            throw new ProfessionalException(ProfessionalException::ASSESSMENT_COLUMN_DELETE_DEPENDENCY_FOUND, " Column can't be deleted !!.  Please remove the reference(s) from following column(s) [".$dependentColumns."]");
        }
        $groupId = $this->getAssessmentGroupByColumnId($internalAssessmentColumnId);
        if ( $groupId ) {
            // By deleting the group - All the corresponding assessment columns will be deleted
            $this->deleteAssessmentColumnGroupById($groupId);
        }
        else {
            $sql = "DELETE FROM internal_assessment_column WHERE id = ".$internalAssessmentColumnId;
            try {
                $this->executeQuery($sql);
            }
            catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
        return true;
    }
    /**
     * Get Internal Assessment column details
     *
     * @param int $internalAssessmentColumnId
     */
    public function getAssessmentColumnDetailsById($internalAssessmentColumnId) {
    }
    /**
     * Validate internal assessment formula
     *
     * @param string $formula
     * @return boolean
     */
    public function validateInternalAssessmentFormula($formula) {
        $variables = array_unique(preg_split("/[-+*\/^%\(\)]/", $formula, -1, PREG_SPLIT_NO_EMPTY));
        $variables = array_filter($variables, function ($arrayEntry) {
                return !is_numeric($arrayEntry);
            });
        usort($variables, function ($a, $b) {
                return strlen($b)-strlen($a);
            });
        foreach ($variables as $variable) {
            $formula = str_replace($variable, 1, $formula);
        }
        $result = eval('return '.$formula.';');
        if ($result) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * Get formula dependent columns by columnId
     *
     * @param int $internalAssessmentColumnId
     * @return string[]
     */
    public function getFormlaDependentColumns($internalAssessmentColumnId) {
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $columnNo                   = NULL;
        $columns                    = [];
        $columnNo = $this->getColumnNoById($internalAssessmentColumnId);
        $sql = "SELECT group_concat(columnNo) as columnNo FROM internal_assessment_column clmn
        INNER JOIN  internal_assessment_formula frmla ON  clmn.id = frmla.internalAssessmentColumnId
        WHERE clmn.internalAssessmentId = (SELECT internalAssessmentId FROM internal_assessment_column WHERE id = $internalAssessmentColumnId) AND frmla.formula LIKE '%$columnNo%' ";
        try
        {
            $columns = $this->executeQueryForObject($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $columns;
    }
    /**
     * Get formula dependent columnIds by columnId
     *
     * @param int $internalAssessmentColumnId
     * @return string[]
     */
    public function getFormlaDependentColumnIds($internalAssessmentColumnId) {
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $columnNo                   = NULL;
        $columnIds                  = [];
        $columnNo = $this->getColumnNoById($internalAssessmentColumnId);
        $sql = "SELECT clmn.id, clmn.columnNo FROM internal_assessment_column clmn
        INNER JOIN  internal_assessment_formula frmla ON  clmn.id = frmla.internalAssessmentColumnId
        WHERE clmn.internalAssessmentId = (SELECT internalAssessmentId FROM internal_assessment_column WHERE id = $internalAssessmentColumnId) AND frmla.formula LIKE '%$columnNo%' ";
        try
        {
            $columnIds = $this->executeQueryForList($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $columnIds;
    }
    /**
     * Get column number by internalAssessmentColumnId
     *
     * @param int $internalAssessmentColumnId
     * @throws ProfessionalException
     * @return string
     */
    public function getColumnNoById($internalAssessmentColumnId) {
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $columnNo = "";
        $sql      = "SELECT columnNo FROM internal_assessment_column WHERE id = $internalAssessmentColumnId";
        try
        {
            $columnNo = $this->executeQueryForObject($sql)->columnNo;
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $columnNo;
    }
    /**
     * recalulcate the marks
     *
     * @param int $assessmentId
     * @param InternalAssessmentRequest $internalAssessmentReq
     * @throws ProfessionalException
     * @return boolean
     */
    public function recalculateMarksByAssessmentId($assessmentId, $internalAssessmentReq, $batchId = null, $semId = null, $subjectId = null, $pssuid=null) {
        $assessmentId = $this->realEscapeString($assessmentId);
        $columnIds    = $this->getInernalAssessmentColums($assessmentId);
        if (!empty($columnIds) && $columnIds != NULL) {
            foreach ($columnIds as $id) {
                try {
                    $isGenderwise = $this->checkAttendancRuleIsGenderWise($id->id);
                    $marks = $this->getInternalAssessmentColumnMarks($id->id, $internalAssessmentReq, $batchId, $semId, $subjectId,$pssuid,$isGenderwise);
                }
                catch (\Exception $e) {
                    throw new ProfessionalException($e->getCode(), $e->getMessage());
                }
            }
        }
        return true;
    }
    /**
     * get formula columns by assessment id
     *
     * @param int $assessmentId
     * @throws ProfessionalException
     * @return object|array|\com\linways\base\util\$objectList[]
     */
    public function getInernalAssessmentColums($assessmentId) {
        $assessmentId = $this->realEscapeString($assessmentId);
        $columnIds    = NULL;
        $sql          = "SELECT id,columnName,totalMark FROM internal_assessment_column WHERE internalAssessmentId=$assessmentId ORDER BY columnNo";
        try
        {
            $columnIds = $this->executeQueryForList($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $columnIds;
    }
    /**
     * add or update student marks by studentId and internalAssessmentId
     *
     * @param int $studentId
     * @param int $columnId
     * @param float $mark
     * @throws ProfessionalException
     * @return object|NULL|\com\linways\base\util\$objectList[]
     */
    public function addInternalAssessmentMarkByStudentId($studentId, $columnId, $mark, $batchId, $subjectId) {
        $studentId = $this->realEscapeString($studentId);
        $columnId  = $this->realEscapeString($columnId);
        $mark      = $this->realEscapeString($mark);
        $batchId   = $this->realEscapeString($batchId);
        $subjectId = $this->realEscapeString($subjectId);
        $sqlCheck = "SELECT if(id,1,0) as isMark FROM internal_assessment_student_column_mark WHERE internalAssessmentColumnId=$columnId AND studentId=$studentId AND subjectId = $subjectId AND batchId = $batchId";
        $isMark   = $this->executeQueryForObject($sqlCheck)->isMark;
        if ($isMark) {
            $sql = "UPDATE internal_assessment_student_column_mark SET marks = $mark WHERE internalAssessmentColumnId = $columnId AND studentId = $studentId AND subjectId = $subjectId AND batchId = $batchId";
        } else {
            $sql = "INSERT INTO internal_assessment_student_column_mark (internalAssessmentColumnId, studentId, marks, batchId, subjectId) VALUES($columnId$studentId$mark$batchId$subjectId)";
        }
        try
        {
            return $this->executeQueryForObject($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * get student internalAssessment mark
     *
     * @param int $studentId
     * @param int $assessmentId
     * @param int $columnId
     * @throws ProfessionalException
     * @return NULL[]
     */
    public function getInternalAssessmentMarkByStudentId($studentId, $assessmentId, $columnId, $batchId, $subjectId) {
        $studentId    = $this->realEscapeString($studentId);
        $columnId     = $this->realEscapeString($columnId);
        $assessmentId = $this->realEscapeString($assessmentId);
        $studentMarks = [];
        try
        {
            $depenetentColumnList = $this->getFormlaDependentColumnIds($columnId);
            $internalAssessment   = $this->getInternalAssessmentById($assessmentId);
            if (!empty($depenetentColumnList) && $depenetentColumnList != NULL) {
                foreach ($depenetentColumnList as $column) {
                    $rule           = $this->getInternalAssessmentFormulaRule($column->id);
                    $studentMarks[] = $this->reCalculateMarkByStudentId($studentId, $internalAssessment, $rule, $column->id, $batchId, $subjectId);
                }
            }
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $studentMarks;
    }
    /**
     * recalulate student mark
     *
     * @param int $studentId
     * @param InternalAssessment $internalAssessment
     * @param InternalAssessmentFormula $internalAssessmentFormula
     * @param int $columnId
     * @return \com\linways\core\ams\professional\dto\InternalAssessmentStudentColumnMark
     */
    public function reCalculateMarkByStudentId($studentId, $internalAssessment, $internalAssessmentFormula, $columnId, $batchId, $subjectId) {
        $internalAssessmentFormula            = $this->realEscapeObject($internalAssessmentFormula);
        $internalAssessment                   = $this->realEscapeObject($internalAssessment);
        $internalAssessmentColumnId           = $this->realEscapeString($internalAssessmentColumnId);
        $studentId                            = $this->realEscapeString($studentId);
        $internalAssessmentStudentColumnMarks = 0;
        $formula_temp                         = NULL;
        $variables[]                          = NULL;
        $values[]                             = NULL;
        $mark                                 = 0;
        $columnDetails = $this->getInternalAssessmentColumnById($columnId);
        $variables = array_unique(preg_split("/[-+*\/^%\(\)]/", $internalAssessmentFormula->formula, -1, PREG_SPLIT_NO_EMPTY));
        $variables = array_filter($variables, function ($arrayEntry) {
                return !is_numeric($arrayEntry);
            });
        usort($variables, function ($a, $b) {
                return strlen($b)-strlen($a);
            });
        $mark = 0;
        $internalAssessmentStudentColumnMark                             = new InternalAssessmentStudentColumnMark();
        $internalAssessmentStudentColumnMark->internalAssessmentColumnId = $columnId;
        $internalAssessmentStudentColumnMark->studentId                  = $studentId;
        $internalAssessmentStudentColumnMark->columnNo                   = $columnDetails->columnNo;
        $formula_temp = $internalAssessmentFormula->formula;
        $values = $this->getVariableValues($studentId, $variables, $internalAssessment->id, $batchId, $subjectId);
        foreach ($variables as $variable) {
            if ($values[$variable] != NULL) {
                $formula_temp = str_replace($variable, $values[$variable], $formula_temp);
            }
        }
        // Evaluating formula.
        $mark                                       = eval('return '.$formula_temp.';');
        $mark                                       = empty($mark)?0:round($mark, 2);
        $internalAssessmentStudentColumnMark->marks = $mark;
        // Saving column Marks
        $this->addInternalAssessmentMarkByStudentId($studentId, $columnId, $mark, $batchId, $subjectId);
        $internalAssessmentStudentColumnMarks = $internalAssessmentStudentColumnMark;
        return $internalAssessmentStudentColumnMarks;
    }
    /**
     * get attendance dates by internal assessment columnId
     *
     * @param int $internalAssessmentColumnId
     * @throws ProfessionalException
     * @return object|array|\com\linways\base\util\$objectList[]
     */
    public function getAttendanceDates($internalAssessmentColumnId) {
        $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
        $sql = "select DISTINCT fromDate, toDate from internal_assessment_attendance_rule WHERE internalAssessmentColumnId = $internalAssessmentColumnId";
        try
        {
            $columnDetails = $this->executeQueryForObject($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $columnDetails;
    }
    /**
     * Publish internal assessment by id
     *
     * @param int $internalAssessmentId
     * @throws ProfessionalException
     */
    public function publishInternalAssessmentById($internalAssessmentId) {
        $internalAssessmentId = $this->realEscapeString($internalAssessmentId);
        $sql                  = "UPDATE internal_assessment SET isPublished = 1 WHERE id = '".$internalAssessmentId."'";
        try
        {
            $this->executeQuery($sql);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return true;
    }
    public function getColumnStatus($columnId, $batchId, $subjectId) {
        $columnId  = $this->realEscapeString($columnId);
        $batchId   = $this->realEscapeString($batchId);
        $subjectId = $this->realEscapeString($subjectId);
        $assessmentColumn = NULL;
        $sql = "SELECT internalAssessmentColumnId as id, studentsPassed, studentsFailed, passedPercent, absenteesNo FROM internal_assessment_column_status WHERE internalAssessmentColumnId = ".$columnId." AND batchId = '".$batchId."' AND subjectId = ".$subjectId."";
        try {
            $assessmentColumn = $this->executeQueryForObject($sql, FALSE, $this->mapper[AssessmentServiceMapper::GET_ASSESSMENT_COLUMNS]);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $assessmentColumn;
    }
    /**
     *
     * @param InternalAssessmentColumn $internalAssessmentColumn
     * @return $internalAssessmentColumnId
     * @Author Ambu
     */
    public function createInternalAssessmentColumn ($internalAssessmentColumn, $groupId = null) {
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $groupId = $this->realEscapeString($groupId);
        if ( $groupId == null ) {
            $groupId = 'NULL';
        }
        $staffId = $_SESSION['staffID'];
        // Generate next column No. in this assessment
        $internalAssessmentColumn->columnNo = $this->generateNextColumnNoById($internalAssessmentColumn->internalAssessmentId);
        // Insert InternalAssessmentColumn details. If ruletype of this column is not InternalAssessmentRuleType::FORMULA, totalMarks will be null and must be saved as 0. Otherwise save the totalMarks as it is.
        $sql = "INSERT INTO internal_assessment_column (internalAssessmentId, columnNo, columnName, ruleType, passPercent, totalMark, groupId, createdBy, updatedBy, updatedDate, createdDate) VALUES($internalAssessmentColumn->internalAssessmentId, '$internalAssessmentColumn->columnNo', '$internalAssessmentColumn->columnName', '$internalAssessmentColumn->ruleType', '$internalAssessmentColumn->passPercent',  $internalAssessmentColumn->totalMark$groupId$staffId$staffId, utc_timestamp(), utc_timestamp())";
        try {
            $internalAssessmentColumnId = $this->executeQueryForObject($sql, true);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessmentColumnId;
    }
    /**
     * To create new column group
     * @param String $groupName
     * @throws ProfessionalException
     * @return object|NULL|\com\linways\base\util\$objectList[]
     */
    public function createInternalAssessmentColumnGroup ( $groupName = null ) {
        $groupName = $this->realEscapeString($groupName);
        $sql = "INSERT INTO internal_assessment_column_group (groupName) VALUES ('$groupName')";
        try {
            $internalAssessmentColumnGroupId = $this->executeQueryForObject($sql, true);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $internalAssessmentColumnGroupId;
    }
    /**
     *
     * @param integer $groupId
     * @throws ProfessionalException
     * @return Array columnIds[]
     */
    public function getInternalAssessmentColumnByGroupId ( $groupId ) {
        $groupId = $this->realEscapeString($groupId);
        $columnList    = NULL;
        $sql = "SELECT id, internalAssessmentId, columnNo, columnName, ruleType, passPercent, totalMark, groupId FROM internal_assessment_column WHERE groupId = $groupId ORDER BY id ASC";
        try {
            $columnList = $this->executeQueryForList($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $columnList;
    }
    /**
     * Update exam rules of all the columns of the same group
     * @param Obj $internalAssessmentExamRule
     * @param Int $groupId
     * @throws ProfessionalException
     */
    public function updateInternalAssessmentExamRuleByGroupId ( $internalAssessmentExamRule, $groupId ) {
        $internalAssessmentExamRule = $this->realEscapeObject($internalAssessmentExamRule);
        $sql = "UPDATE internal_assessment_exam_rule iaer JOIN internal_assessment_column iac ON ( iaer.internalAssessmentColumnId = iac.id ) SET
            iaer.examTypeIDs= '$internalAssessmentExamRule->examTypeIDs',
            iaer.examMark    = $internalAssessmentExamRule->examMark,
            iaer.examBestOf    = $internalAssessmentExamRule->examBestOf,
            iaer.isExamAvg    = $internalAssessmentExamRule->isExamAvg,
            iaer.ordinalNo    = $internalAssessmentExamRule->ordinalNo
            WHERE iac.groupId = $groupId";
        try {
            $this->executeQuery($sql);
            $oldRanges = $this->getInternalAssessmentExamMarkRange($internalAssessmentExamRule->internalAssessmentColumnId);
            if($oldRanges){
                $sqlDelRange = "DELETE FROM internalAssessmentExamMarkRange WHERE internalAssessmentColumnId = ".$internalAssessmentExamRule->internalAssessmentColumnId;
                $this->executeQuery($sqlDelRange);
            }
            foreach($internalAssessmentExamRule->markRange as $range){
                if(($range['from']!="") && ($range['to']!="") && ($range['mark']!="")){
                    $sqlMarkRange = "INSERT INTO internalAssessmentExamMarkRange(internalAssessmentColumnId,percentFrom,percentTo,marks) VALUES($internalAssessmentExamRule->internalAssessmentColumnId,$range[from],$range[to],$range[mark])";
                    $this->executeQuery($sqlMarkRange);
                }
            } 
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Update assignment rules of all the columns of the same group
     * @param Obj $internalAssessmentAssignmentRule
     * @param Int $groupId
     * @throws ProfessionalException
     */
    public function updateInternalAssessmentAssignmentRuleByGroupId ( $internalAssessmentAssignmentRule, $groupId ) {
        $internalAssessmentAssignmentRule = $this->realEscapeObject($internalAssessmentAssignmentRule);
        $sql = "UPDATE internal_assessment_assignment_rule iaar JOIN internal_assessment_column iac ON ( iaar.internalAssessmentColumnId = iac.id ) SET
            iaar.assignmentNos         = '$internalAssessmentAssignmentRule->assignmentNos',
            iaar.assignmentMark        = $internalAssessmentAssignmentRule->assignmentMark,
            iaar.assignmentBestOf    = $internalAssessmentAssignmentRule->assignmentBestOf,
            iaar.isassignmentAvg    = $internalAssessmentAssignmentRule->isassignmentAvg,
            iaar.ordinalNo            = $internalAssessmentAssignmentRule->ordinalNo
            WHERE iac.groupId = $groupId";
        try {
            $this->executeQuery($sql);
            $oldRanges = $this->getInternalAssessmentAssignmentMarkRange($internalAssessmentAssignmentRule->internalAssessmentColumnId);
            if($oldRanges){
                $sqlDelRange = "DELETE FROM internal_assessment_assignment_mark_range WHERE internalAssessmentColumnId = ".$internalAssessmentAssignmentRule->internalAssessmentColumnId;
                $this->executeQuery($sqlDelRange);
            }
            foreach($internalAssessmentAssignmentRule->markRange as $range){
                if(($range['from']!="") && ($range['to']!="") && ($range['mark']!="")){
                    $sqlMarkRange = "INSERT INTO internal_assessment_assignment_mark_range(internalAssessmentColumnId,percentFrom,percentTo,marks) VALUES($internalAssessmentAssignmentRule->internalAssessmentColumnId,$range[from],$range[to],$range[mark])";
                    $this->executeQuery($sqlMarkRange);
                }
            } 
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Enter exam marks for internal assessment by group
     * @param unknown $internalAssessmentColumn
     * @param unknown $rules
     * @param unknown $groupId
     * @throws ProfessionalException
     */
    public function insertInernalAssessmentColumnExamMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId = null, $batchId = null, $semId = null, $subjectId = null, $pssuid = null) {
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $internalAssessment = $this->getInternalAssessmentById($internalAssessmentColumn->internalAssessmentId);
        $rules = $this->realEscapeObject($rules);
        $groupId = $this->realEscapeString($groupId);
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        $columns = $this->getInternalAssessmentColumnByGroupId($groupId);
        foreach ($columns as $column) {
            $status[$column->id] = [
                'studentsPassed' => 0,
                'passedPercent' => 0,
                'studentFailed' => 0,
                'absenteesNo' => 0
            ];
        }
        if ($internalAssessment->batchId == NULL && $internalAssessment->psId == NULL) {
            $internalAssessment->batchId = $batchId;
            $internalAssessment->semId = $semId;
            $internalAssessment->subjectId = $subjectId;
        }
        
        if ($internalAssessment->batchId != NULL && $internalAssessment->semId != NULL) {
            $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
            if ($isCurrentSem) {
                $sql_exam_mark = "SELECT sa.studentID, sa.rollNo, group_concat(sm.percentage) as percentages, sm.marksObtained,sa.batchID FROM studentaccount sa LEFT JOIN student_marks sm ON (sa.studentID = sm.studentID AND sm.subjectID = ".$internalAssessment->subjectId." AND sm.semID = ".$internalAssessment->semId." AND sm.batchID = ".$internalAssessment->batchId." AND sm.examTypeID IN (".$rules->examTypeIDs.")) WHERE sa.batchID = ".$internalAssessment->batchId." GROUP BY sa.studentID ORDER BY sa.rollNo ASC, sm.examTypeID ASC, sm.percentage DESC";
                
            } else {
                
                $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
                
                $sql_exam_mark = "SELECT sa.studentID, sa.rollNo, group_concat(sm.percentage) as percentages, sm.marksObtained,sa.batchID FROM studentaccount sa INNER JOIN batches ba ON sa.batchID =  ba.batchID LEFT JOIN student_marks sm ON (sa.studentID = sm.studentID AND sm.subjectID = ".$internalAssessment->subjectId." AND sm.semID = ".$internalAssessment->semId." AND sm.batchID = ".$internalAssessment->batchId." AND sm.examTypeID IN (".$rules->examTypeIDs.")) inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID  WHERE ba.batchID = ".$internalAssessment->batchId." and joinedSem.orderNo <= sem.orderNo GROUP BY sa.studentID
UNION SELECT sa.studentID, sa.rollNo, group_concat(sm.percentage) as percentages, sm.marksObtained,sa.batchID FROM failed_students fs LEFT JOIN studentaccount sa ON fs.studentID = sa.studentID LEFT JOIN student_marks sm ON (sa.studentID = sm.studentID AND sm.subjectID = ".$internalAssessment->subjectId." AND sm.semID = ".$internalAssessment->semId." AND sm.batchID = ".$internalAssessment->batchId." AND sm.examTypeID IN (".$rules->examTypeIDs.")) left join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID WHERE previousBatch = ".$internalAssessment->batchId." AND fsem.orderNo > $semDetails->orderNo and joinedSem.orderNo <= $semDetails->orderNo GROUP BY sa.studentID ORDER BY rollNo ASC;";
                
            }
            if($internalAssessmentColumn->psId){
                $internalAssessmentColumn->batchId = null;
                $internalAssessment->batchId = null;
                $sql_exam_mark = "SELECT 
                                    sa.studentID,
                                    sa.rollNo,
                                    ba.batchID,
                                    GROUP_CONCAT(sm.percentage) AS percentages,
                                    sm.marksObtained
                                FROM
                                    pseudosubjects_students pss
                                        INNER JOIN
                                    studentaccount sa ON pss.studentID = sa.studentID
                                        INNER JOIN
                                    batches ba ON ba.batchID = sa.batchID
                                        INNER JOIN
                                    department de ON de.deptID = ba.deptID
                                        LEFT JOIN
                                    student_marks sm ON (sa.studentID = sm.studentID
                                        AND sm.subjectID = $internalAssessment->subjectId AND sm.examTypeID IN (".$rules->examTypeIDs."))
                                WHERE
                                    pss.pseudosubjectID = $internalAssessmentColumn->psId  GROUP BY sa.studentID";
            }
        }
        else {
            // return;
            if(!$pssuid){
                $pssuid = $internalAssessment->psId;
                $subjectId = $internalAssessment->subjectId;
            }
            if($pssuid){
                $sql_exam_mark = "SELECT 
                                    sa.studentID,
                                    sa.rollNo,
                                    ba.batchID,
                                    GROUP_CONCAT(sm.percentage) AS percentages,
                                    sm.marksObtained
                                FROM
                                    pseudosubjects_students pss
                                        INNER JOIN
                                    studentaccount sa ON pss.studentID = sa.studentID
                                        INNER JOIN
                                    batches ba ON ba.batchID = sa.batchID
                                        INNER JOIN
                                    department de ON de.deptID = ba.deptID
                                        LEFT JOIN
                                    student_marks sm ON (sa.studentID = sm.studentID
                                        AND sm.subjectID = $subjectId AND sm.examTypeID IN (".$rules->examTypeIDs."))
                                WHERE
                                    pss.pseudosubjectID = $pssuid  GROUP BY sa.studentID";
            }
            else{
                return; 
            }
        }
//         error_log($sql_exam_mark);
        // $sql_exam_mark = "SELECT sm.studentID, group_concat(sm.percentage) as percentages FROM student_marks sm WHERE sm.subjectID = ".$internalAssessment->subjectId." AND sm.semID = ".$internalAssessment->semId." AND sm.batchID = ".$internalAssessment->batchId." AND sm.examTypeID IN (".$rules->examTypeIDs.") GROUP BY sm.studentID ORDER BY sm.examTypeID ASC, sm.percentage DESC";
        try {
            $studentMarkDetails = $this->executeQueryForList($sql_exam_mark);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        $sql_insert = "INSERT INTO internal_assessment_student_column_mark (internalAssessmentColumnId, studentId, marks, batchId, subjectId) VALUES ";
        $scaleFunction = function($percent) use ($rules) {
            return $percent > 0 ? ( $percent / 100 ) * $rules->examMark : 0;
        };
        $values = null;
        $selectedExamsCount = count(explode(',', $rules->examTypeIDs));
        foreach ($studentMarkDetails as $studentMarkDetail) {
            // $studentID = $studentMarkDetail->studentID;
            $marksCount = $rules->ordinalNo ? $rules->ordinalNo : $rules->examBestOf;
            $studentMarks = explode(",", $studentMarkDetail->percentages);
            rsort ( $studentMarks );
            $studentMarks = array_slice ( $studentMarks, 0, $marksCount);
            $studentMarks = array_map ($scaleFunction, $studentMarks );
            if ( count ( $studentMarks ) < $marksCount ) {
                $studentMarks = array_pad ( $studentMarks, $marksCount, 0 );
            }
            if ( $rules->ordinalNo ) {
                $studentMarks = $studentMarks[$rules->ordinalNo - 1];
            }
            else if ( $rules->isExamAvg == 1 ) {
                $studentMarks = array_sum($studentMarks) / $rules->examBestOf;
            }
            else if ( $selectedExamsCount  == 1) {
                if ( $studentMarkDetail->marksObtained == -1 ) {
                    $status[$columns[0]->id]['absenteesNo'] += 1;
                }
            }
            $i = 0;
            $passPercentage = $rules->examMark * ( $internalAssessmentColumn->passPercent / 100 );
            foreach ($columns as $column) {
                $studentFinalMarks = is_array($studentMarks) ? $studentMarks[$i++] : $studentMarks;
                $studentFinalMarksInPercentage = ($studentFinalMarks/$column->totalMark)*100;
                $studentFinalMarksInPercentage = round($studentFinalMarksInPercentage,2);
                $sqlMarkRange = "SELECT marks FROM internalAssessmentExamMarkRange WHERE internalAssessmentColumnId=$column->id AND percentFrom <= $studentFinalMarksInPercentage AND percentTo >= $studentFinalMarksInPercentage";
                $studentFinalMark = $this->executeQueryForObject($sqlMarkRange);
                $studentFinalMarks = $studentFinalMark->marks ? $studentFinalMark->marks : $studentFinalMarks;
                if ( $studentFinalMarks >= $passPercentage ) {
                    $status[$column->id]['studentsPassed'] += 1;
                } 
                else {
                    $status[$column->id]['studentFailed'] += 1;
                    $studentFinalMarks = $studentFinalMarks > 0 ? $studentFinalMarks : 0;
                }
                $values[] = " (".$column->id.", ".$studentMarkDetail->studentID.", ".$studentFinalMarks.", '".$studentMarkDetail->batchID."', ".$internalAssessment->subjectId." )";
            }
        }
        $sql_insert .= implode(',', $values);
        $sql_insert .= " ON DUPLICATE KEY UPDATE marks = VALUES(marks)";
        try {
            $this->executeQuery($sql_insert);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        // Inserting Internal assessment column status
        $staffId = $_SESSION['staffID'];
        $status_check = $this->getColumnStatus($internalAssessment->id, $internalAssessment->batchId, $internalAssessment->subjectId);
        if ( empty ( $status_check ) ) {
            foreach ($columns as $column) {
                $status[$column->id]['passedPercent'] = ( $status[$column->id]['studentsPassed'] / count($studentMarkDetails) ) * 100;
                $statusValues[] = " (".$column->id.", '".$internalAssessment->batchId."', ".$internalAssessment->subjectId.", ".$status[$column->id]['studentsPassed'].", ".$status[$column->id]['studentFailed'].", ".$status[$column->id]['passedPercent'].", ".$status[$column->id]['absenteesNo'].", ".$staffId.", utc_timestamp(), ".$staffId.", utc_timestamp() )";
            }
            $sql_status = "INSERT INTO internal_assessment_column_status (internalAssessmentColumnId, batchId, subjectId, studentsPassed, studentsFailed, passedPercent, absenteesNo, createdBy, createdDate, updatedBy, updatedDate) VALUES";
            $sql_status .= implode(',', $statusValues);
            try {
                $this->executeQuery($sql_status);
            }
            catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
        else {
            foreach ($columns as $column) {
                $status[$column->id]['passedPercent'] = ( $status[$column->id]['studentsPassed'] / count($studentMarkDetails) ) * 100;
                $sql_status = "UPDATE internal_assessment_column_status SET 
                studentsPassed = ".$status[$column->id]['studentsPassed'].",
                studentsFailed = ".$status[$column->id]['studentFailed'].",
                passedPercent = ".$status[$column->id]['passedPercent'].",
                absenteesNo = ".$status[$column->id]['absenteesNo'].",
                updatedBy = ".$staffId.",
                updatedDate = utc_timestamp() WHERE 
                internalAssessmentColumnId = ".$column->id." AND 
                batchId = ".$internalAssessment->batchId." AND
                subjectId = ".$internalAssessment->subjectId."";
                try {
                    $this->executeQuery($sql_status);
                }
                catch (\Exception $e) {
                    throw new ProfessionalException($e->getCode(), $e->getMessage());
                }
            }
        }
    }
/**
 * Enter online exam marks for internal assessment by group
 * @param unknown $internalAssessmentColumn
 * @param unknown $rules
 * @param unknown $groupId
 * @throws ProfessionalException
 */
    public function insertInernalAssessmentColumnOnlineExamMarks($internalAssessmentColumn, $rules, $groupId, $batchId=null, $semId=null, $subjectId=null,$pssuid=null){
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $internalAssessment = $this->getInternalAssessmentById($internalAssessmentColumn->internalAssessmentId);
        $rules = $this->realEscapeObject($rules);
        $groupId = $this->realEscapeString($groupId);
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        $columns = $this->getInternalAssessmentColumnByGroupId($groupId);
        $psId = $pssuid?$pssuid:$internalAssessmentColumn->psId;
        if(!$psId){
            $students = StudentService::getInstance()->getStudentsByBatchIdSemIdSubjectIdStaffId($internalAssessment->batchId,$internalAssessment->semId,$internalAssessment->subjectId,$_SESSION['staffID']);
        }
        else{
            $students = StudentService::getInstance()-> getStudentsAssignedToApseudoSub($psId);
        }
        $sql_insert = "INSERT INTO internal_assessment_student_column_mark (internalAssessmentColumnId, studentId, marks, batchId, subjectId) VALUES ";
        $scaleFunction = function($percent) use ($rules) {
            return $percent > 0 ? ( $percent / 100 ) * $rules->examMark : 0;
        };
        $selectedExamsCount = count(explode(',', $rules->examTypeIDs));
        $rules->examTypeIDs =str_replace(",","','",$rules->examTypeIDs);
        $rules->examTypeIDs ="'".$rules->examTypeIDs."'";
        $i = 0;
        $studentsPassed = 0;
        $studentsFailed = 0;
        $values=[];
        //Total Marks of selected exams
        $sql_total_marks = "SELECT id, SUM(mark) AS totalMark FROM (
            SELECT 
                oe_exams_id as id,
                oeq.id as qid,
                oeq.mark as mark
           from oe_exam_questions oeq where oe_exams_id IN ($rules->examTypeIDs)
            ) result group by id";
        $totalMarkDetail = $this->executeQueryForList($sql_total_marks);
        $examTotalMarks = 0;
        foreach($totalMarkDetail as $totalMark){
            $examTotalMarks = $examTotalMarks+$totalMark->totalMark;
        }
        //Mark Obtained by a student in selected exams
        foreach ($students as $student){
            $sqlMarks = "SELECT 
                            oeua.id,
                            oeua.oe_exams_id AS examId,
                            SUM(IF(oeua.oe_exam_answers_id IS NOT NULL,
                                oea.point,
                                oeum.mark)) AS markObtained,
                            oeua.user_id AS userId,
                            oeua.user_type AS userType,
                            user.studentName AS userName
                        FROM
                            oe_exam_user_answers oeua
                                INNER JOIN
                            studentaccount user ON (user.studentID = oeua.user_id)
                                LEFT JOIN
                            oe_exam_answers oea ON (oeua.oe_exams_id = oea.oe_exams_id
                                AND oeua.oe_exam_questions_id = oea.oe_exam_questions_id
                                AND oeua.oe_exam_answers_id = oea.id
                                AND oeua.user_type = 'STUDENT')
                                LEFT JOIN
                            oe_exam_user_mark oeum ON (oeum.oe_exams_id = oeua.oe_exams_id
                                AND oeum.oe_exam_questions_id = oeua.oe_exam_questions_id
                                AND oeua.user_id = oeum.user_id
                                AND oeum.user_type = 'STUDENT')
                        WHERE
                            oeua.oe_exams_id IN ($rules->examTypeIDs)
                            AND oeua.user_id = $student->studentID 
                            GROUP BY oeua.oe_exams_id,oeua.user_id order by markObtained desc";
            $studentMarkDetail = $this->executeQueryForList($sqlMarks);
            $combinedstotalMarks = [];
            $combinedPercentage = [];
            $combinedstudentMarks = [];
            $flag = true;
            foreach($studentMarkDetail as $s){
                $individualExamTotalDetails = CommonUtil::objArraySearch($totalMarkDetail, "id", $s->examId);
                if($individualExamTotalDetails->totalMark) {
                    $s->percentage =  round((($s->markObtained/$individualExamTotalDetails->totalMark)*100),2);
                    $s->totalMark = $individualExamTotalDetails->totalMark;
                }
                else {
                    $s->percentage = 0;
                    $s->totalMark = 0;
                }
                
                array_push($combinedPercentage,$s->percentage);
            }
            usort($studentMarkDetail,function($first,$second){
                return strtolower($first->percentage) < strtolower($second->percentage);
            });
            if(count($combinedPercentage)>1){
                $studentMarks = explode(",", $combinedPercentage);
            }
            else{
                $studentMarks = $combinedPercentage[0]?$combinedPercentage[0]:0;
            }
            if($rules->ordinalNo ){
                $studentMarks = $scaleFunction($studentMarkDetail[$rules->ordinalNo - 1]->percentage);
            }
            if ( $selectedExamsCount  == 1) {
                if($studentMarkDetail[0]->markObtained){
                    $studentMarks = $scaleFunction($studentMarkDetail[0]->percentage);
                }
            }
            else if ( $rules->isExamAvg == 1 ) {
                if(count($studentMarkDetail )){
                    foreach($studentMarkDetail as $s){
                        array_push($combinedstudentMarks,$s->markObtained);
                        array_push($combinedstotalMarks,$s->totalMark);
                    }
                    $studentMarks = array_sum($combinedstudentMarks) / $rules->examBestOf;
                }
            }
            else{
                for ( $x = 0; $x < $rules->examBestOf; $x++ ) {
                    $studentMarks = $studentMarkDetail[$x]->markObtained;
                    $studentFinalMarksInPercentage = ($studentMarks/$studentMarkDetail[$x]->totalMark)*100;
                    $studentFinalMarksInPercentage=$studentMarks?$studentFinalMarksInPercentage:0;
                    $studentMarks =  $scaleFunction($studentFinalMarksInPercentage);
                    if($studentFinalMarksInPercentage >= $internalAssessmentColumn->passPercent){
                        $studentsPassed++;
                    }
                    else{
                        $studentsFailed++;
                    }
                    $columnId=$columns[$x]->id;
                    $sqlMarkRange = "SELECT marks FROM internalAssessmentExamMarkRange WHERE internalAssessmentColumnId=$columnId AND $studentFinalMarksInPercentage BETWEEN percentFrom AND percentTo";
                    $studentFinalMark = $this->executeQueryForObject($sqlMarkRange);
                    $studentFinalMarks = $studentFinalMark->marks ? $studentFinalMark->marks : $studentMarks ;
                    $batchId = $internalAssessment->batchId?$internalAssessment->batchId:$student->batchID;
                    $values[$i] = " (".$columns[$x]->id.", ".$student->studentID.", ".$studentFinalMarks."$batchId , ".$internalAssessment->subjectId." )";
                    $i++;
                    $flag = false;
                }
            }
            if($flag){
                foreach ($columns as $column) {
                    if($studentMarks){
                        if ( !$rules->isExamAvg == 1 ){
                            $studentFinalMarksInPercentage = ($studentMarks/$column->totalMark)*100;
                        }
                        else{
                            $studentFinalMarksInPercentage = ($studentMarks/
                            ($examTotalMarks/$rules->examBestOf))*100;
                        }
                        $studentMarks =  $scaleFunction($studentFinalMarksInPercentage);
                    }
                    else{
                        $studentFinalMarksInPercentage=0;
                    }
                    
                    if($studentFinalMarksInPercentage >= $internalAssessmentColumn->passPercent){
                        $studentsPassed++;
                    }
                    else{
                        $studentsFailed++;
                    }
                    //For enabled mark ranges
                    $sqlMarkRange = "SELECT marks FROM internalAssessmentExamMarkRange WHERE internalAssessmentColumnId=$column->id AND $studentFinalMarksInPercentage BETWEEN percentFrom AND percentTo";
                    $studentFinalMark = $this->executeQueryForObject($sqlMarkRange);
    
                    $studentFinalMarks = $studentFinalMark->marks ? $studentFinalMark->marks : $studentMarks ;
    
                    $batchId = $internalAssessment->batchId?$internalAssessment->batchId:$student->batchID;
    
                    $values[$i] = " (".$column->id.", ".$student->studentID.", ".$studentFinalMarks."$batchId , ".$internalAssessment->subjectId." )";
                    $i++;
                }
            }
        }
        $sql_insert .= implode(',', $values);
        $sql_insert .= " ON DUPLICATE KEY UPDATE marks = VALUES(marks)";
        try {
            $this->executeQuery($sql_insert);
            //Update column status
            $internalAssessmentReq =new stdClass();
            $internalAssessmentReq->batchId = $internalAssessment->batchId?$internalAssessment->batchId:0;
            $internalAssessmentReq->subjectId = $internalAssessment->subjectId?$internalAssessment->subjectId:0;
            foreach ($columns as $column) {
                $this->updateColumnDetailsById($column->id,
            $internalAssessmentColumn->totalMark, $internalAssessmentReq, $studentsPassed, $studentsFailed, $internalAssessmentColumn->passPercent);
            }
            
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }    
        
    }
    /**
     * Enter Assignment marks for internal assessment by group
     * @param unknown $internalAssessmentColumn
     * @param unknown $rules
     * @param unknown $groupId
     * @throws ProfessionalException
     */
    public function insertInernalAssessmentColumnAssignmentMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId = null, $batchId = null, $semId = null, $subjectId = null) {
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $internalAssessment = $this->getInternalAssessmentById($internalAssessmentColumn->internalAssessmentId);
        $rules = $this->realEscapeObject($rules);
        $groupId = $this->realEscapeString($groupId);
        $columns = $this->getInternalAssessmentColumnByGroupId($groupId);
        $batchId = $this->realEscapeString($batchId);
        $semId = $this->realEscapeString($semId);
        $subjectId = $this->realEscapeString($subjectId);
        
        if ($internalAssessment->batchId == NULL) {
            $internalAssessment->batchId = $batchId;
            $internalAssessment->semId = $semId;
            $internalAssessment->subjectId = $subjectId;
        }
        
        if(empty($internalAssessment->batchId))
        {
            
            return ;
        }
        $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($internalAssessment->semId);
        
        $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($internalAssessment->batchId, $internalAssessment->semId);
        
        if($isCurrentSem)
        {
            $sql_assignment_mark = "SELECT am.studentID, GROUP_CONCAT(am.percentage) as percentages FROM assignment_marks am INNER JOIN batch_assignment baa ON (am.assignmentID = baa.assignmentID) inner join studentaccount sa on sa.studentID = am.studentID  inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID  WHERE baa.batchID = ".$internalAssessment->batchId." AND baa.subjectID = ".$internalAssessment->subjectId." AND baa.semID = ".$internalAssessment->semId." AND baa.assiNu IN (".$rules->assignmentNos.") and joinedSem.orderNo <= ".$semDetails->orderNo."  GROUP BY am.studentID ORDER BY am.percentage DESC;";
        }
        else
        {
            $sql_assignment_mark = "SELECT am.studentID, GROUP_CONCAT(am.percentage) as percentages FROM assignment_marks am INNER JOIN batch_assignment baa ON (am.assignmentID = baa.assignmentID) inner join studentaccount sa on sa.studentID = am.studentID  inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID  WHERE baa.batchID = ".$internalAssessment->batchId." AND baa.subjectID = ".$internalAssessment->subjectId." AND baa.semID = ".$internalAssessment->semId." AND baa.assiNu IN (".$rules->assignmentNos.") and sa.studentID in (select studentID from studentaccount sa inner join batches ba on sa.batchID = ba.batchID inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID  where ba.batchID = ".$internalAssessment->batchId." and joinedSem.orderNo <= ".$semDetails->orderNo." union select sa.studentID from failed_students fs inner join studentaccount sa on sa.studentID = fs.studentID inner join semesters fsem on fsem.semID = fs.failedInSemester inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID where previousBatch = ".$internalAssessment->batchId." and fsem.orderNo > ".$semDetails->orderNo." and joinedSem.orderNo <= ".$semDetails->orderNo." ) GROUP BY am.studentID ORDER BY am.percentage DESC;";
        }
        
        try {
            $studentMarkDetails = $this->executeQueryForList($sql_assignment_mark);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        if(empty($studentMarkDetails))
        {
            return ;
        }
        
        $sql_insert = "INSERT INTO internal_assessment_student_column_mark (internalAssessmentColumnId, studentId, marks, batchId, subjectId) VALUES ";
        $scaleFunction = function($percent) use ($rules) {
            return $percent > 0 ? ( $percent / 100 ) * $rules->assignmentMark : 0;
        };
        $values = null;
        foreach ($studentMarkDetails as $studentMarkDetail) {
            // $studentID = $studentMarkDetail->studentID;
            $marksCount = $rules->ordinalNo ? $rules->ordinalNo : $rules->assignmentBestOf;
            $studentMarks = explode(",", $studentMarkDetail->percentages);
            rsort ( $studentMarks );
            $studentMarks = array_slice ( $studentMarks, 0, $marksCount);
            $studentMarks = array_map ($scaleFunction, $studentMarks );
            if ( count ( $studentMarks ) < $marksCount ) {
                $studentMarks = array_pad ( $studentMarks, $marksCount, 0 );
            }
            if(!$rules->ordinalNo && !$rules->isassignmentAvg ) {
                for ( $i = 0; $i < $rules->assignmentBestOf; $i++ ) {
                    if((((is_array($rules->markRange[0]))&&($rules->markRange[0]['from']!=""))|| ($rules->markRange[0]->percentFrom!="")) && (((is_array($rules->markRange[0])) && ($rules->markRange[0]['to']!=""))||($rules->markRange[0]->percentTo!=""))){
                        $studentFinalMarksInPercentage = ($studentMarks[$i]/$internalAssessmentColumn->totalMark)*100;
                        $studentMarks[$i] = $studentFinalMarksInPercentage ;
                        $sqlMarkRange = "SELECT marks FROM internal_assessment_assignment_mark_range WHERE internalAssessmentColumnId=$internalAssessmentColumn->id AND $studentMarks[$i] BETWEEN percentFrom AND percentTo";
                        $studentFinalMark = $this->executeQueryForObject($sqlMarkRange);
                        $studentMarks[$i] = $studentFinalMark->marks ? $studentFinalMark->marks : $studentMarks[$i];
                    }
                    $values[] = " (".$columns[$i]->id.", ".$studentMarkDetail->studentID.", ".$studentMarks[$i].", ".$internalAssessment->batchId.", ".$internalAssessment->subjectId." )";
                }
            }
            else{
                if ( $rules->ordinalNo ) {
                    $studentMarks = $studentMarks[$rules->ordinalNo - 1];
                    
                }
                else if ( $rules->isassignmentAvg == 1 ) {
                    $studentMarks = array_sum($studentMarks) / $rules->assignmentBestOf;
                
                }
                if((((is_array($rules->markRange[0]))&&($rules->markRange[0]['from']!=""))|| ($rules->markRange[0]->percentFrom!="")) && (((is_array($rules->markRange[0])) && ($rules->markRange[0]['to']!=""))||($rules->markRange[0]->percentTo!=""))){
                    $studentFinalMarksInPercentage = ($studentMarks/$internalAssessmentColumn->totalMark)*100;
                    $studentMarks = $studentFinalMarksInPercentage ;
                    $sqlMarkRange = "SELECT marks FROM internal_assessment_assignment_mark_range WHERE internalAssessmentColumnId=$internalAssessmentColumn->id AND $studentMarks BETWEEN percentFrom AND percentTo";
                    $studentFinalMark = $this->executeQueryForObject($sqlMarkRange);
                    $studentMarks = $studentFinalMark->marks ? $studentFinalMark->marks : $studentMarks;
                }
                
    
                $values[] = " ( ".$columns[0]->id.", ".$studentMarkDetail->studentID.", ".$studentMarks.", ".$internalAssessment->batchId.", ".$internalAssessment->subjectId." )";
            }
        }
        $sql_insert .= implode(',', $values);
        $sql_insert .= " ON DUPLICATE KEY UPDATE marks = VALUES(marks)";
        try {
            $this->executeQuery($sql_insert);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Delete internal assessment column(s) on deleteing 1 column in a group , all the columns in that group will get delated
     *
     * @param int $groupId
     * @param int $limit
     * @throws ProfessionalException
     */
    public function deleteInternalAssessmentColumnByGroupId ( $groupId, $limit = null ) {
        $groupId = $this->realEscapeString($groupId);
        $limit = $this->realEscapeString($limit);
        if ( !$groupId || $limit === 0 ) {
            return;
        }
        $limitCondition = $limit ? " LIMIT $limit " : "";
        $sql = "SELECT id FROM internal_assessment_column WHERE groupId = ".$groupId." ORDER BY id DESC ".$limitCondition."";
        try {
            $columnList = $this->executeQueryForList($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        foreach ( $columnList as $column ) {
            $columnId = $column->id;
            $dependentColumns[] = $this->getFormlaDependentColumns($columnId)->columnNo;
        }
        // if (!empty($dependentColumns)) {
        if (!count($dependentColumns)) {
            $dependentColumnsStr = implode(",", $dependentColumns);
            throw new ProfessionalException(ProfessionalException::ASSESSMENT_COLUMN_DELETE_DEPENDENCY_FOUND, " Column can't be deleted !!.  Please remove the reference(s) from following column(s) [".$dependentColumnsStr."]");
        }
        else {
            $sql = "DELETE FROM internal_assessment_column WHERE groupId = ".$groupId." ORDER BY id DESC ".$limitCondition."";
            try {
                $this->executeQuery($sql);
            }
            catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
    }
    /**
     * On updating the rule of internal assessment exam column - add or remove the columns accordingly and update corresponding marks
     *
     * @param internalAssessmentColumn $internalAssessmentColumn
     * @param rules $rules
     * @throws ProfessionalException
     */
    public function addRemoveInternalAssessmentExamColumnOnUpdate ( $internalAssessmentColumn, $rules ) {
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $rules = $this->realEscapeObject($rules);
        $oldInternalAssessmentColumn = $this->getInternalAssessmentColumnById($internalAssessmentColumn->id);
        $oldRules = $this->getInternalAssessmentExamRule($internalAssessmentColumn->id);
        $groupId = $oldInternalAssessmentColumn->groupId;
        if(empty($groupId))
        {
            $groupId = $this->createInternalAssessmentColumnGroup();
            $updateSql = "UPDATE internal_assessment_column SET groupId = ".$groupId." WHERE id = ".$internalAssessmentColumn->id."";
            try {
                $this->executeQueryForObject($updateSql);
            }
            catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
        
        $sql = "SELECT COUNT(id) as columnCount FROM internal_assessment_column WHERE groupId = $groupId";
        try {
            $columnCount = $this->executeQueryForObject($sql)->columnCount;
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        // Change in MARK SELECTION METHOD
        if ( ( $oldRules->ordinalNo == 0 && $rules->ordinalNo ) || ( $oldRules->ordinalNo && $rules->ordinalNo == 0 ) ) {
            $limit = $columnCount - 1;
            // Rule changed from SELECT BEST -> ORDINAL NO
            if ( $rules->ordinalNo > 0 ) {
                if ( $limit > 0 ) {
                    $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
                }
            }
            // Rule changed from ORDINAL NO -> SELECT BEST
            else if ( $rules->ordinalNo == 0 ) {
                // Rule change in AVG
                if ( $oldRules->isExamAvg != $rules->isExamAvg ) {
                    // Rule is AVG ( SELECT BEST )
                    if ( $rules->isExamAvg == 1 ) {
                        if ( $limit > 0 ) {
                            $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
                        }
                    }
                }
                if ( $rules->isExamAvg == 0 ) {
                    if ( $rules->examBestOf > 1 ) {
                        $this->addInternalAssessmentColumn($internalAssessmentColumn, $rules, $groupId);
                    }
                }
            }
        }
        // change in isAvg : either new columns are added or everything except 1 will get deleted
        else if ( $oldRules->isExamAvg != $rules->isExamAvg ) {
            $limit = $columnCount - 1;
            if ( $rules->isExamAvg == 1 ) {
                if ( $limit > 0 ) {
                    $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
                }
            }
            else if ( $rules->isExamAvg == 0 ) {
                if ( $rules->examBestOf > 1 ) {
                    $this->addInternalAssessmentColumn($internalAssessmentColumn, $rules, $groupId);
                }
            }
        }
        else if ( $oldRules->examBestOf != $rules->examBestOf && $rules->isExamAvg == 0 ) {
            if ( $oldRules->examBestOf > $rules->examBestOf ) {
                $limit = $oldRules->examBestOf - $rules->examBestOf;
                $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
            }
            else {
                $this->addInternalAssessmentColumn($internalAssessmentColumn, $rules, $groupId);
            }
        }
        $this->updateInternalAssessmentColumnByGroupId ( $internalAssessmentColumn, $groupId );
        $this->updateInternalAssessmentExamRuleByGroupId ( $rules, $groupId );
        if($internalAssessmentColumn->ruleType == "EXAM"){
            $this->insertInernalAssessmentColumnExamMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId );
        }
        else{
            $this->insertInernalAssessmentColumnOnlineExamMarks ( $internalAssessmentColumn, $rules, $groupId );
        }
        
    }
    /**
     * On updating the rule of internal assessment Assignment column - add or remove the columns accordingly and update corresponding marks
     *
     * @param internalAssessmentColumn $internalAssessmentColumn
     * @param rules $rules
     * @throws ProfessionalException
     */
    public function addRemoveInternalAssessmentAssignmentColumnOnUpdate ( $internalAssessmentColumn, $rules ) {
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $rules = $this->realEscapeObject($rules);
        $oldInternalAssessmentColumn = $this->getInternalAssessmentColumnById($internalAssessmentColumn->id);
        $oldRules = $this->getInternalAssessmentAssignmentRule($internalAssessmentColumn->id);
        $groupId = $oldInternalAssessmentColumn->groupId;
        if(empty($groupId))
        {
            $groupId = $this->createInternalAssessmentColumnGroup();
            $updateSql = "UPDATE internal_assessment_column SET groupId = ".$groupId." WHERE id = ".$internalAssessmentColumn->id."";
            try {
                $this->executeQueryForObject($updateSql);
            }
            catch (\Exception $e) {
                throw new ProfessionalException($e->getCode(), $e->getMessage());
            }
        }
        
        $sql = "SELECT COUNT(id) as columnCount FROM internal_assessment_column WHERE groupId = $groupId";
        try {
            $columnCount = $this->executeQueryForObject($sql)->columnCount;
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        // Change in MARK SELECTION METHOD
        if ( ( $oldRules->ordinalNo == 0 && $rules->ordinalNo ) || ( $oldRules->ordinalNo && $rules->ordinalNo == 0 ) ) {
            $limit = $columnCount - 1;
            // Rule changed from SELECT BEST -> ORDINAL NO
            if ( $rules->ordinalNo > 0 ) {
                if ( $limit > 0 ) {
                    $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
                }
            }
            // Rule changed from ORDINAL NO -> SELECT BEST
            else if ( $rules->ordinalNo == 0 ) {
                // Rule change in AVG
                if ( $oldRules->isassignmentAvg != $rules->isassignmentAvg ) {
                    // Rule is AVG ( SELECT BEST )
                    if ( $rules->isassignmentAvg == 1 ) {
                        if ( $limit > 0 ) {
                            $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
                        }
                    }
                }
                if ( $rules->isassignmentAvg == 0 ) {
                    if ( $rules->assignmentBestOf > 1 ) {
                        $this->addInternalAssessmentColumn($internalAssessmentColumn, $rules, $groupId);
                    }
                }
            }
        }
        // change in isAvg : either new columns are added or everything except 1 will get deleted
        else if ( $oldRules->isassignmentAvg != $rules->isassignmentAvg ) {
            $limit = $columnCount - 1;
            if ( $rules->isassignmentAvg == 1 ) {
                if ( $limit > 0 ) {
                    $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
                }
            }
            else if ( $rules->isassignmentAvg == 0 ) {
                if ( $rules->assignmentBestOf > 1 ) {
                    $this->addInternalAssessmentColumn($internalAssessmentColumn, $rules, $groupId);
                }
            }
        }
        else if ( $oldRules->assignmentBestOf != $rules->assignmentBestOf && $rules->isassignmentAvg == 0 ) {
            if ( $oldRules->assignmentBestOf > $rules->assignmentBestOf ) {
                $limit = $oldRules->assignmentBestOf - $rules->assignmentBestOf;
                $this->deleteInternalAssessmentColumnByGroupId ( $groupId, $limit );
            }
            else {
                $this->addInternalAssessmentColumn($internalAssessmentColumn, $rules, $groupId);
            }
        }
        $this->updateInternalAssessmentColumnByGroupId ( $internalAssessmentColumn, $groupId );
        $this->updateInternalAssessmentAssignmentRuleByGroupId ( $rules, $groupId );
        $this->insertInernalAssessmentColumnAssignmentMarksByGroupId ( $internalAssessmentColumn, $rules, $groupId );
    }
    public function updateInternalAssessmentColumnByGroupId ( $internalAssessmentColumn, $groupId ) {
        $internalAssessmentColumn = $this->realEscapeObject($internalAssessmentColumn);
        $groupId = $this->realEscapeString($groupId);
        $sql = "UPDATE internal_assessment_column SET columnName = '".$internalAssessmentColumn->columnName."', totalMark = '".$internalAssessmentColumn->totalMark."', passPercent = '".$internalAssessmentColumn->passPercent."', updatedBy = ".$internalAssessmentColumn->updatedBy.", updatedDate = utc_timestamp() WHERE groupId = ".$groupId."";
        try {
            $this->executeQuery ( $sql );
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * check if the column rule type is attendance hours
     * @param string $columnNo
     * @param int $internalAssessmentId
     * @throws ProfessionalException
     * @return boolean
     */
    public function isColumnRuleTypeAttendanceHours($columnNo, $internalAssessmentId)
    {
        $columnNo = $this->realEscapeString($columnNo);
        $internalAssessmentId = $this->realEscapeString($internalAssessmentId);
        
        $sql = "select attrule.ruleType from internal_assessment_column clm inner join internal_assessment_attendance_rule attrule on clm.id = attrule.internalAssessmentColumnId where clm.internalAssessmentId = ".$internalAssessmentId." and clm.columnNo = '".$columnNo."'";
        
        try {
            $ruleType = $this->executeQueryForObject($sql);
            if ($ruleType->ruleType == InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS || $ruleType->ruleType == InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_PRESENT || $ruleType->ruleType == InternalAssessmentAttendanceRuleType::ATTENDANCE_HOURS_ABSENT)
            {
                return true;
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return false;
    }
    /**
     * Get internal assessment column by column no
     * @param int $columnNo
     * @param int $internalAssessmentId
     * @throws ProfessionalException
     */
    public function getInternalAssessmentColumnByColumnNo($columnNo, $internalAssessmentId)
    {
        $columnNo = $this->realEscapeString($columnNo);
        $internalAssessmentId = $this->realEscapeString($internalAssessmentId);
        
        $sql = "SELECT id, internalAssessmentId, columnNo, columnName, ruleType, passPercent, totalMark FROM internal_assessment_column WHERE internalAssessmentId = ".$internalAssessmentId." AND columnNo = '".$columnNo."'";
        
        try {
            return $this->executeQueryForObject($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get mark rannge of internal assessment exam rule
     * @param int $columnId
     * @throws ProfessionalException
     */
    public function getInternalAssessmentExamMarkRange($columnId){
        $columnId = $this->realEscapeString($columnId);
        
        $sql = "SELECT id, internalAssessmentColumnId, percentFrom, percentTo, marks FROM internalAssessmentExamMarkRange WHERE internalAssessmentColumnId = ".$columnId;
        
        try {
            return $this->executeQueryForList($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Get mark rannge of internal assessment assignment rule
     * @param int $columnId
     * @throws ProfessionalException
     */
    public function getInternalAssessmentAssignmentMarkRange($columnId){
        $columnId = $this->realEscapeString($columnId);
        
        $sql = "SELECT id, internalAssessmentColumnId, percentFrom, percentTo, marks FROM internal_assessment_assignment_mark_range WHERE internalAssessmentColumnId = ".$columnId;
        
        try {
            return $this->executeQueryForList($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getConsolidatedAssessmentReport($assessmentId, $semId, $batchId,$columnId) {
        $assessmentReport = NULL;
        $assessmentDetails = $this->getInternalAssessmentById($assessmentId);
        if ($assessmentDetails->batchId == NULL && $assessmentDetails->semId == NULL && $batchId == NULL) {
            return $assessmentReport;
        }
        $assessmentId = $this->realEscapeString($assessmentId);
        $semId        = $this->realEscapeString($semId);
        $isCurrentSem = SemesterService::getInstance()->isCurrentSemester($batchId, $semId);
        if ($isCurrentSem) {
            $sql = "SELECT sa.studentID, sa.studentName,sa.regNo, sa.rollNo, iac.columnName,iac.columnNo, iam.marks, iac.id, iac.ruleType, iac.totalMark,iam.subjectID,s.subjectName FROM studentaccount sa inner join batches ba on ba.batchID = sa.batchID inner join semesters sem on sem.semID = ba.semID inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID INNER JOIN internal_assessment ia ON (sa.batchId = IF(ia.batchID <> NULL, ia.batchID, '$batchId' ))  LEFT JOIN internal_assessment_column iac ON iac.internalAssessmentId=ia.id LEFT JOIN internal_assessment_student_column_mark iam ON iam.internalAssessmentColumnId=iac.id AND sa.studentID=iam.studentId AND iam.batchId=$batchId LEFT JOIN subjects s ON s.subjectID=iam.subjectID WHERE ia.id=$assessmentId and joinedSem.orderNo <= sem.orderNo  AND iac.id=$columnId ORDER BY sa.rollNo, iac.columnNo";
            
        } else {
            $semDetails = SemesterService::getInstance()->getSemDetailsBySemId($semId);
            
            $sql = "SELECT sa.studentID, sa.studentName,sa.regNo, sa.rollNo, iac.columnName,iac.columnNo, iam.marks, iac.id, iac.ruleType, iac.totalMark,iam.subjectID,s.subjectName FROM studentaccount sa LEFT JOIN failed_students fs on sa.studentID = fs.studentID AND fs.reason <> 'BATCH_SHUFFLE' INNER JOIN internal_assessment ia ON (sa.batchId = IF(ia.batchID <> NULL, ia.batchID, '$batchId' ) or fs.previousBatch = IF(ia.batchID <> NULL, ia.batchID, '$batchId' )) left join semesters fsem on fsem.semID = fs.failedInSemester  inner join semesters joinedSem on sa.joiningSemId = joinedSem.semID LEFT JOIN internal_assessment_column iac ON iac.internalAssessmentId=ia.id LEFT JOIN internal_assessment_student_column_mark iam ON iam.internalAssessmentColumnId=iac.id AND sa.studentID=iam.studentId AND iam.batchId=$batchId LEFT JOIN subjects s ON s.subjectID=iam.subjectID WHERE ia.id='$assessmentId'  and (fsem.orderNo > $semDetails->orderNo or fsem.orderNo is null)  and joinedSem.orderNo <= $semDetails->orderNo  AND iac.id=$columnId ORDER BY sa.rollNo, iac.columnNo";
        }
        
        try
        {
            $assessmentReport = $this->executeQueryForList($sql, $this->mapper[AssessmentServiceMapper::GET_CONSOLIDATED_ASSESSMENT_REPORT]);
        }
         catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $assessmentReport;
    }
    
    /**
     * batches/ subjects assigned for assessments created in custom reports
     * @param int $assessmentId
     * @throws ProfessionalException
     */
    public function    getAssignedBatchesOrSubjectsInInternalAssessment($assessmentId){
        $assessmentId = $this->realEscapeString($assessmentId);
        
        $sql = "SELECT id,batches FROM internal_assessment_assigned_batches  WHERE internal_assessment_id  = $assessmentId";
        
        try {
            return $this->executeQueryForObject($sql);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Updating max mark for the given $assessmentIds with $maxMark
     * @param $assessmentIds , $maxMark
     * @throws ProfessionalException
     */
    public function    updateMaxMarksInExams($assessmentIds,$maxMark){
        $assessmentIds = $this->realEscapeArray($assessmentIds);
        $maxMark = $this->realEscapeString($maxMark);
        try {
            $assessmentIdsWhereCondition = " oe.identifying_context->>'$.assessmentId' IN ('".implode("','",$assessmentIds)."') ";    
            $attendedCountQuery = "    SELECT
                                        oe.id
                                    FROM
                                        oe_exam_user_log oeul
                                    LEFT JOIN oe_exams oe ON
                                        oe.id = oeul.oe_exams_id
                                    WHERE
                                        $assessmentIdsWhereCondition
                                    GROUP BY 
                                        oe.id
                                    HAVING 
                                        COUNT(DISTINCT oeul.user_id) > 0;";
            $userAttendedExamsCount = $this->executeQueryForList($attendedCountQuery);
            if (count($userAttendedExamsCount) > 0) {
                throw new ProfessionalException ( ProfessionalException::USER_ATTENDED, "Exams cannot be edited since in some exams students have been attended");
            }
            $assessmentIdsToBeUpdatedQuery = "    SELECT 
                                                    oe.identifying_context->>'$.assessmentId' AS assessmentId
                                                FROM 
                                                    oe_exams oe
                                                WHERE 
                                                    oe.properties->>'$.maxMark' != '$maxMark'
                                                    AND $assessmentIdsWhereCondition ;";
            $assessmentIdsToBeUpdated = $this->executeQueryForList($assessmentIdsToBeUpdatedQuery);
            $assessmentIdsToBeUpdated = array_map(function($a) {return $a->assessmentId;},$assessmentIdsToBeUpdated);
            $assessmentIdsToBeUpdatedWhereCondition = "('".implode("','",$assessmentIdsToBeUpdated)."')";    
            $oeExamUpdateQuery = "    UPDATE
                                        oe_exams
                                    SET
                                        properties = JSON_SET(properties,\"$.maxMark\",'$maxMark'),
                                        settings = JSON_SET(settings,\"$.isValidated\",'0'),
                                        updated_by = 0
                                    WHERE
                                        identifying_context->>'$.assessmentId' IN $assessmentIdsToBeUpdatedWhereCondition ;";
            $amAssessmentUpdateQuery = "    UPDATE
                                                am_assessment
                                            SET
                                                properties_value = JSON_SET(properties_value,\"$.maxMark\",'$maxMark'),
                                                updated_by = 0
                                            WHERE
                                                id IN $assessmentIdsToBeUpdatedWhereCondition ;";
        
            $this->executeQuery($oeExamUpdateQuery);
            $this->executeQuery($amAssessmentUpdateQuery);
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function getCustomReportOfStudentBatch($batchID)
    {
        try{
            $selectedAssessments = [];
            $sql = "SELECT iaab.internal_assessment_id ,
                                                ia.name ,
                                                iaab.batches  
                                        from internal_assessment_assigned_batches iaab 
                                        inner join internal_assessment ia on ia.id = iaab.internal_assessment_id
                                        WHERE ia.isPublished = 1;";
            $assessments = $this->executeQueryForList($sql);
            foreach ($assessments as $key => $assessment) {
                $batches = json_decode($assessment->batches);
                $batchIds = $batches->batchIds;
                if(in_array($batchID, $batchIds))
                {
                    $subjects = SubjectService::getInstance()->getSubjectsByBatchId($batchID);
                    $temp = $assessment;
                    $temp->subjects = count($subjects) > 0 ? $subjects : [];
                    $selectedAssessments[] = $temp;
                }
            }
            return $selectedAssessments;
        }
        catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    public function checkAttendancRuleIsGenderWise($internalAssessmentColumnId)
    {
        try{
                $internalAssessmentColumnId = $this->realEscapeString($internalAssessmentColumnId);
                $sql = "SELECT id from internal_assessment_attendance_genderwise_rule WHERE internalAssessmentColumnId = '$internalAssessmentColumnId'";
                $result = $this->executeQueryForObject($sql) ? true : false;
                return $result;
        }catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
}