MIF_E31230650/Assets/Resources/Script/KuisManager.cs

532 lines
18 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;
using Firebase;
using Firebase.Database;
using Firebase.Extensions;
[System.Serializable]
public class SoalData
{
public int id;
public string tipe;
public string pertanyaan;
public string gambar;
public string audio_pertanyaan;
public string audio_jawaban;
public string[] pilihan;
public string[] pilihan_gambar;
public string jawaban;
}
[System.Serializable]
public class SoalWrapper
{
public string kategori;
public SoalData[] soal;
}
public class KuisManager : MonoBehaviour
{
[Header("Panel")]
public GameObject panelSoal;
public GameObject panelHasil;
[Header("Loading")]
public GameObject panelLoading;
public TextMeshProUGUI textLoading;
[Header("Elemen Soal")]
public TextMeshProUGUI textSoal;
public Image imageSoal;
public Button btnA, btnB, btnC;
public TextMeshProUGUI textA, textB, textC;
public GameObject frameSoal;
public GameObject frameSoalGambar;
public TextMeshProUGUI textSoalGambar;
[Header("Skor")]
public TextMeshProUGUI textSkor;
[Header("Panel Hasil")]
public TextMeshProUGUI textPesan;
public TextMeshProUGUI textSkorAkhir;
public Button btnUlang, btnMenu, btnNextLevel;
public Image imgStikerHasil;
public Sprite stikerHasilBagus;
public Sprite stikerHasilKurang;
[Header("Popup Benar/Salah")]
public GameObject panelPopup;
public Image imgStiker;
public Sprite stikerBenar;
public Sprite stikerSalah;
[Header("Jawaban Gambar")]
public GameObject panelJawabanGambar;
public Button btnGambarA, btnGambarB, btnGambarC;
[Header("Navigasi")]
public Button btnHome;
// --- private ---
private List<SoalData> daftarSoal = new List<SoalData>();
private int indexSoal = 0;
private int skor = 0;
private int totalSoal = 5;
private string jawabanBenar;
private AudioSource audioSource;
private AudioClip clipPertanyaan;
private string kategoriAktif;
private DatabaseReference dbRef;
private List<string> listHewan = new List<string> {
"anjing","ayam","babi","bebek","buaya","burung",
"gajah","harimau","ikan","jerapah","kambing","katak","kelinci",
"kepiting","kucing","kupu-kupu","kura","landak","lebah","rubah",
"rusa","sapi","singa","ular","ulat","zebra"
};
private List<string> listAssetWarna = new List<string> {
"bintang_merah","bintang_biru","bintang_hijau","bintang_kuning",
"bintang_orange","bintang_ungu","bintang_pink","bintang_coklat","bintang_hitam",
"krayon_merah","krayon_biru","krayon_hijau","krayon_kuning",
"krayon_orange","krayon_ungu","krayon_pink","krayon_coklat",
"lingkaran_merah","lingkaran_biru","lingkaran_hijau","lingkaran_kuning",
"lingkaran_orange","lingkaran_ungu","lingkaran_pink","lingkaran_coklat",
"persegi_merah","persegi_biru","persegi_hijau","persegi_kuning",
"persegi_orange","persegi_ungu","persegi_pink","persegi_coklat",
"segitiga_merah","segitiga_biru","segitiga_hijau","segitiga_kuning",
"segitiga_orange","segitiga_ungu","segitiga_pink","segitiga_coklat",
"tomat","matahari","rumput","payung_biru","payung_merah",
"pita","terong","balon","kursi","pelampung"
};
void Start()
{
audioSource = GetComponent<AudioSource>();
if (audioSource == null)
audioSource = gameObject.AddComponent<AudioSource>();
string rawKategori = PlayerPrefs.GetString("kategori", "Hewan");
kategoriAktif = rawKategori.ToLower();
if (btnHome != null)
{
btnHome.onClick.RemoveAllListeners();
btnHome.onClick.AddListener(KembaliKeMenu);
}
panelHasil.SetActive(false);
panelSoal.SetActive(false);
panelPopup.SetActive(false);
panelJawabanGambar.SetActive(false);
frameSoalGambar.SetActive(false);
// Tampilkan loading dulu
if (panelLoading != null) panelLoading.SetActive(true);
if (textLoading != null) textLoading.text = "Memuat soal...";
// Inisialisasi Firebase lalu muat soal
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
if (task.Result == DependencyStatus.Available)
{
dbRef = FirebaseDatabase.DefaultInstance.RootReference;
Debug.Log("✅ Firebase siap!");
MuatSoalDariFirebase();
}
else
{
Debug.LogError("❌ Firebase gagal: " + task.Result);
if (textLoading != null)
textLoading.text = "Gagal konek ke server.\nCek koneksi internet!";
}
});
}
void MuatSoalDariFirebase()
{
int level = PlayerPrefs.GetInt("level", 1);
string kunci = kategoriAktif + "_level" + level; // contoh: "hewan_level1"
Debug.Log("📡 Mengambil soal dari Firebase: soal/" + kunci);
dbRef.Child("soal").Child(kunci).GetValueAsync().ContinueWithOnMainThread(task =>
{
if (task.IsFaulted || task.IsCanceled)
{
Debug.LogError("❌ Gagal ambil data dari Firebase: " + task.Exception);
if (textLoading != null)
textLoading.text = "Gagal memuat soal.\nCek koneksi internet!";
return;
}
DataSnapshot snapshot = task.Result;
if (!snapshot.Exists)
{
Debug.LogError("❌ Data tidak ditemukan di Firebase: soal/" + kunci);
if (textLoading != null)
textLoading.text = "Data soal tidak ditemukan!";
return;
}
// Parse data dari Firebase ke List<SoalData>
List<SoalData> semua = new List<SoalData>();
foreach (DataSnapshot soalSnap in snapshot.Children)
{
Debug.Log("proses ambil data soal dari firebase");
SoalData s = new SoalData();
s.id = soalSnap.Child("id").Value != null
? int.Parse(soalSnap.Child("id").Value.ToString()) : 0;
s.tipe = soalSnap.Child("tipe").Value?.ToString() ?? "pilihan_ganda";
s.pertanyaan = soalSnap.Child("pertanyaan").Value?.ToString() ?? "";
s.gambar = soalSnap.Child("gambar").Value?.ToString() ?? "";
s.audio_pertanyaan = soalSnap.Child("audio_pertanyaan").Value?.ToString() ?? "";
s.audio_jawaban = soalSnap.Child("audio_jawaban").Value?.ToString() ?? "";
s.jawaban = soalSnap.Child("jawaban").Value?.ToString() ?? "";
Debug.Log("pertanyaan : "+s.pertanyaan.ToString());
// Ambil pilihan dari pilihan_0, pilihan_1, pilihan_2
s.pilihan = new string[]
{
soalSnap.Child("pilihan_0").Value?.ToString() ?? "",
soalSnap.Child("pilihan_1").Value?.ToString() ?? "",
soalSnap.Child("pilihan_2").Value?.ToString() ?? ""
};
// pilihan_gambar kosong (tidak dipakai di struktur Firebase saat ini)
//s.pilihan_gambar = new string[0];
if (soalSnap.Child("pilihan_gambar_0").Exists)
{
s.pilihan_gambar = new string[]
{
soalSnap.Child("pilihan_gambar_0").Value?.ToString() ?? "",
soalSnap.Child("pilihan_gambar_1").Value?.ToString() ?? "",
soalSnap.Child("pilihan_gambar_2").Value?.ToString() ?? ""
};
}
else
{
s.pilihan_gambar = new string[0];
}
// Filter tipe suara_hewan
if (s.tipe != "suara_hewan")
semua.Add(s);
}
// Shuffle
for (int i = semua.Count - 1; i > 0; i--)
{
int r = Random.Range(0, i + 1);
SoalData tmp = semua[i];
semua[i] = semua[r];
semua[r] = tmp;
}
daftarSoal.Clear();
indexSoal = 0;
skor = 0;
totalSoal = Mathf.Min(5, semua.Count);
for (int i = 0; i < totalSoal; i++)
daftarSoal.Add(semua[i]);
Debug.Log("✅ Soal berhasil dimuat: " + totalSoal + " soal dari Firebase");
// Sembunyikan loading, tampilkan soal
if (panelLoading != null) panelLoading.SetActive(false);
panelSoal.SetActive(true);
TampilkanSoal();
});
}
string DeteksiFolderGambar(string namaFile)
{
if (listAssetWarna.Contains(namaFile))
return "warna";
else if (listHewan.Contains(namaFile))
return "hewan";
else
return "buah";
}
void TampilkanSoal()
{
if (indexSoal >= totalSoal)
{
TampilkanHasil();
return;
}
StartCoroutine(TampilkanSoalCoroutine());
}
IEnumerator TampilkanSoalCoroutine()
{
SoalData s = daftarSoal[indexSoal];
jawabanBenar = s.jawaban;
bool adaPilihanGambar = s.tipe == "pilihan_gambar";
bool adaGambar = (s.tipe == "pilihan_ganda" || s.tipe == "drag_drop") && !string.IsNullOrEmpty(s.gambar);
// STEP 1: Sembunyikan semua
btnA.gameObject.SetActive(false);
btnB.gameObject.SetActive(false);
btnC.gameObject.SetActive(false);
panelJawabanGambar.SetActive(false);
imageSoal.gameObject.SetActive(false);
frameSoal.SetActive(false);
frameSoalGambar.SetActive(false);
yield return null;
// STEP 2: Set teks soal
textSoal.text = s.pertanyaan;
textSoalGambar.text = s.pertanyaan;
// STEP 3: Aktifkan frame
frameSoal.SetActive(!adaPilihanGambar);
frameSoalGambar.SetActive(adaPilihanGambar);
// STEP 4: Aktifkan panel jawaban
if (adaPilihanGambar)
{
panelJawabanGambar.SetActive(true);
}
else
{
btnA.gameObject.SetActive(true);
btnB.gameObject.SetActive(true);
btnC.gameObject.SetActive(true);
}
yield return null;
// STEP 5: Load gambar soal
if (adaGambar)
{
string folderGambarSoal = kategoriAktif == "warna"
? DeteksiFolderGambar(s.gambar)
: kategoriAktif;
Sprite sp = Resources.Load<Sprite>("Gambar/" + folderGambarSoal + "/" + s.gambar);
if (sp != null)
{
imageSoal.sprite = sp;
imageSoal.gameObject.SetActive(true);
}
else
Debug.LogWarning("⚠️ Gambar tidak ditemukan: Gambar/" + folderGambarSoal + "/" + s.gambar);
}
// STEP 6: Setup tombol jawaban gambar
if (adaPilihanGambar && s.pilihan_gambar != null && s.pilihan_gambar.Length >= 3)
{
Button[] btns = { btnGambarA, btnGambarB, btnGambarC };
for (int i = 0; i < 3; i++)
{
Image img = btns[i].GetComponent<Image>();
string namaSprite = s.pilihan_gambar[i];
string folderSprite = kategoriAktif == "warna"
? DeteksiFolderGambar(namaSprite) : kategoriAktif;
Sprite sp = Resources.Load<Sprite>("Gambar/" + folderSprite + "/" + namaSprite);
if (sp != null) img.sprite = sp;
string jwb = s.pilihan[i];
btns[i].onClick.RemoveAllListeners();
btns[i].onClick.AddListener(() => CekJawaban(jwb));
btns[i].interactable = true;
}
}
// STEP 7: Isi teks & listener tombol pilihan ganda
if (!adaPilihanGambar)
{
textA.text = s.pilihan != null && s.pilihan.Length > 0 ? s.pilihan[0] : "-";
textB.text = s.pilihan != null && s.pilihan.Length > 1 ? s.pilihan[1] : "-";
textC.text = s.pilihan != null && s.pilihan.Length > 2 ? s.pilihan[2] : "-";
btnA.onClick.RemoveAllListeners();
btnB.onClick.RemoveAllListeners();
btnC.onClick.RemoveAllListeners();
btnA.onClick.AddListener(() => CekJawaban(textA.text));
btnB.onClick.AddListener(() => CekJawaban(textB.text));
btnC.onClick.AddListener(() => CekJawaban(textC.text));
btnA.interactable = true;
btnB.interactable = true;
btnC.interactable = true;
// STEP 8: Force rebuild layout
yield return null;
Canvas.ForceUpdateCanvases();
RectTransform parentLayout = btnA.transform.parent.GetComponent<RectTransform>();
if (parentLayout != null)
LayoutRebuilder.ForceRebuildLayoutImmediate(parentLayout);
if (parentLayout != null && parentLayout.parent != null)
{
RectTransform grandParent = parentLayout.parent.GetComponent<RectTransform>();
if (grandParent != null)
LayoutRebuilder.ForceRebuildLayoutImmediate(grandParent);
}
}
// STEP 9: Audio pertanyaan
clipPertanyaan = null;
if (!string.IsNullOrEmpty(s.audio_pertanyaan))
{
clipPertanyaan = Resources.Load<AudioClip>("Audio/" + s.audio_pertanyaan);
if (clipPertanyaan != null)
StartCoroutine(AutoPlayPertanyaan());
}
textSkor.text = "Skor: " + skor;
Debug.Log("📝 Soal " + (indexSoal + 1) + " | Tipe: " + s.tipe + " | Jawaban: " + s.jawaban);
}
IEnumerator AutoPlayPertanyaan()
{
yield return new WaitForSeconds(0.5f);
if (clipPertanyaan != null)
{
audioSource.Stop();
audioSource.clip = clipPertanyaan;
audioSource.Play();
}
}
void CekJawaban(string jawaban)
{
btnA.interactable = false;
btnB.interactable = false;
btnC.interactable = false;
btnGambarA.interactable = false;
btnGambarB.interactable = false;
btnGambarC.interactable = false;
audioSource.Stop();
StopCoroutine("AutoPlayPertanyaan");
bool benar = (jawaban == jawabanBenar);
if (benar)
{
skor += 10;
textSkor.text = "Skor: " + skor;
Debug.Log("✅ Benar! Skor: " + skor);
StartCoroutine(BenarDenganAudio());
}
else
{
Debug.Log("❌ Salah! Jawaban benar: " + jawabanBenar);
StartCoroutine(PopupOtomatis(false));
}
}
IEnumerator BenarDenganAudio()
{
SoalData s = daftarSoal[indexSoal];
if (!string.IsNullOrEmpty(s.audio_jawaban))
{
AudioClip clipJawaban = Resources.Load<AudioClip>("Audio/" + s.audio_jawaban);
if (clipJawaban != null)
{
audioSource.PlayOneShot(clipJawaban);
yield return new WaitForSeconds(clipJawaban.length + 0.3f);
}
else
yield return new WaitForSeconds(0.8f);
}
else
yield return new WaitForSeconds(0.5f);
StartCoroutine(PopupOtomatis(true));
}
IEnumerator PopupOtomatis(bool benar)
{
panelPopup.SetActive(true);
imgStiker.sprite = benar ? stikerBenar : stikerSalah;
string namaAudio = benar ? "suara_benar" : "suara_salah";
AudioClip clip = Resources.Load<AudioClip>("Audio/" + namaAudio);
if (clip != null)
audioSource.PlayOneShot(clip);
yield return new WaitForSeconds(1.5f);
panelPopup.SetActive(false);
btnA.gameObject.SetActive(false);
btnB.gameObject.SetActive(false);
btnC.gameObject.SetActive(false);
btnA.interactable = true;
btnB.interactable = true;
btnC.interactable = true;
btnGambarA.interactable = true;
btnGambarB.interactable = true;
btnGambarC.interactable = true;
panelJawabanGambar.SetActive(false);
yield return null;
indexSoal++;
TampilkanSoal();
}
void TampilkanHasil()
{
panelSoal.SetActive(false);
panelHasil.SetActive(true);
int skorMax = totalSoal * 10;
textSkorAkhir.text = "Skor Akhir : " + skor + " / " + skorMax;
bool skorBagus = skor >= 30;
if (textPesan != null)
textPesan.text = skorBagus
? "Hebat! Kamu Luar Biasa!"
: "Jangan Menyerah! Coba Lagi!";
if (imgStikerHasil != null)
{
Sprite stikerDipilih = skorBagus ? stikerHasilBagus : stikerHasilKurang;
if (stikerDipilih != null)
imgStikerHasil.sprite = stikerDipilih;
}
int level = PlayerPrefs.GetInt("level", 1);
btnNextLevel.gameObject.SetActive(level < 3);
btnUlang.onClick.RemoveAllListeners();
btnMenu.onClick.RemoveAllListeners();
btnNextLevel.onClick.RemoveAllListeners();
btnUlang.onClick.AddListener(() => SceneManager.LoadScene("Kuis"));
btnMenu.onClick.AddListener(() => SceneManager.LoadScene("MainMenu"));
btnNextLevel.onClick.AddListener(() =>
{
PlayerPrefs.SetInt("level", level + 1);
SceneManager.LoadScene("Kuis");
});
}
public void KembaliKeMenu()
{
SceneManager.LoadScene("MainMenu");
}
}