Skip to content

Instantly share code, notes, and snippets.

@FiqSky
Created June 15, 2023 09:54
Show Gist options
  • Save FiqSky/3519f649fb6d5578fdfc10f734ce69f4 to your computer and use it in GitHub Desktop.
Save FiqSky/3519f649fb6d5578fdfc10f734ce69f4 to your computer and use it in GitHub Desktop.
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