Created
June 15, 2023 09:54
-
-
Save FiqSky/3519f649fb6d5578fdfc10f734ce69f4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.ContentValues | |
import android.content.ContentValues.TAG | |
import android.content.Intent | |
import androidx.appcompat.app.AppCompatActivity | |
import android.os.Bundle | |
import android.os.Handler | |
import android.os.Looper | |
import android.util.Log | |
import android.view.View | |
import android.widget.Button | |
import android.widget.Toast | |
import androidx.recyclerview.widget.LinearLayoutManager | |
import androidx.recyclerview.widget.RecyclerView | |
import com.airbnb.lottie.LottieAnimationView | |
import com.google.firebase.database.* | |
import soup.neumorphism.NeumorphCardView | |
import kotlin.math.pow | |
class GejalaActivity : AppCompatActivity() { | |
private lateinit var database: DatabaseReference | |
private val selectedGejala = mutableSetOf<Gejala>() | |
private lateinit var gejalaAdapter: GejalaAdapter | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_gejala) | |
database = FirebaseDatabase.getInstance().reference | |
fetchGejala { gejalaMap -> | |
val gejalaList = gejalaMap.values.toList() | |
setupRecyclerView(gejalaList) | |
Log.d(ContentValues.TAG, "onCreate: $gejalaList") | |
} | |
val calculateButton = findViewById<NeumorphCardView>(R.id.calculateButton) | |
calculateButton.setOnClickListener { | |
if (selectedGejala.size < 5 || selectedGejala.size > 8) { | |
Toast.makeText(this, "Harap pilih antara 5 hingga 8 gejala", Toast.LENGTH_SHORT).show() | |
} else { | |
showLoadingProgress(true) | |
fetchPenyakit { penyakitMap -> | |
val (mostLikelyPenyakitPair, calculationDetails) = dempsterShafer(selectedGejala.toList(), penyakitMap.values.toList()) | |
val (mostLikelyPenyakitKeys, mostLikelyPenyakitProbability) = mostLikelyPenyakitPair | |
// val mostLikelyPenyakitNames = mostLikelyPenyakitKeys.map { penyakitKey -> | |
// penyakitMap[penyakitKey]?.nama_penyakit ?: "Tidak ditemukan" | |
// }.joinToString(", ") | |
val mostLikelyPenyakitNames = mostLikelyPenyakitKeys.joinToString(", ") | |
for (penyakitKey in mostLikelyPenyakitKeys) { | |
Log.d("debug", "Penyakit key: $penyakitKey, name: ${penyakitMap[penyakitKey]?.nama_penyakit}") | |
} | |
val probabilityPercentage = (mostLikelyPenyakitProbability * 100).toInt() | |
Log.d(ContentValues.TAG, "onCreate: $mostLikelyPenyakitNames") | |
val intent = Intent(this, ResultActivity::class.java) | |
val result = "Hasil Diagnosa: $mostLikelyPenyakitNames\n" + | |
"Nilai Keyakinan: $probabilityPercentage%" | |
intent.putExtra("result", result) | |
intent.putExtra("calculationDetails", calculationDetails) | |
val mostLikelyPenyakitKey = mostLikelyPenyakitKeys.firstOrNull() | |
intent.putExtra("nama_penyakit", penyakitMap[mostLikelyPenyakitKey]?.nama_penyakit) | |
intent.putExtra("pengertian", penyakitMap[mostLikelyPenyakitKey]?.pengertian) | |
intent.putExtra("penanganan", penyakitMap[mostLikelyPenyakitKey]?.penanganan) | |
intent.putExtra("catatan", penyakitMap[mostLikelyPenyakitKey]?.catatan) | |
intent.putExtra("sumber", penyakitMap[mostLikelyPenyakitKey]?.sumber) | |
intent.putExtra("gambar", penyakitMap[mostLikelyPenyakitKey]?.gambar) | |
// Menambahkan penundaan sebelum memulai ResultActivity dan menyembunyikan progress view | |
Handler(Looper.getMainLooper()).postDelayed({ | |
startActivity(intent) | |
showLoadingProgress(false) | |
}, 2000) // 2000 ms = 2 detik | |
} | |
} | |
} | |
} | |
private fun fetchGejala(callback: (Map<String, Gejala>) -> Unit) { | |
val gejalaRef = database.child("GEJALA") | |
gejalaRef.addValueEventListener(object : ValueEventListener { | |
override fun onDataChange(dataSnapshot: DataSnapshot) { | |
val gejalaMap = dataSnapshot.children.associateBy({ it.key!! }, { it.getValue(Gejala::class.java)!! }) | |
callback(gejalaMap) | |
} | |
override fun onCancelled(databaseError: DatabaseError) { | |
Log.w("MainActivity", "loadGejala:onCancelled", databaseError.toException()) | |
} | |
}) | |
} | |
private fun fetchPenyakit(callback: (Map<String, Penyakit>) -> Unit) { | |
val penyakitRef = database.child("PENYAKIT") | |
penyakitRef.addValueEventListener(object : ValueEventListener { | |
override fun onDataChange(dataSnapshot: DataSnapshot) { | |
val penyakitMap = dataSnapshot.children.associateBy({ it.key!! }, { dataSnapshot -> | |
val kode_penyakit = dataSnapshot.child("kode_penyakit").getValue(String::class.java) ?: "" | |
val nama_penyakit = dataSnapshot.child("nama_penyakit").getValue(String::class.java) ?: "" | |
val pengertian = dataSnapshot.child("pengertian").getValue(String::class.java) ?: "" | |
val penanganan = dataSnapshot.child("penanganan").getValue(String::class.java) ?: "" | |
val sumber = dataSnapshot.child("sumber").getValue(String::class.java) ?: "" | |
val catatan = dataSnapshot.child("catatan").getValue(String::class.java) ?: "" | |
val gambar = dataSnapshot.child("gambar").getValue(String::class.java) ?: "" | |
val daftar_gejala = dataSnapshot.child("daftar_gejala").children | |
.mapNotNull { it.getValue(String::class.java) } | |
Penyakit(kode_penyakit, nama_penyakit, pengertian, penanganan, sumber, catatan, gambar, daftar_gejala) | |
}) | |
callback(penyakitMap) | |
} | |
override fun onCancelled(databaseError: DatabaseError) { | |
Log.w("MainActivity", "loadPenyakit:onCancelled", databaseError.toException()) | |
} | |
}) | |
} | |
private fun setupRecyclerView(gejalaList: List<Gejala>) { | |
val gejalaRecyclerView = findViewById<RecyclerView>(R.id.gejalaRecyclerView) | |
gejalaRecyclerView.layoutManager = LinearLayoutManager(this) | |
// Urutkan gejalaList berdasarkan alfabet | |
val sortedGejalaList = gejalaList.sortedBy { it.gejala } | |
gejalaRecyclerView.adapter = GejalaAdapter(sortedGejalaList) { gejala, isChecked -> | |
if (isChecked) { | |
selectedGejala.add(gejala) | |
} else { | |
selectedGejala.remove(gejala) | |
} | |
} | |
gejalaRecyclerView.isNestedScrollingEnabled = false | |
} | |
private fun showLoadingProgress(show: Boolean) { | |
val lottieProgressView = findViewById<LottieAnimationView>(R.id.animationView) | |
lottieProgressView.visibility = if (show) View.VISIBLE else View.GONE | |
} | |
// Implementasikan metode Dempster-Shafer dan tampilkan hasil diagnosa | |
data class MassFunction( | |
val penyakit: List<String>, | |
val mValue: Double | |
) | |
data class PersentaseKemungkinan( | |
val penyakit: List<String>, | |
val nilaiPersentase: Double | |
) | |
private fun hitungMassFunction(gejala: Gejala): MassFunction { | |
val mValue = gejala.bobot | |
val daftarPenyakit = gejala.daftar_penyakit.toSet() | |
return MassFunction(daftarPenyakit.toList(), mValue) | |
} | |
private fun hitungMassFunctionKombinasi( | |
semuaGejala: List<MassFunction> | |
): List<MassFunction> { | |
var totalBelief = mutableMapOf<Set<String>, Double>() | |
totalBelief[setOf()] = 1.0 | |
for (gejala in semuaGejala) { | |
val newBelief = mutableMapOf<Set<String>, Double>() | |
newBelief[gejala.penyakit.toSet()] = gejala.mValue | |
newBelief[setOf()] = 1 - gejala.mValue | |
val combinedBelief = mutableMapOf<Set<String>, Double>() | |
for ((newKey, newValue) in newBelief) { | |
for ((oldKey, oldValue) in totalBelief) { | |
val intersect = newKey.intersect(oldKey) | |
val combinedKey = if (intersect.isNotEmpty()) intersect else newKey.union(oldKey) | |
val denominator = 1 - (newBelief.getOrDefault(setOf(), 0.0) * totalBelief.getOrDefault(setOf(), 0.0)) | |
if (denominator != 0.0) { | |
val combinedValue = (newValue * oldValue) / denominator | |
combinedBelief[combinedKey] = combinedBelief.getOrDefault(combinedKey, 0.0) + combinedValue | |
} | |
} | |
} | |
totalBelief = combinedBelief | |
} | |
return totalBelief.entries.map { MassFunction(it.key.toList(), it.value) } | |
} | |
private fun dempsterShafer( | |
selectedGejala: List<Gejala>, | |
allPenyakit: List<Penyakit> | |
): Pair<PersentaseKemungkinan, ArrayList<String>> { | |
val semuaGejala = selectedGejala.map { hitungMassFunction(it) } | |
val mKombinasi = hitungMassFunctionKombinasi(semuaGejala) | |
val mostLikelyPenyakit = mKombinasi.maxByOrNull { it.mValue }!! | |
val mostLikelyPenyakitName = mostLikelyPenyakit.penyakit.map { penyakitCode -> | |
allPenyakit.find { it.kode_penyakit == penyakitCode }?.nama_penyakit ?: "Tidak ditemukan" | |
}.joinToString(", ") | |
Log.d(TAG, "dempsterShafer: $mostLikelyPenyakitName = ${mostLikelyPenyakit.mValue}") | |
val calculationDetails = arrayListOf<String>() | |
calculationDetails.add("Gejala yang dipilih:") | |
for (gejala in selectedGejala) { | |
calculationDetails.add("${gejala.gejala} (kode: ${gejala.kode_gejala}, bobot: ${gejala.bobot})") | |
} | |
calculationDetails.add("") | |
calculationDetails.add("Kombinasi Nilai Massa:") | |
for ((penyakitKey, massValue) in mKombinasi) { | |
val penyakitName = penyakitKey.joinToString(", ") | |
calculationDetails.add("[$penyakitName], nilai: $massValue") | |
} | |
return Pair(PersentaseKemungkinan(mostLikelyPenyakit.penyakit, mostLikelyPenyakit.mValue), calculationDetails) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment