172 lines
5.9 KiB
PHP
172 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Siswa;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Challenge;
|
|
use App\Models\PesertaChallenge;
|
|
use App\Models\Leaderboard;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class ChallengeController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
$siswa = Auth::guard('siswa')->user();
|
|
|
|
$challenges = Challenge::whereHas('kelas', function ($q) use ($siswa) {
|
|
$q->where('challenge_kelas.id_kelas', $siswa->id_kelas);
|
|
})
|
|
->with(['soal'])
|
|
->withCount('soal')
|
|
->orderBy('tenggat_waktu', 'asc')
|
|
->get();
|
|
|
|
$sudahDikerjakan = PesertaChallenge::where('id_siswa', $siswa->id_siswa)
|
|
->where('status', 'selesai')
|
|
->pluck('id_challenge')
|
|
->toArray();
|
|
|
|
return view('siswa.challenge.index', compact('challenges', 'sudahDikerjakan'));
|
|
}
|
|
|
|
public function kerjakan($id_challenge)
|
|
{
|
|
$siswa = Auth::guard('siswa')->user();
|
|
|
|
$challenge = Challenge::whereHas('kelas', function ($q) use ($siswa) {
|
|
$q->where('challenge_kelas.id_kelas', $siswa->id_kelas);
|
|
})
|
|
->with('soal')
|
|
->findOrFail($id_challenge);
|
|
|
|
$sudah = PesertaChallenge::where('id_siswa', $siswa->id_siswa)
|
|
->where('id_challenge', $id_challenge)
|
|
->where('status', 'selesai')
|
|
->exists();
|
|
|
|
if ($sudah) {
|
|
return redirect()->route('siswa.challenge.hasil', $id_challenge);
|
|
}
|
|
|
|
if (Carbon::parse($challenge->tenggat_waktu)->isPast()) {
|
|
return redirect()->route('siswa.challenge.index')
|
|
->with('error', 'Challenge ini sudah melewati tenggat waktu.');
|
|
}
|
|
|
|
if ($challenge->soal->isEmpty()) {
|
|
return redirect()->route('siswa.challenge.index')
|
|
->with('error', 'Challenge ini belum memiliki soal.');
|
|
}
|
|
|
|
return view('siswa.challenge.kerjakan', compact('challenge'));
|
|
}
|
|
|
|
public function submit(Request $request, $id_challenge)
|
|
{
|
|
$siswa = Auth::guard('siswa')->user();
|
|
|
|
$challenge = Challenge::whereHas('kelas', function ($q) use ($siswa) {
|
|
$q->where('challenge_kelas.id_kelas', $siswa->id_kelas);
|
|
})
|
|
->with('soal')
|
|
->findOrFail($id_challenge);
|
|
|
|
$sudah = PesertaChallenge::where('id_siswa', $siswa->id_siswa)
|
|
->where('id_challenge', $id_challenge)
|
|
->where('status', 'selesai')
|
|
->exists();
|
|
|
|
if ($sudah) {
|
|
return redirect()->route('siswa.challenge.hasil', $id_challenge);
|
|
}
|
|
|
|
if (Carbon::parse($challenge->tenggat_waktu)->isPast()) {
|
|
return redirect()->route('siswa.challenge.index')
|
|
->with('error', 'Challenge sudah melewati tenggat waktu.');
|
|
}
|
|
|
|
$jawaban = $request->input('jawaban', []);
|
|
$totalExp = 0;
|
|
$jawabanJson = [];
|
|
|
|
foreach ($challenge->soal as $soal) {
|
|
$jwb = $jawaban[$soal->id_soal] ?? null;
|
|
$jawabanJson[$soal->id_soal] = $jwb;
|
|
if ($jwb && strtoupper($jwb) === strtoupper($soal->jawaban_benar)) {
|
|
$totalExp += $soal->exp_per_soal;
|
|
}
|
|
}
|
|
|
|
// Semester & tahun ajaran otomatis
|
|
$now = Carbon::now();
|
|
$semester = $now->month >= 7 ? '1' : '2';
|
|
$tahunAjaran = $now->month >= 7
|
|
? $now->year . '/' . ($now->year + 1)
|
|
: ($now->year - 1) . '/' . $now->year;
|
|
|
|
DB::transaction(function () use ($siswa, $challenge, $jawabanJson, $totalExp, $semester, $tahunAjaran) {
|
|
PesertaChallenge::create([
|
|
'id_challenge' => $challenge->id_challenge,
|
|
'id_siswa' => $siswa->id_siswa,
|
|
'jawaban' => json_encode($jawabanJson),
|
|
'waktu_submit' => Carbon::now(),
|
|
'exp' => $totalExp,
|
|
'status' => 'selesai',
|
|
]);
|
|
|
|
// firstOrCreate dengan semester & tahun_ajaran sebagai key
|
|
$lb = Leaderboard::firstOrCreate(
|
|
[
|
|
'id_siswa' => $siswa->id_siswa,
|
|
'id_kelas' => $siswa->id_kelas,
|
|
'semester' => $semester,
|
|
'tahun_ajaran' => $tahunAjaran,
|
|
],
|
|
['total_exp' => 0, 'ranking' => 0]
|
|
);
|
|
|
|
$lb->increment('total_exp', $totalExp);
|
|
|
|
// Recalculate ranking per kelas + semester + tahun ajaran
|
|
Leaderboard::where('id_kelas', $siswa->id_kelas)
|
|
->where('semester', $semester)
|
|
->where('tahun_ajaran', $tahunAjaran)
|
|
->orderBy('total_exp', 'desc')
|
|
->get()
|
|
->each(fn($row, $i) => $row->update(['ranking' => $i + 1]));
|
|
});
|
|
|
|
return redirect()->route('siswa.challenge.hasil', $id_challenge);
|
|
}
|
|
|
|
public function hasil($id_challenge)
|
|
{
|
|
$siswa = Auth::guard('siswa')->user();
|
|
|
|
$challenge = Challenge::with('soal')->findOrFail($id_challenge);
|
|
|
|
$peserta = PesertaChallenge::where('id_siswa', $siswa->id_siswa)
|
|
->where('id_challenge', $id_challenge)
|
|
->firstOrFail();
|
|
|
|
$jawabanSiswa = json_decode($peserta->jawaban, true) ?? [];
|
|
|
|
$benar = 0; $salah = 0;
|
|
foreach ($challenge->soal as $soal) {
|
|
$jwb = $jawabanSiswa[$soal->id_soal] ?? null;
|
|
strtoupper((string)$jwb) === strtoupper($soal->jawaban_benar) ? $benar++ : $salah++;
|
|
}
|
|
|
|
$totalSoal = $challenge->soal->count();
|
|
$persentase = $totalSoal > 0 ? round(($benar / $totalSoal) * 100) : 0;
|
|
|
|
return view('siswa.challenge.hasil', compact(
|
|
'challenge', 'peserta', 'jawabanSiswa',
|
|
'benar', 'salah', 'totalSoal', 'persentase'
|
|
));
|
|
}
|
|
} |