<?php

namespace App\Controllers\Mobile\Ujian;

use App\Controllers\Mobile\BC;
use App\Models\Mobile\Ujian\Jadwal;
use App\Models\Mobile\Ujian\Ujian as UjianUjian;
use App\Models\Panel\Ujian\Hasil;
use CodeIgniter\API\ResponseTrait;
use Predis\Client;

class Ujian extends BC
{
    use ResponseTrait;
    private $ujianModel, $redis;
    public function __construct()
    {
        $this->ujianModel = new UjianUjian();
    }
    public function index($id)
    {
        $jadwalModel = new Jadwal();
        $ujian = $jadwalModel->findId(base64_decode($id), ['withToken' => true]);
        $update = [];
        if (!$ujian)  return view('Utils/404', ['code' => 404, 'text' => 'Ujian Tidak Ditemukan']);
        if ($ujian['status'] != '1') return redirect()->to('ujian/jadwal');
        if ($ujian['status_jadwal'] != "1") return redirect()->to('ujian/jadwal');
        if ($ujian['siswa_id'] != user()->id) return redirect()->to('ujian/jadwal');

        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt']) {
            return redirect()->to('ujian/jadwal');
        }
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] == null) $update['jwt'] = get_cookie(MOBILECN());
        if (count($update) > 0) $this->ujianModel->update(base64_decode($id), $update);
        return view('Mobile/Ujian/exam', ['page_title' => 'Loading...', 'no_header' => true, 'no_footer' => true, 'no_sidebar' => true]);
    }
    public function soalAnswered($ujian_id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true);
        if (!$ujian) return $this->failNotFound();
        if ($ujian['status'] != "1") return $this->failNotFound();
        if ($ujian['siswa_id'] != user()->id) return $this->failNotFound();
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt']) {
            return $this->failForbidden("Ujian Dikunci Pada Perangkat Lain");
        }
        $data['soal_answered'] = [];

        if (redison()) {
            try {
                $redis  = json_decode(options('redis-config'), true);
                $this->redis = new Client([
                    'scheme' => 'tcp',
                    'host'   => $redis['host'],
                    'port'   => $redis['port'],
                    'password' => $redis['password'],
                    'database' => $redis['database'],
                ]);
                $this->redis->connect();
            } catch (\Throwable $th) {
                return $this->failServerError(ENVIRONMENT != 'production' ? $th->getMessage() : "Gagal koneksi ke redis");
            }
        }
        $db = db_connect();
        if ($ujian['visible_pg'] > 0) {
            if (redison()) {
                $keyJPG = $this->redis->keys("jawaban_pg_ujian_siswa-$ujian_id-*");
                $sid = [];
                foreach ($keyJPG as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPG) <= 0 ? [] : $this->redis->mget($keyJPG);
                foreach ($rJawaban as $k => $rj) {
                    $data['soal_answered'][$sid[$k]] = is_null($rj) || $rj == "" ? 0 : 1;
                }
            } else {
                $_jawaban = $db->table('jawaban_pg_ujian_siswa jpus')->select('(CASE WHEN opsi_id IS NULL THEN 0 ELSE 1 END) answered,jpus.soal_id');
                $_jawaban = $_jawaban->where('jpus.ujian_id', $ujian_id)->get()->getResultArray();
                foreach ($_jawaban as $key => $value) {
                    $data['soal_answered'][$value['soal_id']] = $value['answered'];
                }
            }
        }
        if ($ujian['visible_pgmulti'] > 0) {
            if (redison()) {
                $keyJPGM = $this->redis->keys("jawaban_pgmulti_ujian_siswa-$ujian_id-*");
                $sid = [];
                foreach ($keyJPGM as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPGM) <= 0 ? [] :  $this->redis->mget($keyJPGM);
                foreach ($rJawaban as $k => $rj) {
                    $data['soal_answered'][$sid[$k]] = is_null($rj) || $rj == "" ? 0 : 1;
                }
            } else {
                $_jawaban = $db->table('jawaban_pgmulti_ujian_siswa jpus')->select('GROUP_CONCAT((CASE WHEN opsi_id IS NULL THEN 0 ELSE 1 END)) answered,jpus.soal_id');
                $_jawaban = $_jawaban->where('jpus.ujian_id', $ujian_id)->groupBy("CONCAT(jpus.ujian_id,'-',jpus.soal_id)")->get()->getResultArray();
                foreach ($_jawaban as $k => $v) {
                    $j = explode(',', $v['answered']);
                    $data['soal_answered'][$v['soal_id']] = array_search(1, $j) !== FALSE ? 1 : 0;
                }
            }
        }
        if ($ujian['visible_pgtf'] > 0) {
            if (redison()) {
                $keyJPGTF = $this->redis->keys("jawaban_pgtf_ujian_siswa-$ujian_id-*");
                $sid = [];
                foreach ($keyJPGTF as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPGTF) <= 0 ? [] : $this->redis->mget($keyJPGTF);
                foreach ($rJawaban as $k => $rj) {
                    $data['soal_answered'][$sid[$k]] = is_null($rj) || $rj == "" ? 0 : 1;
                }
            } else {
                $_jawaban = $db->table('jawaban_pgtf_ujian_siswa jpus')->select('GROUP_CONCAT((CASE WHEN opsi_id IS NULL THEN 0 ELSE 1 END)) answered,jpus.soal_id');
                $_jawaban = $_jawaban->where('jpus.ujian_id', $ujian_id)->groupBy("CONCAT(jpus.ujian_id,'-',jpus.soal_id)")->get()->getResultArray();
                foreach ($_jawaban as $k => $v) {
                    $j = explode(',', $v['answered']);
                    $data['soal_answered'][$v['soal_id']] = array_search(1, $j) !== FALSE ? 1 : 0;
                }
            }
        }
        if ($ujian['visible_pgcouple'] > 0) {
            if (redison()) {
                $keyJPGC = $this->redis->keys("jawaban_pgcouple_ujian_siswa-$ujian_id-*");
                $sid = [];
                foreach ($keyJPGC as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPGC) <= 0 ? [] : $this->redis->mget($keyJPGC);
                foreach ($rJawaban as $k => $rj) {
                    $data['soal_answered'][$sid[$k]] = is_null($rj) || $rj == "" ? 0 : 1;
                }
            } else {
                $_jawaban = $db->table('jawaban_pgcouple_ujian_siswa jpus')->select('GROUP_CONCAT((CASE WHEN opsi_id IS NULL OR couple_id IS NULL THEN 0 ELSE 1 END)) answered,jpus.soal_id');
                $_jawaban = $_jawaban->where('jpus.ujian_id', $ujian_id)->groupBy("CONCAT(jpus.ujian_id,'-',jpus.soal_id)")->get()->getResultArray();
                foreach ($_jawaban as $k => $v) {
                    $j = explode(',', $v['answered']);
                    $data['soal_answered'][$v['soal_id']] = array_search(1, $j) !== FALSE ? 1 : 0;
                }
            }
        }
        if ($ujian['visible_shortentry'] > 0) {
            if (redison()) {
                $keyJSE = $this->redis->keys("jawaban_shortentry_ujian_siswa-$ujian_id-*");
                $sid = [];
                foreach ($keyJSE as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJSE) <= 0 ? [] : $this->redis->mget($keyJSE);
                foreach ($rJawaban as $k => $rj) {
                    $data['soal_answered'][$sid[$k]] = is_null($rj) || $rj == "" ? 0 : 1;
                }
            } else {
                $_jawaban = $db->table('jawaban_shortentry_ujian_siswa jsus')->select("(CASE WHEN respond IS NULL OR respond = '' THEN 0 ELSE 1 END) answered,jsus.soal_id");
                $_jawaban = $_jawaban->where('jsus.ujian_id', $ujian_id)->get()->getResultArray();
                foreach ($_jawaban as $key => $value) {
                    $data['soal_answered'][$value['soal_id']] = $value['answered'];
                }
            }
        }
        if ($ujian['visible_esai'] > 0) {
            if (redison()) {
                $keyJE = $this->redis->keys("jawaban_esai_ujian_siswa-$ujian_id-*");
                $sid = [];
                foreach ($keyJE as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJE) <= 0 ? [] : $this->redis->mget($keyJE);
                foreach ($rJawaban as $k => $rj) {
                    $data['soal_answered'][$sid[$k]] = is_null($rj) || $rj == "" ? 0 : 1;
                }
            } else {
                $_jawaban = $db->table('jawaban_esai_ujian_siswa jeus')->select("(CASE WHEN esai IS NULL OR esai = '' THEN 0 ELSE 1 END) answered,jeus.soal_id");
                $_jawaban = $_jawaban->where('jeus.ujian_id', $ujian_id)->get()->getResultArray();
                foreach ($_jawaban as $key => $value) {
                    $data['soal_answered'][$value['soal_id']] = $value['answered'];
                }
            }
        }
        return $this->respond($data);
    }
    public function config($ujian_id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true);
        if (!$ujian) return $this->failNotFound();
        if ($ujian['status'] != "1") return $this->failNotFound();
        if ($ujian['siswa_id'] != user()->id) return $this->failNotFound();
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt']) {
            return $this->failForbidden("Ujian Dikunci Pada Perangkat Lain");
        }
        $data['timezone'] = date_default_timezone_get();
        $data['nama_mapel'] = $ujian['nama_mapel'];
        $data['ujian_id'] = $ujian['ujian_id'];
        $data['strict'] = $ujian['strict'] == 1;
        $data['afktimeout'] = $ujian['afktimeout'];
        $data['start_at'] = $ujian['start_at'];
        $data['end_at'] = $ujian['end_at'];
        $data['status'] = $ujian['status'];
        $data['acak_soal'] = $ujian['acak_soal'];
        $data['acak_opsi'] = $ujian['acak_opsi'];
        $data['startDateTime'] = $ujian['startDateTime'];
        $data['endDateTime'] = $ujian['endDateTime'];
        $data['minFinishTime'] = $ujian['minFinishTime'];
        $data['timeout'] = $ujian['timeout'];
        $data['maxCheatCount'] = $ujian['maxCheatCount'];
        $data['soal_generated'] = $ujian['soal_generated'];
        // $data['cache_soal'] = $ujian['cache_soal'] == 1;
        $data['cache_soal'] = true;
        $data['environment'] = ENVIRONMENT;
        $data['total_soal'] = $ujian['visible_pg'] + $ujian['visible_pgmulti'] + $ujian['visible_pgtf'] + $ujian['visible_pgcouple'] + $ujian['visible_shortentry'] + $ujian['visible_esai'];
        return $this->respond($data);
    }
    public function soals($ujian_id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true, false, true);
        if (!$ujian) return $this->failNotFound();
        if ($ujian['status'] != "1") return $this->failNotFound();
        if ($ujian['siswa_id'] != user()->id) return $this->failNotFound();
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt']) {
            return $this->failForbidden("Ujian Dikunci Pada Perangkat Lain");
        }
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] == null) $this->ujianModel->update($ujian_id, ['jwt' => get_cookie(MOBILECN())]);
        $soals = [];
        if (redison()) {
            try {
                $redis  = json_decode(options('redis-config'), true);
                $this->redis = new Client([
                    'scheme' => 'tcp',
                    'host'   => $redis['host'],
                    'port'   => $redis['port'],
                    'password' => $redis['password'],
                    'database' => $redis['database'],
                ]);
                $this->redis->connect();
            } catch (\Throwable $th) {
                return $this->failServerError(ENVIRONMENT != 'production' ? $th->getMessage() : "Gagal koneksi ke redis");
            }
        }
        if ((int)$ujian['visible_pg'] > 0) {
            $sid = [];
            if (redison()) {
                $keyJPG = $this->redis->keys("jawaban_pg_ujian_siswa-$ujian_id-*");
                if ($ujian['acak_soal'] == '0') {
                    usort($keyJPG, function ($a, $b) {
                        $fid = explode('-', $a);
                        $lid = explode('-', $b);
                        return end($fid) <=> end($lid);
                    });
                }
                $rsid = [];
                foreach ($keyJPG as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPG) <= 0 ? [] : $this->redis->mget($keyJPG);
                $redSoals = count($rsid) <= 0 ? [] : $this->redis->mget($rsid);
                $soal = [];
                foreach ($redSoals as $rs) {
                    $rs = json_decode($rs, true);
                    $opsid = null;
                    foreach ($keyJPG as $kkjpg => $vkjpg) {
                        if ($vkjpg == "jawaban_pg_ujian_siswa-$ujian_id-$rs[soal_id]") {
                            $opsid = $rJawaban[$kkjpg] ?? null;
                            break;
                        }
                    }
                    $soal[] = [
                        'ujian_id' => $ujian_id,
                        'soal_id' => $rs['soal_id'],
                        'question' => $rs['question'],
                        'jenis_soal' => $rs['jenis_soal'],
                        'opsi_id' => $opsid
                    ];
                }
            } else {
                $soal = $this->ujianModel->getAllSoalUjianPG($ujian_id);
                $sid = [];
                foreach ($soal as $key => $value) {
                    $sid[] = $value['soal_id'];
                }
            }
            $opsi = $this->ujianModel->getOpsiSoal($sid);
            foreach ($soal as $s) {
                $s['opsi'] = [];
                foreach ($opsi as $o) {
                    if ($s['soal_id'] == $o['soal_id']) {
                        $s['opsi'][] = $o;
                    }
                }
                $soals[] = $s;
            }
        }
        if ((int)$ujian['visible_pgmulti'] > 0) {

            $sid = [];
            if (redison()) {
                $keyJPGM = $this->redis->keys("jawaban_pgmulti_ujian_siswa-$ujian_id-*");
                if ($ujian['acak_soal'] == '0') {
                    usort($keyJPGM, function ($a, $b) {
                        $fid = explode('-', $a);
                        $lid = explode('-', $b);
                        return end($fid) <=> end($lid);
                    });
                }
                $rsid = [];
                foreach ($keyJPGM as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPGM) <= 0 ? [] : $this->redis->mget($keyJPGM);
                $redSoals = count($rsid) <= 0 ? [] : $this->redis->mget($rsid);
                $soal = [];
                foreach ($redSoals as $rs) {
                    $rs = json_decode($rs, true);
                    $opsid = null;
                    foreach ($keyJPGM as $kkjpg => $vkjpg) {
                        if ($vkjpg == "jawaban_pgmulti_ujian_siswa-$ujian_id-$rs[soal_id]") {
                            $opsid = $rJawaban[$kkjpg] ?? '';
                            break;
                        }
                    }
                    $soal[] = [
                        'ujian_id' => $ujian_id,
                        'soal_id' => $rs['soal_id'],
                        'question' => $rs['question'],
                        'jenis_soal' => $rs['jenis_soal'],
                        'opsi_id' => $opsid
                    ];
                }
            } else {
                $soal = $this->ujianModel->getAllSoalUjianPGMulti($ujian_id);
                $sid = [];
                foreach ($soal as $key => $value) {
                    $sid[] = $value['soal_id'];
                }
            }
            $opsi = $this->ujianModel->getOpsiSoal($sid);
            foreach ($soal as $s) {
                $s['opsi'] = [];
                foreach ($opsi as $o) {
                    if ($s['soal_id'] == $o['soal_id']) {
                        $s['opsi'][] = $o;
                    }
                }
                $soals[] = $s;
            }
        }
        if ((int)$ujian['visible_pgtf'] > 0) {

            $sid = [];
            if (redison()) {

                $keyJPGTF = $this->redis->keys("jawaban_pgtf_ujian_siswa-$ujian_id-*");
                if ($ujian['acak_soal'] == '0') {
                    usort($keyJPGTF, function ($a, $b) {
                        $fid = explode('-', $a);
                        $lid = explode('-', $b);
                        return end($fid) <=> end($lid);
                    });
                }
                $rsid = [];
                foreach ($keyJPGTF as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPGTF) <= 0 ? [] :  $this->redis->mget($keyJPGTF);
                $redSoals = count($rsid) <= 0 ? [] : $this->redis->mget($rsid);
                $soal = [];
                foreach ($redSoals as $rs) {
                    $rs = json_decode($rs, true);
                    $opsid = null;
                    foreach ($keyJPGTF as $kkjpg => $vkjpg) {
                        if ($vkjpg == "jawaban_pgtf_ujian_siswa-$ujian_id-$rs[soal_id]") {
                            $opsid = $rJawaban[$kkjpg] ?? '';
                            break;
                        }
                    }
                    $soal[] = [
                        'ujian_id' => $ujian_id,
                        'soal_id' => $rs['soal_id'],
                        'question' => $rs['question'],
                        'jenis_soal' => $rs['jenis_soal'],
                        'opsi_id' => $opsid
                    ];
                }
            } else {
                $soal = $this->ujianModel->getAllSoalUjianPGTF($ujian_id);
                $sid = [];
                foreach ($soal as $key => $value) {
                    $sid[] = $value['soal_id'];
                }
            }
            $opsi = $this->ujianModel->getOpsiSoal($sid);
            foreach ($soal as $s) {
                $s['opsi'] = [];
                foreach ($opsi as $o) {
                    if ($s['soal_id'] == $o['soal_id']) {
                        $s['opsi'][] = $o;
                    }
                }
                $soals[] = $s;
            }
        }
        if ((int)$ujian['visible_pgcouple'] > 0) {

            $sid = [];
            if (redison()) {
                $keyJPGC = $this->redis->keys("jawaban_pgcouple_ujian_siswa-$ujian_id-*");
                if ($ujian['acak_soal'] == '0') {
                    usort($keyJPGC, function ($a, $b) {
                        $fid = explode('-', $a);
                        $lid = explode('-', $b);
                        return end($fid) <=> end($lid);
                    });
                }
                $rsid = [];
                foreach ($keyJPGC as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJPGC) <= 0 ? [] : $this->redis->mget($keyJPGC);
                $redSoals = count($rsid) <= 0 ? [] : $this->redis->mget($rsid);
                $soal = [];
                foreach ($redSoals as $rs) {
                    $rs = json_decode($rs, true);
                    $opsid = null;
                    foreach ($keyJPGC as $kkjpg => $vkjpg) {
                        if ($vkjpg == "jawaban_pgcouple_ujian_siswa-$ujian_id-$rs[soal_id]") {
                            $opsid = $rJawaban[$kkjpg] ?? '';
                            break;
                        }
                    }
                    $soal[] = [
                        'ujian_id' => $ujian_id,
                        'soal_id' => $rs['soal_id'],
                        'question' => $rs['question'],
                        'jenis_soal' => $rs['jenis_soal'],
                        'opsi_id' => $opsid
                    ];
                }
            } else {
                $soal = $this->ujianModel->getAllSoalUjianPGCouple($ujian_id);
                $sid = [];
                foreach ($soal as $key => $value) {
                    $sid[] = $value['soal_id'];
                }
            }
            $opsi = $this->ujianModel->getOpsiSoal($sid);
            $coupleQuestion = $this->ujianModel->getCoupleQuestionSoal($sid);
            foreach ($soal as $s) {
                $s['opsi'] = [];
                $s['questions'] = [];
                foreach ($opsi as $o) {
                    if ($s['soal_id'] == $o['soal_id']) {
                        $s['opsi'][] = $o;
                    }
                }
                foreach ($coupleQuestion as $question) {
                    if ($question['soal_id'] == $s['soal_id']) {
                        $s['questions'][] = $question;
                    }
                }
                $soals[] = $s;
            }
        }
        if ((int)$ujian['visible_shortentry'] > 0) {
            $sid = [];
            if (redison()) {
                $keyJS = $this->redis->keys("jawaban_shortentry_ujian_siswa-$ujian_id-*");
                if ($ujian['acak_soal'] == '0') {
                    usort($keyJS, function ($a, $b) {
                        $fid = explode('-', $a);
                        $lid = explode('-', $b);
                        return end($fid) <=> end($lid);
                    });
                }
                $rsid = [];
                foreach ($keyJS as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJS) <= 0 ? [] : $this->redis->mget($keyJS);
                $redSoals = count($rsid) <= 0 ? [] : $this->redis->mget($rsid);
                $soal = [];
                foreach ($redSoals as $rs) {
                    $rs = json_decode($rs, true);
                    $respond = '';
                    foreach ($keyJS as $kkjpg => $vkjpg) {
                        if ($vkjpg == "jawaban_shortentry_ujian_siswa-$ujian_id-$rs[soal_id]") {
                            $respond = $rJawaban[$kkjpg] ?? '';
                            break;
                        }
                    }
                    $soals[] = [
                        'ujian_id' => $ujian_id,
                        'soal_id' => $rs['soal_id'],
                        'question' => $rs['question'],
                        'jenis_soal' => $rs['jenis_soal'],
                        'respond' => $respond
                    ];
                }
            } else {
                $soal = $this->ujianModel->getAllSoalUjianShortEntry($ujian_id);
                $sid = [];
                foreach ($soal as $key => $value) {
                    $soals[] = $value;
                }
            }
        }
        if ((int)$ujian['visible_esai'] > 0) {
            $sid = [];
            if (redison()) {

                $keyJE = $this->redis->keys("jawaban_esai_ujian_siswa-$ujian_id-*");
                if ($ujian['acak_soal'] == '0') {
                    usort($keyJE, function ($a, $b) {
                        $fid = explode('-', $a);
                        $lid = explode('-', $b);
                        return end($fid) <=> end($lid);
                    });
                }
                $rsid = [];
                foreach ($keyJE as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $rJawaban = count($keyJE) <= 0 ? [] : $this->redis->mget($keyJE);
                $redSoals = count($rsid) <= 0 ? [] : $this->redis->mget($rsid);
                $soal = [];
                foreach ($redSoals as $rs) {
                    $rs = json_decode($rs, true);
                    $esai = '';
                    foreach ($keyJE as $kkjpg => $vkjpg) {
                        if ($vkjpg == "jawaban_esai_ujian_siswa-$ujian_id-$rs[soal_id]") {
                            $esai = $rJawaban[$kkjpg] ?? '';
                            break;
                        }
                    }
                    $soals[] = [
                        'ujian_id' => $ujian_id,
                        'soal_id' => $rs['soal_id'],
                        'question' => $rs['question'],
                        'jenis_soal' => $rs['jenis_soal'],
                        'esai' => $esai
                    ];
                }
            } else {

                $soal = $this->ujianModel->getAllSoalUjianEsai($ujian_id);
                $sid = [];
                foreach ($soal as $key => $value) {
                    $soals[] = $value;
                }
            }
        }
        if (!$soals) return $this->failNotFound();
        if ($ujian['acak_soal'] == '0') {

            $orders = explode(',', $ujian['order_soal']);
            $d = [];
            foreach ($soals as $k => $v) {
                foreach ($orders as $id) {
                    if ($id == $v['soal_id']) {
                        $d[] = $v;
                        unset($soals[$k]);
                    }
                }
            }
            $soals = [...$d, ...$soals];
        }
        return $this->respond($soals);
    }
    public function imageUploader($ujian_id)
    {
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true);
        if (!$ujian) return $this->failNotFound();
        if ($ujian['status'] != "1") return $this->fail(['message' => 'Ujian Sudah Selesai']);
        if (!$ujian_id) return $this->fail(['message' => 'Ujian Tidak Ditemukan']);
        if ($ujian['siswa_id'] != user()->id) return $this->fail(['message' => 'Ujian Tidak Ditemukan']);
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt']) {
            return $this->failForbidden("Ujian Dikunci Pada Perangkat Lain");
        }
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] == null) $this->ujianModel->update($ujian_id, ['jwt' => get_cookie(MOBILECN())]);
        //sudah selesai
        if ($ujian['endDateTime'] < time() || $ujian['end_at'] < time()) return $this->fail(['message' => 'Ujian Telah Selesai']);
        $app = config('app');
        $img = $this->request->getFile('file');
        $allowed_mime = ['image/png', 'image/jpg', 'image/jpeg'];
        if (!$img->isValid()) return $this->failForbidden();
        if (!in_array($img->getClientMimeType(), $allowed_mime)) $this->failForbidden();
        if ($img->hasMoved()) return $this->failNotFound();
        $imgName = $img->getRandomName();
        $taskPath = "$app->imgPath/jawaban";
        compress_and_resize_image($img->getTempName(), "$taskPath/$imgName");
        rmbfe('php', $taskPath);
        return $this->respond(['location' => base_url("$taskPath/$imgName")]);
    }
    public function save_soal($ujian_id, $soalnum)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        if ($soalnum <= 0) return $this->failNotFound();
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true);
        if (!$ujian) return $this->failNotFound();
        if ($ujian['status'] != "1") return $this->fail(['message' => 'Ujian Sudah Selesai']);
        $total_soal_tampil = (int)$ujian['visible_pg'] + (int)$ujian['visible_pgmulti'] + (int)$ujian['visible_pgtf'] + (int)$ujian['visible_esai'] + (int)$ujian['visible_pgcouple'] + (int)$ujian['visible_shortentry'];
        if (!$ujian_id) return $this->fail(['message' => 'Ujian Tidak Ditemukan']);
        if ($ujian['siswa_id'] != user()->id) return $this->fail(['message' => 'Ujian Tidak Ditemukan']);
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt']) {
            return $this->failForbidden("Ujian Dikunci Pada Perangkat Lain");
        }
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] == null) $this->ujianModel->update($ujian_id, ['jwt' => get_cookie(MOBILECN())]);
        //sudah selesai
        if ($ujian['endDateTime'] < time() || $ujian['end_at'] < time()) return $this->fail(['message' => 'Ujian Telah Selesai']);
        if ($total_soal_tampil < $soalnum) return $this->fail(['message' => 'Soal Tidak Valid']);
        $data = (array)$this->request->getVar();
        $db = db_connect();

        if (redison()) {
            try {
                $redis  = json_decode(options('redis-config'), true);
                $this->redis = new Client([
                    'scheme' => 'tcp',
                    'host'   => $redis['host'],
                    'port'   => $redis['port'],
                    'password' => $redis['password'],
                    'database' => $redis['database'],
                ]);

                $this->redis->connect();
            } catch (\Throwable $th) {
                return $this->failServerError(ENVIRONMENT != 'production' ? $th->getMessage() : "Gagal koneksi ke redis");
            }
        }
        switch ($data['jenis_soal']) {
            case '1':
                if (!$data['opsi_id']) return $this->fail(['message' => 'Tolong Pilih Jawaban!']);
                if (redison()) $this->redis->set("jawaban_pg_ujian_siswa-$ujian_id-$data[soal_id]", $data['opsi_id']);
                else $db->table('jawaban_pg_temp_ujian_siswa')->where(['ujian_id' => $ujian_id, 'soal_id' => $data['soal_id']])->set(['opsi_id' => $data['opsi_id'], 'updated_at' => time()])->update();
                break;
            case '2':
                if (!$data['esai']) return $this->fail(['message' => 'Tolong Isi Jawaban!']);
                $data['esai'] = str_replace(['<script', '<iframe'], '', $data['esai']);
                $data['esai'] = base64ToImage($data['esai'], FCPATH . config('app')->imgPath . "/jawaban")['str'];
                if (redison()) $this->redis->set("jawaban_esai_ujian_siswa-$ujian_id-$data[soal_id]", $data['esai']);
                else $db->table('jawaban_esai_temp_ujian_siswa')->where(['ujian_id' => $ujian_id, 'soal_id' => $data['soal_id']])->set(['esai' => $data['esai'], 'updated_at' => time()])->update();
                break;
            case '5':
                if ($data['respond'] === null) return $this->fail(['message' => 'Tolong Isi Jawaban!']);
                if ($data['respond'] === false) return $this->fail(['message' => 'Tolong Isi Jawaban!']);
                $data['respond'] = trim($data['respond'], '.');
                $data['respond'] = str_replace('&amp;', '&', $data['respond']);
                $data['respond'] = str_replace('&amp', '&', $data['respond']);
                $data['respond'] = str_replace('&nbsp;', ' ', $data['respond']);
                $data['respond'] = str_replace('&nbsp', ' ', $data['respond']);
                $data['respond'] = trim($data['respond'], ' ');
                if (redison()) $this->redis->set("jawaban_shortentry_ujian_siswa-$ujian_id-$data[soal_id]", $data['respond']);
                else $db->table('jawaban_shortentry_temp_ujian_siswa')->where(['ujian_id' => $ujian_id, 'soal_id' => $data['soal_id']])->set(['respond' => $data['respond'], 'updated_at' => time()])->update();
                break;
            case '3':
                if (!$data['opsi_id']) return $this->fail(['message' => 'Tolong Pilih Jawaban!']);
                if (redison()) $this->redis->set("jawaban_pgmulti_ujian_siswa-$ujian_id-$data[soal_id]", $data['opsi_id']);
                else {
                    $j = [];
                    foreach (explode(',', $data['opsi_id']) as $key => $value) {
                        $j[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $data['soal_id'],
                            'opsi_id' => $value,
                            'created_at' => time(),
                        ];
                    }
                    $db->transStart();
                    $db->table('jawaban_pgmulti_temp_ujian_siswa')->delete(['ujian_id' => $ujian_id, 'soal_id' => $data['soal_id']]);
                    $db->query("SET unique_checks=0;");
                    if ($j) $db->table('jawaban_pgmulti_temp_ujian_siswa')->insertBatch($j);
                    $db->query("SET unique_checks=1;");
                    $db->transComplete();
                    if ($db->transStatus() === FALSE) return $this->fail(['message' => 'Tidak Dapat Menyimpan Soal']);
                }
                break;
            case '6':
                if (!$data['opsi_id']) return $this->fail(['message' => 'Tolong Pilih Jawaban!']);
                if (redison()) $this->redis->set("jawaban_pgtf_ujian_siswa-$ujian_id-$data[soal_id]", $data['opsi_id']);
                else {
                    $j = [];
                    foreach (explode(',', $data['opsi_id']) as $key => $value) {
                        $j[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $data['soal_id'],
                            'opsi_id' => explode('-', $value)[0] ?? null,
                            'tf' => explode('-', $value)[1] ?? null,
                            'created_at' => time(),

                        ];
                    }
                    $db->transStart();
                    $db->table('jawaban_pgtf_temp_ujian_siswa')->delete(['ujian_id' => $ujian_id, 'soal_id' => $data['soal_id']]);
                    $db->query("SET unique_checks=0;");
                    if ($j) $db->table('jawaban_pgtf_temp_ujian_siswa')->insertBatch($j);
                    $db->query("SET unique_checks=1;");
                    $db->transComplete();
                    if ($db->transStatus() === FALSE) return $this->fail(['message' => 'Tidak Dapat Menyimpan Soal']);
                }
                break;
            case '4':
                if (!$data['opsi_id']) return $this->fail(['message' => 'Tolong Pilih Jawaban!']);
                if (redison()) $this->redis->set("jawaban_pgcouple_ujian_siswa-$ujian_id-$data[soal_id]", $data['opsi_id']);
                else {
                    $j = [];
                    foreach (explode(',', $data['opsi_id']) as $key => $value) {
                        $couple = explode('-', $value);
                        $j[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $data['soal_id'],
                            'couple_id' => $couple[0],
                            'opsi_id' => $couple[1],
                            'created_at' => time(),

                        ];
                    }
                    $db->transStart();
                    $db->table('jawaban_pgcouple_temp_ujian_siswa')->delete(['ujian_id' => $ujian_id, 'soal_id' => $data['soal_id']]);
                    $db->query("SET unique_checks=0;");
                    if ($j) $db->table('jawaban_pgcouple_temp_ujian_siswa')->insertBatch($j);
                    $db->query("SET unique_checks=1;");
                    $db->transComplete();
                    if ($db->transStatus() === FALSE) return $this->fail(['message' => 'Tidak Dapat Menyimpan Soal']);
                }
                break;
        }
        $response['message'] = 'Berhasil Menyimpan Soal';
        $response['csrf'] = csrf_hash();
        return $this->respond($response);
    }
    public function finish($ujian_id)
    {
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true);
        if (!$ujian)  return view('Utils/404', ['code' => 404, 'text' => 'Ujian Tidak Ditemukan']);
        if ($ujian['siswa_id'] != user()->id) return view('Utils/404', ['code' => 404, 'text' => 'Ujian Tidak Ditemukan']);
        if ($ujian['status'] != "1") {
            if ($this->request->isAJAX()) {
                return $this->failNotFound();
            } else {
                return redirect()->to('ujian/jadwal');
            }
        }
        $hc = $this->request->getGet('hc');
        $examEnd = $ujian['endDateTime'] < time() || $ujian['end_at'] < time();
        if ($ujian['minFinishTime'] > 0 && ($ujian['minFinishTime'] + $ujian['start_at']) >= time()) return redirect()->back();
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt'] && !$examEnd) {
            return view('Utils/404', ['code' => 403, 'text' => 'Ujian Dikunci Pada Perangkat Lain']);
        }
        $db = db_connect();
        if (redison()) {
            try {
                $redis  = json_decode(options('redis-config'), true);
                $this->redis = new Client([
                    'scheme' => 'tcp',
                    'host'   => $redis['host'],
                    'port'   => $redis['port'],
                    'password' => $redis['password'],
                    'database' => $redis['database'],
                ]);
                $this->redis->connect();
                // $this->trxRedis = $this->redis->transaction();
            } catch (\Throwable $th) {
                return $this->failServerError(ENVIRONMENT != 'production' ? $th->getMessage() : "Gagal koneksi ke redis");
            }
        }
        $db->transStart();
        $keyJPG = [];
        $keyJPGM = [];
        $keyJPGC = [];
        $keyJPGTF = [];
        $keyJSE = [];
        $keyJE = [];
        if ($ujian['visible_pg'] != 0) {
            if (redison()) {
                $keyJPG = $this->redis->keys("jawaban_pg_ujian_siswa-$ujian_id-*");
                $sid = [];
                $rsid = [];
                foreach ($keyJPG as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $jawaban_pg = [];
                if ($keyJPG) {
                    foreach ($this->redis->mget($keyJPG) as $k => $rs) {
                        if ($rs == "" && !$hc && !$examEnd) return redirect()->to("ujian/$ujian[ujian_id]");
                        $jawaban_pg[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $sid[$k],
                            'opsi_id' => !empty($rs) ? $rs : null,
                            'created_at' => time(),
                            'updated_at' => time(),
                        ];
                    }
                }
                if ($jawaban_pg) {
                    $db->table('jawaban_pg_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                    $db->query("SET unique_checks=0;");
                    $db->table('jawaban_pg_ujian_siswa')->insertBatch($jawaban_pg);
                    $db->query("SET unique_checks=1;");
                }
            } else {
                $pg = $db->table('jawaban_pg_temp_ujian_siswa')->getWhere(['ujian_id' => $ujian_id])->getResultArray();
                if ($ujian['visible_pg'] > count($pg) && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                foreach ($pg as $key => $value) {
                    if (!$value['opsi_id'] && !$examEnd && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                }
                $db->query("SET unique_checks=0;");
                $db->table('jawaban_pg_ujian_siswa')->insertBatch($pg);
                $db->query("SET unique_checks=1;");
                $db->table('jawaban_pg_temp_ujian_siswa')->where(['ujian_id' => $ujian_id])->delete();
            }
        }
        if ($ujian['visible_pgmulti'] != 0) {
            if (redison()) {
                $keyJPGM = $this->redis->keys("jawaban_pgmulti_ujian_siswa-$ujian_id-*");
                $sid = [];
                $rsid = [];
                foreach ($keyJPGM as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $jawaban_pgmulti = [];
                if ($keyJPGM) {
                    foreach ($this->redis->mget($keyJPGM) as $k => $rs) {
                        if ($rs == "" && !$hc && !$examEnd) return redirect()->to("ujian/$ujian[ujian_id]");
                        foreach (explode(',', $rs) as $srs) {
                            $jawaban_pgmulti[] = [
                                'ujian_id' => $ujian_id,
                                'soal_id' => $sid[$k],
                                'opsi_id' => !empty($srs) ? $srs : null,
                                'created_at' => time(),
                            ];
                        }
                    }
                }
                if ($jawaban_pgmulti) {
                    $db->table('jawaban_pgmulti_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                    $db->query("SET unique_checks=0;");
                    $db->table('jawaban_pgmulti_ujian_siswa')->insertBatch($jawaban_pgmulti);
                    $db->query("SET unique_checks=1;");
                }
            } else {
                $pgmulti = $db->table('jawaban_pgmulti_temp_ujian_siswa')->groupBy('opsi_id,soal_id,ujian_id')->getWhere(['ujian_id' => $ujian_id])->getResultArray();
                if ($ujian['visible_pgmulti'] > count($pgmulti) && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                $db->table('jawaban_pgmulti_ujian_siswa')->insertBatch($pgmulti);
                $db->table('jawaban_pgmulti_temp_ujian_siswa')->where(['ujian_id' => $ujian_id])->delete();
            }
        }
        if ($ujian['visible_pgtf'] != 0) {

            if (redison()) {
                $keyJPGTF = $this->redis->keys("jawaban_pgtf_ujian_siswa-$ujian_id-*");
                $sid = [];
                $rsid = [];
                foreach ($keyJPGTF as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $jawaban_pgtf = [];
                if ($keyJPGTF) {
                    foreach ($this->redis->mget($keyJPGTF) as $k => $rs) {
                        if ($rs == "" && !$hc && !$examEnd) return redirect()->to("ujian/$ujian[ujian_id]");
                        foreach (explode(',', $rs) as $srs) {
                            $jawaban_pgtf[] = [
                                'ujian_id' => $ujian_id,
                                'soal_id' => $sid[$k],
                                'opsi_id' => !empty(explode('-', $srs)[0]) ? explode('-', $srs)[0] : null,
                                'tf' => explode('-', $srs)[1] ?? 0,
                                'created_at' => time(),
                            ];
                        }
                    }
                }
                if ($jawaban_pgtf) {
                    $db->table('jawaban_pgtf_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                    $db->query("SET unique_checks=0;");
                    $db->table('jawaban_pgtf_ujian_siswa')->insertBatch($jawaban_pgtf);
                    $db->query("SET unique_checks=1;");
                }
            } else {
                $pgtf = $db->table('jawaban_pgtf_temp_ujian_siswa')->groupBy('opsi_id,soal_id,ujian_id')->getWhere(['ujian_id' => $ujian_id])->getResultArray();
                if ($ujian['visible_pgtf'] > count($pgtf) && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                $db->query("SET unique_checks=0;");
                $db->table('jawaban_pgtf_ujian_siswa')->insertBatch($pgtf);
                $db->query("SET unique_checks=1;");
                $db->table('jawaban_pgtf_temp_ujian_siswa')->where(['ujian_id' => $ujian_id])->delete();
            }
        }
        if ($ujian['visible_pgcouple'] != 0) {
            if (redison()) {
                $keyJPGC = $this->redis->keys("jawaban_pgcouple_ujian_siswa-$ujian_id-*");
                $sid = [];
                $rsid = [];
                foreach ($keyJPGC as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $jawaban_pgcouple = [];
                if ($keyJPGC) {
                    foreach ($this->redis->mget($keyJPGC) as $k => $rs) {
                        if ($rs == "" && !$hc && !$examEnd) return redirect()->to("ujian/$ujian[ujian_id]");
                        foreach (explode(',', $rs) as $srs) {
                            $jawaban_pgcouple[] = [
                                'ujian_id' => $ujian_id,
                                'soal_id' => $sid[$k],
                                'couple_id' => !empty(explode('-', $srs)[0]) ? explode('-', $srs)[0] : null,
                                'opsi_id' => explode('-', $srs)[1],
                                'created_at' => time(),
                            ];
                        }
                    }
                }
                if ($jawaban_pgcouple) {
                    $db->table('jawaban_pgcouple_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                    $db->query("SET unique_checks=0;");
                    $db->table('jawaban_pgcouple_ujian_siswa')->insertBatch($jawaban_pgcouple);
                    $db->query("SET unique_checks=1;");
                }
            } else {
                $pgcouple = $db->table('jawaban_pgcouple_temp_ujian_siswa')->getWhere(['ujian_id' => $ujian_id])->getResultArray();
                if ($ujian['visible_pgcouple'] > count($pgcouple) && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                foreach ($pgcouple as $key => $value) {
                    if ((!$value['couple_id'] || !$value['opsi_id']) && !$examEnd) return redirect()->to("ujian/$ujian[ujian_id]");
                }
                $db->query("SET unique_checks=0;");
                $db->table('jawaban_pgcouple_ujian_siswa')->insertBatch($pgcouple);
                $db->query("SET unique_checks=1;");
                $db->table('jawaban_pgcouple_temp_ujian_siswa')->where(['ujian_id' => $ujian_id])->delete();
            }
        }

        if ($ujian['visible_shortentry'] != 0) {
            if (redison()) {

                $keyJSE = $this->redis->keys("jawaban_shortentry_ujian_siswa-$ujian_id-*");
                $sid = [];
                $rsid = [];
                foreach ($keyJSE as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $jawaban_shortentry = [];
                if ($keyJSE) {
                    foreach ($this->redis->mget($keyJSE) as $k => $rs) {
                        if ($rs == "" && !$hc && !$examEnd) return redirect()->to("ujian/$ujian[ujian_id]");
                        foreach (explode(',', $rs) as $srs) {
                            $jawaban_shortentry[] = [
                                'ujian_id' => $ujian_id,
                                'soal_id' => $sid[$k],
                                'respond' => $srs,
                                'created_at' => time(),
                                'updated_at' => time(),
                            ];
                        }
                    }
                }
                if ($jawaban_shortentry) {
                    $js = [];
                    foreach ($jawaban_shortentry as $kjs => $vjs) {
                        $id = $vjs['ujian_id'] . $vjs['soal_id'];
                        if (!isset($js[$id])) {
                            $js[$id] = $vjs;
                            continue;
                        }
                        $js[$id]['respond'] .= ",$vjs[respond]";
                    }
                    $jawaban_shortentry = [];
                    foreach ($js as $k => $v) {
                        $jawaban_shortentry[] = $v;
                    }
                    $db->table('jawaban_shortentry_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                    $db->query("SET unique_checks=0;");
                    $db->table('jawaban_shortentry_ujian_siswa')->insertBatch($jawaban_shortentry);
                    $db->query("SET unique_checks=1;");
                }
            } else {
                $shortentry = $db->table('jawaban_shortentry_temp_ujian_siswa')->getWhere(['ujian_id' => $ujian_id])->getResultArray();
                if ($ujian['visible_shortentry'] > count($shortentry) && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                foreach ($shortentry as $key => $value) {
                    if (!$value['respond'] && $ujian['end_at'] > time() && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                }
                $db->query("SET unique_checks=0;");
                $db->table('jawaban_shortentry_ujian_siswa')->insertBatch($shortentry);
                $db->query("SET unique_checks=1;");
                $db->table('jawaban_shortentry_temp_ujian_siswa')->where(['ujian_id' => $ujian_id])->delete();
            }
        }
        if ($ujian['visible_esai'] != 0) {
            if (redison()) {
                $keyJE = $this->redis->keys("jawaban_esai_ujian_siswa-$ujian_id-*");
                $sid = [];
                $rsid = [];
                foreach ($keyJE as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $jawaban_esai = [];
                if ($keyJE) {
                    foreach ($this->redis->mget($keyJE) as $k => $rs) {
                        if ($rs == "" && !$hc && !$examEnd) return redirect()->to("ujian/$ujian[ujian_id]");
                        foreach (explode(',', $rs) as $srs) {
                            $jawaban_esai[] = [
                                'ujian_id' => $ujian_id,
                                'soal_id' => $sid[$k],
                                'esai' => $srs,
                                'created_at' => time(),
                                'updated_at' => time(),
                            ];
                        }
                    }
                }
                if ($jawaban_esai) {
                    $je = [];
                    foreach ($jawaban_esai as $kje => $vje) {
                        $id = $vje['ujian_id'] . $vje['soal_id'];
                        if (!isset($je[$id])) {
                            $je[$id] = $vje;
                            continue;
                        }
                        $je[$id]['esai'] .= ",$vje[esai]";
                    }
                    $jawaban_esai = [];
                    foreach ($je as $k => $v) {
                        $jawaban_esai[] = $v;
                    }
                    $db->table('jawaban_esai_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                    $db->query("SET unique_checks=0;");
                    $db->table('jawaban_esai_ujian_siswa')->insertBatch($jawaban_esai);
                    $db->query("SET unique_checks=1;");
                }
            } else {
                $esai = $db->table('jawaban_esai_temp_ujian_siswa')->getWhere(['ujian_id' => $ujian_id])->getResultArray();
                if ($ujian['visible_esai'] > count($esai) && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                foreach ($esai as $key => $value) {
                    if (!$value['esai'] && !$examEnd && !$hc) return redirect()->to("ujian/$ujian[ujian_id]");
                }
                $db->query("SET unique_checks=0;");
                $db->table('jawaban_esai_ujian_siswa')->insertBatch($esai);
                $db->query("SET unique_checks=1;");
                $db->table('jawaban_esai_temp_ujian_siswa')->where(['ujian_id' => $ujian_id])->delete();
            }
        }
        if ($hc) db_connect()->table('ujian_siswa')->set('hasCheating', '1')->where('id', $ujian_id)->update();
        $db->transComplete();

        // if (redison()) $this->trxRedis->execute();
        // if ($keyJPG) $this->redis->del($keyJPG);
        // if ($keyJPGM) $this->redis->del($keyJPGM);
        // if ($keyJPGTF) $this->redis->del($keyJPGTF);
        // if ($keyJPGC) $this->redis->del($keyJPGC);
        // if ($keyJSE) $this->redis->del($keyJSE);
        // if ($keyJE) $this->redis->del($keyJE);
        $state = (new Hasil())->finish($ujian_id, base64_decode($ujian['jadwal_id']));
        if ($this->request->isAJAX()) return $this->respond(['finished' => $state, 'message' => $state ? "Berhasil Selesaikan" : "Gagal Selesaikan"]);
        setLog("Selesai Ujian " . ($ujian['nama_mapel'] ?? ''));
        if ($ujian['show_point'] == 1) return redirect()->to('ujian/' . $ujian['ujian_id'] . '/point');
        return redirect()->to('ujian/jadwal');
    }
    public function point($ujian_id)
    {
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true, true);
        if (!$ujian) return redirect()->to('ujian/jadwal');
        if ($ujian['siswa_id'] != user()->id) return redirect()->to('ujian/jadwal');
        switch ($ujian['status']) {
            case 0:
                return redirect()->to('ujian/jadwal/confirm/' . $ujian['ujian_id']);
            case 1:
                return redirect()->to('ujian/' . $ujian['ujian_id']);
        }
        if ($ujian['show_point'] == 0) return redirect()->to('ujian/jadwal');
        return view('Mobile/Ujian/point', ['point' => $ujian['nilai_pg'] + $ujian['nilai_esai'], 'page_title' => 'Nilai Ujian']);
    }

    public function hc($ujian_id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $ujian_id = base64_decode($ujian_id);
        $ujian = $this->ujianModel->findId($ujian_id, true);
        if (!$ujian) return $this->failNotFound();
        if ($ujian['status'] != "1") return $this->failNotFound();
        if ($ujian['siswa_id'] != user()->id) return $this->failNotFound();
        if ($ujian['multi_login'] != 1 && $ujian['jwt'] != null && get_cookie(MOBILECN()) != $ujian['jwt']) {
            return $this->failForbidden("Ujian Dikunci Pada Perangkat Lain");
        }
        db_connect()->table('ujian_siswa')->set('hasCheating', '1')->where('id', $ujian_id)->update();
        setLog("Melakukan Pelanggaran Pada Ujian " . $ujian['nama_mapel']);
        return $this->respond(['message' => "OK"]);
    }
}
