/home/techb158/ileadtechnology.com/SSM/app/Repositories/exam
Edit: /home/techb158/ileadtechnology.com/SSM/app/Repositories/exam/OnlineExamRepository.php (27281B)
online_exam = $online_exam;
$this->course_group = $course_group;
$this->batch = $batch;
$this->subject = $subject;
$this->online_exam_question = $online_exam_question;
$this->student = $student;
$this->online_exam_record = $online_exam_record;
$this->student_record = $student_record;
}
/**
* Get online exam query
*
* @return Online Exam query
*/
public function getQuery()
{
return $this->online_exam;
}
/**
* Count exam
*
* @return integer
*/
public function count()
{
return $this->online_exam->filterBySession()->count();
}
/**
* List all online exams by name & id
*
* @return array
*/
public function listAll()
{
return $this->online_exam->filterBySession()->get()->pluck('name', 'id')->all();
}
/**
* List all online exams by name & id for select option
*
* @return array
*/
public function selectAll()
{
return $this->online_exam->filterBySession()->get(['name', 'id']);
}
/**
* List all online exams by id
*
* @return array
*/
public function listId()
{
return $this->online_exam->filterBySession()->get()->pluck('id')->all();
}
/**
* Get all online exams
*
* @return array
*/
public function getAll()
{
return $this->online_exam->filterBySession()->get();
}
/**
* Find online exam with given id.
*
* @param integer $id
* @return OnlineExam
*/
public function find($id)
{
return $this->online_exam->info()->filterBySession()->filterById($id)->first();
}
/**
* Find online exam with given id or throw an error.
*
* @param integer $id
* @return OnlineExam
*/
public function findOrFail($id, $field = 'message')
{
$online_exam = $this->online_exam->info()->filterBySession()->filterById($id)->first();
if (! $online_exam) {
throw ValidationException::withMessages([$field => trans('exam.could_not_find_online_exam')]);
}
return $online_exam;
}
/**
* Find online exam with given uuid.
*
* @param uuid $uuid
* @return OnlineExam
*/
public function findByUuid($uuid)
{
return $this->online_exam->info()->filterBySession()->filterByUuid($uuid)->first();
}
/**
* Find online exam with given uuid or throw an error.
*
* @param uuid $uuid
* @return OnlineExam
*/
public function findByUuidOrFail($uuid, $field = 'message')
{
$online_exam = $this->online_exam->info()->filterBySession()->filterByUuid($uuid)->first();
if (! $online_exam) {
throw ValidationException::withMessages([$field => trans('exam.could_not_find_online_exam')]);
}
return $online_exam;
}
/**
* Find online exam with given uuid or throw an error.
*
* @param uuid $uuid
* @return OnlineExam
*/
public function findSummaryByUuidOrFail($uuid, $field = 'message')
{
$online_exam = $this->online_exam->summary()->filterBySession()->filterByUuid($uuid)->first();
if (! $online_exam) {
throw ValidationException::withMessages([$field => trans('exam.could_not_find_online_exam')]);
}
return $online_exam;
}
/**
* Get all filtered data
*
* @param array $params
* @return OnlineExam
*/
public function getData($params)
{
$sort_by = gv($params, 'sort_by', 'date');
$order = gv($params, 'order', 'desc');
$name = gv($params, 'name');
$batch_id = gv($params, 'batch_id');
$batch_id = is_array($batch_id) ? $batch_id : ($batch_id ? explode(',', $batch_id) : []);
$query = $this->online_exam->summary()->filterBySession()->filterByName($name);
if (\Auth::user()->hasAnyRole([
config('system.default_role.parent'),
config('system.default_role.student'),
])
) {
$query->whereIsPublished(1);
$student_batch_ids = getAuthUserBatchId();
$batch_id = $batch_id ? array_intersect($student_batch_ids, $batch_id) : $student_batch_ids;
}
$batch_id = array_unique($batch_id);
if (count($batch_id)) {
$query->whereIn('batch_id', $batch_id);
}
return $query->orderBy($sort_by, $order);
}
/**
* Paginate all online exams using given params.
*
* @param array $params
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
public function paginate($params)
{
$page_length = gv($params, 'page_length', config('config.page_length'));
return $this->getData($params)->paginate($page_length);
}
/**
* Get all filtered data for printing
*
* @param array $params
* @return OnlineExam
*/
public function print($params)
{
return $this->getData($params)->get();
}
/**
* Get online exam pre requisite.
*
* @return Array
*/
public function getPreRequisite()
{
$batches = $this->course_group->getBatchOption();
$batch_with_subjects = $this->batch->getAllBatchWithSubjects();
$exam_types = getOnlineExamTypes();
$online_exam_question_types = getOnlineExamQuestionTypes();
return compact('batches', 'batch_with_subjects', 'exam_types', 'online_exam_question_types');
}
/**
* Get exam schedule filters.
*
* @return Array
*/
public function getFilters()
{
return $this->getPreRequisite();
}
/**
* Create a new online exam.
*
* @param array $params
* @return OnlineExam
*/
public function create($params)
{
return $this->online_exam->forceCreate($this->formatParams($params));
}
/**
* Prepare given params for inserting into database.
*
* @param array $params
* @param string $type
* @return array
*/
private function formatParams($params, $online_exam_id = null)
{
$name = gv($params, 'name');
$description = gv($params, 'description');
$instructions = gv($params, 'instructions');
$batch = $this->batch->findOrFail(gv($params, 'batch_id'));
if (! in_array(gv($params, 'subject_id'), $batch->subjects->pluck('id')->all())) {
throw ValidationException::withMessages(['subject_id' => trans('academic.could_not_find_subject')]);
}
$data = getVar('data');
$online_exam_types = gv($data, 'online_exam_types', []);
if (! in_array(gv($params, 'exam_type'), $online_exam_types)) {
throw ValidationException::withMessages(['exam_type' => trans('general.invalid_input')]);
}
$date = toDate(gv($params, 'date'));
if (! dateBetweenSession($date)) {
throw ValidationException::withMessages(['date' => trans('academic.invalid_session_date_range')]);
}
if ($date < date('Y-m-d')) {
throw ValidationException::withMessages(['date' => trans('exam.online_exam_date_should_gte_today')]);
}
$start_time = gv($params, 'start_time');
$end_time = gv($params, 'end_time');
if (strtotime($start_time) === false) {
throw ValidationException::withMessages(['message' => trans('exam.invalid_exam_start_time')]);
}
if (strtotime($end_time) === false) {
throw ValidationException::withMessages(['message' => trans('exam.invalid_exam_end_time')]);
}
if (toTime($start_time) > toTime($end_time)) {
throw ValidationException::withMessages(['message' => trans('exam.online_exam_start_time_should_lt_end_time')]);
}
$query = (! $online_exam_id) ? $this->online_exam : $this->online_exam->where('id', '!=', $online_exam_id);
$online_exam_exists = $query->filterByName($name, 1)->filterBySession()->count();
if ($online_exam_exists) {
throw ValidationException::withMessages(['name' => trans('exam.online_exam_exists')]);
}
if (gv($params, 'exam_type') == 'mcq' && $online_exam_id) {
if ($this->online_exam_question->whereOnlineExamId($online_exam_id)->where('question_type', '!=', 'mcq')->count()) {
throw ValidationException::withMessages(['exam_type' => trans('exam.online_exam_mixed_question_type_found')]);
}
}
$formatted = [
'batch_id' => $batch->id,
'subject_id' => gv($params, 'subject_id'),
'name' => $name,
'description' => $description,
'exam_type' => gv($params, 'exam_type'),
'date' => toDate($date),
'start_time' => toTime($start_time),
'end_time' => toTime($end_time),
'passing_percentage' => gv($params, 'passing_percentage', 0),
'is_negative_mark_applicable' => gbv($params, 'is_negative_mark_applicable'),
'negative_mark_percentage_per_question' => gv($params, 'negative_mark_percentage_per_question', 0),
'instructions' => cleanBody($instructions),
'options' => []
];
if (! $online_exam_id) {
$formatted['uuid'] = \Str::uuid();
$formatted['academic_session_id'] = config('config.default_academic_session.id');
}
return $formatted;
}
/**
* Is online exam editable
* @param OnlineExam $online_exam
* @return boolean
*/
private function isEditable(OnlineExam $online_exam)
{
if (! $online_exam->is_editable) {
throw ValidationException::withMessages(['message' => trans('user.permission_denied')]);
}
}
/**
* Update given online exam.
*
* @param Online Exam $online_exam
* @param array $params
*
* @return Exam
*/
public function update(OnlineExam $online_exam, $params)
{
$this->isEditable($online_exam);
return $online_exam->forceFill($this->formatParams($params, $online_exam->id))->save();
}
/**
* Find online exam & check it can be deleted or not.
*
* @param uuid $uuid
* @return OnlineExam
*/
public function deletable($uuid)
{
$online_exam = $this->findByUuidOrFail($uuid);
$this->isEditable($online_exam);
if ($online_exam->questions()->count()) {
throw ValidationException::withMessages(['message' => trans('exam.online_exam_associated_with_questions')]);
}
return $online_exam;
}
/**
* Delete online exam.
*
* @param integer $id
* @return bool|null
*/
public function delete(OnlineExam $online_exam)
{
return $online_exam->delete();
}
/**
* Delete multiple online exams.
*
* @param array $ids
* @return bool|null
*/
public function deleteMultiple($ids)
{
return $this->online_exam->whereIn('id', $ids)->delete();
}
/**
* Find question or fail
* @param OnlineExam $online_exam
* @param integer $id
* @return OnlineExamQuestion
*/
public function findQuestionOrFail(OnlineExam $online_exam, $id)
{
$online_exam_question = $this->online_exam_question->whereOnlineExamId($online_exam->id)->whereId($id)->first();
if (! $online_exam_question) {
throw ValidationException::withMessages(['message' => trans('exam.could_not_find_online_exam_question')]);
}
return $online_exam_question;
}
/**
* Add question to exam
* @param OnlineExam $online_exam
* @param array $params
*/
public function addQuestion(OnlineExam $online_exam, $params = array())
{
$this->isEditable($online_exam);
$online_exam_question = $this->online_exam_question->forceCreate($this->formatQuestionParams($params, $online_exam));
$online_exam->increment('max_mark', $online_exam_question->mark);
return $online_exam_question;
}
/**
* Update question of exam
* @param OnlineExam $online_exam
* @param array $params
*/
public function updateQuestion(OnlineExamQuestion $online_exam_question, $params = array())
{
$this->isEditable($online_exam);
$mark = $online_exam_question->mark;
$online_exam_question->forceFill($this->formatQuestionParams($params, $online_exam_question->onlineExam, $online_exam_question->id))->save();
if ($mark != $online_exam_question->mark) {
$online_exam = $online_exam_question->onlineExam;
$online_exam->decrement('max_mark', $mark);
$online_exam->increment('max_mark', $online_exam_question->mark);
}
}
/**
* Format question params
* @param array $params
* @param object $online_exam
* @param integer $online_exam_question_id
* @return array
*/
private function formatQuestionParams($params = array(), $online_exam, $online_exam_question_id = null)
{
$question = gv($params, 'question');
$question_type = gv($params, 'question_type');
$mark = gv($params, 'mark');
$image = gv($params, 'image');
$answers = gv($params, 'options');
if (\Storage::exists($image)) {
throw ValidationException::withMessages(['message' => trans('exam.image_doesnt_exist')]);
}
$query = $this->online_exam_question->whereOnlineExamId($online_exam->id);
if ($online_exam_question_id) {
$query->where('id', '!=', $online_exam_question_id);
}
$question_exists = $query->where('question', '=', $question)->count();
if ($question_exists) {
throw ValidationException::withMessages(['message' => trans('exam.online_exam_question_exists')]);
}
$data = getVar('data');
$online_exam_question_types = gv($data, 'online_exam_question_types', []);
if (! in_array($question_type, $online_exam_question_types)) {
throw ValidationException::withMessages(['question_type' => trans('general.invalid_input')]);
}
if ($online_exam->exam_type == 'mcq' && $question_type != 'mcq') {
throw ValidationException::withMessages(['message' => trans('general.invalid_input')]);
}
$answers = $this->validateMCQAnswer($params);
$formatParams = array(
'question' => $question,
'question_type' => $question_type,
'mark' => $mark,
'image' => $image,
'answers' => $answers
);
if (! $online_exam_question_id) {
$formatParams['upload_token'] = \Str::uuid();
$formatParams['options'] = [];
$formatParams['online_exam_id'] = $online_exam->id;
}
return $formatParams;
}
/**
* Validate MCQ answers
* @param array $params [description]
* @return void
*/
private function validateMCQAnswer($params = array())
{
$question_type = gv($params, 'question_type');
$answers = gv($params, 'options', []);
if ($question_type != 'mcq') {
return;
}
if (! count($answers)) {
throw ValidationException::withMessages(['message' => trans('exam.no_answer_found')]);
}
$titles = array();
$no_correct_answer_count = 0;
$data = array();
foreach ($answers as $answer) {
$title = gv($answer, 'title');
$image = gv($answer, 'image');
$is_correct_answer = gbv($answer, 'is_correct_answer');
$titles[] = $title;
if (! $is_correct_answer) {
$no_correct_answer_count++;
}
if (\Storage::exists($image)) {
throw ValidationException::withMessages(['message' => trans('exam.image_doesnt_exist')]);
}
$data[] = array(
'title' => $title,
'image' => $image,
'is_correct_answer' => $is_correct_answer
);
}
if (count($titles) > count(array_unique($titles))) {
throw ValidationException::withMessages(['message' => trans('exam.duplicate_answer_found')]);
}
if (count($answers) == $no_correct_answer_count) {
throw ValidationException::withMessages(['message' => trans('exam.no_correct_answer_chosen')]);
}
return $data;
}
/**
* Delete question
* @param OnlineExamQuestion $online_exam_question
* @return void
*/
public function deleteQuestion(OnlineExamQuestion $online_exam_question)
{
$this->isEditable($online_exam);
$online_exam = $online_exam_question->onlineExam;
$online_exam->decrement('max_mark', $online_exam_question->mark);
$online_exam_question->delete();
}
/**
* Toggle online exam status
* @param OnlineExam $online_exam
* @return void
*/
public function toggleStatus(OnlineExam $online_exam)
{
if ($online_exam->records->count()) {
throw ValidationException::withMessages(['message' => trans('user.permission_denied')]);
}
$status = request('status');
if (! in_array($status, ['publish', 'draft'])) {
throw ValidationException::withMessages(['message' => trans('general.invalid_action')]);
}
if ($online_exam->is_published && $status == 'publish') {
throw ValidationException::withMessages(['message' => trans('general.invalid_action')]);
}
if (! $online_exam->is_published && $status == 'draft') {
throw ValidationException::withMessages(['message' => trans('general.invalid_action')]);
}
$online_exam->is_published = $status == 'publish' ? 1 : 0;
$online_exam->save();
}
/**
* Is online exam available to student & parent
* @param OnlineExam $online_exam
* @return boolean
*/
public function isAvailableToStudentAndParent(OnlineExam $online_exam)
{
if (! \Auth::user()->hasAnyRole([
config('system.default_role.parent'),
config('system.default_role.student')
])) {
return;
}
if (! $online_exam->is_published) {
throw ValidationException::withMessages(['message' => trans('exam.online_exam_restricted')]);
}
if (\Auth::user()->hasAnyRole([
config('system.default_role.parent'),
config('system.default_role.student'),
])
) {
$student_batch_ids = getAuthUserBatchId();
if (! in_array($online_exam->batch_id, $student_batch_ids)) {
throw ValidationException::withMessages(['message' => trans('exam.online_exam_restricted')]);
}
}
if ($online_exam->status == 'upcoming') {
throw ValidationException::withMessages(['message' => trans('exam.online_exam_restricted')]);
}
if (\Auth::user()->hasRole(config('system.default_role.parent')) && $online_exam->status != 'expired') {
throw ValidationException::withMessages(['message' => trans('exam.online_exam_restricted')]);
}
}
/**
* Get online exam questions
* @param OnlineExam $online_exam
* @return array
*/
public function getOnlineExamQuestions(OnlineExam $online_exam)
{
$questions = $this->online_exam_question->whereOnlineExamId($online_exam->id)->orderBy('position', 'asc')->get();
$data = array();
foreach ($questions as $question) {
$options = $question->answers;
$answers = array();
foreach ($options as $option) {
$item = array(
'title' => gv($option, 'title'),
'image' => gv($option, 'image')
);
if ($online_exam->status == 'expired') {
$item['is_correct_answer'] = gbv($option, 'is_correct_answer');
}
$answers[] = $item;
}
$data[] = array(
'id' => $question->id,
'question' => $question->question,
'image' => $question->image,
'mark' => $question->mark,
'question_type' => $question->question_type,
'answers' => $answers
);
}
return $data;
}
/**
* Get online exam record
* @param OnlineExam $online_exam
* @return OnlineExamRecord
*/
public function getOnlineExamRecord(OnlineExam $online_exam)
{
$student_record = $this->student->getAuthStudentRecord($online_exam->batch_id);
if (! $student_record) {
return;
}
return $this->online_exam_record->whereOnlineExamId($online_exam->id)->whereStudentRecordId($student_record->id)->first();
}
/**
* Get online exam record by id
* @param OnlineExam $online_exam
* @param integer $id
* @return OnlineExamRecord
*/
public function getOnlineExamRecordById(OnlineExam $online_exam, $id)
{
return $this->online_exam_record->with('studentRecord', 'studentRecord.student', 'studentRecord.student.parent', 'studentRecord.batch', 'studentRecord.batch.course')->whereOnlineExamId($online_exam->id)->whereId($id)->first();
}
/**
* Store online exam records
* @param OnlineExam $online_exam
* @param array $params
* @return void
*/
public function storeExam(OnlineExam $online_exam, $params = array())
{
$student_record = $this->student->getAuthStudentRecord($online_exam->batch_id);
if (! $student_record) {
throw ValidationException::withMessages(['message' => trans('general.invalid_input')]);
}
$online_exam_record = $this->online_exam_record->firstOrCreate([
'online_exam_id' => $online_exam->id,
'student_record_id' => $student_record->id
]);
if ($online_exam_record->end) {
return;
}
if (! $online_exam_record->start) {
$online_exam_record->start = now();
$online_exam_record->save();
}
$questions = gv($params, 'answers', []);
$online_exam_questions = $online_exam->questions;
$answers = array();
$obtained_mark = 0;
foreach ($questions as $question) {
$question_id = gv($question, 'id');
$online_exam_question = $online_exam_questions->firstWhere('id', $question_id);
if (! $online_exam_question) {
throw ValidationException::withMessages(['message' => trans('general.invalid_action')]);
}
$answer = gv($question, 'answer');
if ($answer && $online_exam_question->question_type == 'mcq') {
$question_answers = gkv($online_exam_question->answers, 'title');
if (! in_array($answer, $question_answers)) {
throw ValidationException::withMessages(['message' => trans('general.invalid_action')]);
}
$question_answer = searchByKey($online_exam_question->answers, 'title', $answer);
if ($question_answer && gbv($question_answer, 'is_correct_answer')) {
$obtained_mark += $online_exam_question->mark;
} else if ($online_exam->is_negative_mark_applicable && $question_answer && ! gbv($question_answer, 'is_correct_answer')) {
$obtained_mark -= ($online_exam_question->mark * $online_exam->negative_mark_percentage_per_question / 100);
}
}
$answers[] = array(
'question_id' => $question_id,
'answer' => $answer
);
}
$online_exam_record->answers = $answers;
$online_exam_record->obtained_mark = $obtained_mark;
if (request('is_final')) {
$online_exam_record->end = now();
}
$online_exam_record->save();
}
/**
* Get Students of Online Exam
* @param OnlineExam $online_exam
* @return array
*/
public function getStudents(OnlineExam $online_exam)
{
$date = toDate($online_exam->date);
$student_records = $this->student_record->with('student', 'student.parent', 'batch', 'batch.course')->filterBySession()->filterbyBatchId($online_exam->batch_id)->where('date_of_entry', '<=', $date)->where(function ($q) use ($date) {
$q->where('date_of_exit', null)->orWhere(function ($q1) use ($date) {
$q1->where('date_of_exit', '!=', null)->where('date_of_exit', '>=', $date);
});
})->orderBy('roll_number', 'asc')->get();
$students = array();
$online_exam_records = $online_exam->records;
foreach ($student_records as $student_record) {
$online_exam_record = $online_exam_records->firstWhere('student_record_id', $student_record->id);
$students[] = array(
'record_id' => optional($online_exam_record)->id,
'name' => $student_record->student->name,
'roll_number' => getRollNumber($student_record),
'start' => optional($online_exam_record)->start,
'end' => optional($online_exam_record)->end,
'mark' => optional($online_exam_record)->obtained_mark,
);
}
array_multisort(array_map(function ($element) {
return $element['mark'];
}, $students), SORT_DESC, $students);
return $students;
}
}