diff --git a/app/build.gradle b/app/build.gradle
index 4fae05b..61967bf 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting"
minSdk 21
targetSdk 34
- versionCode 28
- versionName "2.1.28"
+ versionCode 30
+ versionName "2.1.30"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -80,6 +80,12 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+ // Mockito dependencies
+ testImplementation 'org.mockito:mockito-core:3.12.4'
+ androidTestImplementation 'org.mockito:mockito-android:3.12.4'
+ androidTestImplementation 'org.mockito:mockito-inline:3.12.4'
+ testImplementation "androidx.arch.core:core-testing:2.2.0"
+ testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 98c18c5..c2f6365 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,9 @@
+
+
diff --git a/app/src/main/java/com/example/hpostesting/data/constant/Constants.kt b/app/src/main/java/com/example/hpostesting/data/constant/Constants.kt
index 33aff22..3212e10 100644
--- a/app/src/main/java/com/example/hpostesting/data/constant/Constants.kt
+++ b/app/src/main/java/com/example/hpostesting/data/constant/Constants.kt
@@ -75,6 +75,39 @@ object Constants {
const val BUFFER_VALUE_4 = "BufferValue4"
const val DEVICE_ID = "DEVICE_ID"
- const val BUFFER_LED_LOWER_BOUND = 20000
- const val BUFFER_LED_HIGHER_BOUND = 24000
+ const val BUFFER_LED_LOWER_BOUND = 21000
+ const val BUFFER_LED_UPPER_BOUND = 24500
+
+ val DEVICE_CONFIGURATION: Map>> = mapOf>>(
+ "HCV-000-3001" to listOf(
+ listOf(1.264817, -0.85965), // LED1, 435nm
+ listOf(0.581462456, -0.58502), // LED2, 415nm
+ listOf(0.184991, 0.001704), // LED3, 555nm
+ listOf(1.0, 0.0) // LED4
+ ),
+ "HCV-000-3002" to listOf(
+ listOf(1.264817, -0.85965),
+ listOf(0.581462456, -0.58502),
+ listOf(0.184991, 0.001704),
+ listOf(1.0, 0.0)
+ ),
+ )
+
+ const val INCUBATION_TIME_MIN = 15
+ const val INCUBATION_TIME_MAX = 30
+
+ val BUFFER_INTENSITY_THRESHOLDS: Map>> = mapOf>>(
+ "HCV-000-3001" to listOf(
+ listOf(24000, 24500),
+ listOf(21000, 24500),
+ listOf(21000, 24500),
+ listOf(21000, 24500),
+ ),
+ "HCV-000-3002" to listOf(
+ listOf(21000, 24500),
+ listOf(21000, 24500),
+ listOf(21000, 24500),
+ listOf(21000, 24500),
+ )
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt b/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
index 339d58d..62cbda1 100644
--- a/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
+++ b/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
@@ -11,7 +11,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton
-@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 5, exportSchema = false)
+@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 10, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt
index 8f3b663..f410705 100644
--- a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt
+++ b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt
@@ -8,6 +8,8 @@ data class HemoCubeTestData(
@PrimaryKey
var _id: String = "",
var name: String = "",
+ var incubationTime: String = "",
+ var bloodGroup: String = "",
var birthYear: String = "",
var userImageURL: String = "",
var location: UserData.Location? = null,
@@ -34,8 +36,19 @@ data class HemoCubeTestData(
var led2Average: Double? = null,
var led3Average: Double? = null,
var led4Average: Double? = null,
+ var abs1: Double? = null,
+ var abs2: Double? = null,
+ var abs3: Double? = null,
+ var abs4: Double? = null,
var deviceRatio: Double? = null,
var calculatedRatio: Double? = null,
+ var predictedDenovixRatio: Double? = null,
var coefficients: String? = "",
- var classificationResult: String = ""
+ var classificationResult: String = "",
+ var prdClassification: String = "",
+ var batteryLevel: String = "",
+ var batteryCapacity: String = "",
+ var batteryMaxCapacity: String = "",
+ var batteryTemperature: String = "",
+ var batteryVoltage: String = "",
)
diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
index 1b6c95d..a7ad7fd 100644
--- a/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
+++ b/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
@@ -9,6 +9,7 @@ data class UserData(
@PrimaryKey
var _id: String = "",
var name: String = "",
+ var bloodGroup: String = "",
var incubationTime: String = "",
var birthYear: String = "",
var userImageURL: String = "",
@@ -44,5 +45,7 @@ fun UserData.toHemoCubeTestData() = HemoCubeTestData(
birthYear = birthYear,
userImageURL = userImageURL,
testStatus = testStatus,
+ bloodGroup = bloodGroup,
+ incubationTime = incubationTime,
location = location
)
diff --git a/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt b/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt
index a7a2d8f..728aa3d 100644
--- a/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt
+++ b/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt
@@ -15,13 +15,14 @@ import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.ktx.storage
import kotlinx.coroutines.tasks.await
import java.io.File
+import javax.inject.Inject
-class DatabaseRepository : Repository {
+class DatabaseRepository @Inject constructor() : Repository {
private val db: FirebaseFirestore = Firebase.firestore
private val storage = Firebase.storage
- suspend fun addTestToDatabase(data: HemoCubeTestData?): Response {
+ override suspend fun addTestToDatabase(data: HemoCubeTestData?): Response {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
@@ -36,7 +37,7 @@ class DatabaseRepository : Repository {
}
}
- suspend fun addTestToDatabase(data: UserData?): Response {
+ override suspend fun addTestToDatabase(data: UserData?): Response {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
@@ -52,7 +53,7 @@ class DatabaseRepository : Repository {
}
}
- suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response {
+ override suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response {
return try {
db.collection("buffers").add(data!!).await()
Response.Success(data!!.kitno)
@@ -62,7 +63,7 @@ class DatabaseRepository : Repository {
}
}
- suspend fun addDiagnostics(data: DiagnosticsData?): Response {
+ override suspend fun addDiagnostics(data: DiagnosticsData?): Response {
return try {
db.collection("diagnostics").add(data!!).await()
Response.Success(data!!.deviceId)
@@ -72,7 +73,7 @@ class DatabaseRepository : Repository {
}
}
- suspend fun uploadFileToStorage(patientID: String, filePath: String): Response {
+ override suspend fun uploadFileToStorage(patientID: String, filePath: String): Response {
try {
val file = Uri.fromFile(File(filePath))
@@ -131,7 +132,7 @@ class DatabaseRepository : Repository {
return db.collection("devices").get().await().toObjects(DeviceData::class.java)
}
- suspend fun getDeviceDataById(deviceId: String): DeviceData? {
+ override suspend fun getDeviceDataById(deviceId: String): DeviceData? {
val querySnapshot = db.collection("devices").get().await()
val allDeviceDataList = querySnapshot.toObjects(DeviceData::class.java)
diff --git a/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt b/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt
index 3419ceb..f809295 100644
--- a/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt
+++ b/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt
@@ -1,5 +1,22 @@
package com.example.hpostesting.data.repository
+import com.example.hpostesting.data.model.Response
+import com.example.hpostesting.data.model.diagnostics.DiagnosticsData
+import com.example.hpostesting.data.model.patient.BufferCheckData
+import com.example.hpostesting.data.model.patient.DeviceData
+import com.example.hpostesting.data.model.patient.HemoCubeTestData
+import com.example.hpostesting.data.model.patient.UserData
+
interface Repository {
-// suspend fun addToDatabase(data: PatientDetails)
+ suspend fun addTestToDatabase(data: HemoCubeTestData?): Response
+
+ suspend fun addTestToDatabase(data: UserData?): Response
+
+ suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response
+
+ suspend fun addDiagnostics(data: DiagnosticsData?): Response
+
+ suspend fun uploadFileToStorage(patientID: String, filePath: String): Response
+
+ suspend fun getDeviceDataById(deviceId: String): DeviceData?
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt b/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt
index e0252b6..3c4b5ce 100644
--- a/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt
+++ b/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt
@@ -9,6 +9,7 @@ import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.LocalFileRepository
+import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import dagger.Module
@@ -69,4 +70,10 @@ object AppModule {
fun provideDatabaseRepository(): DatabaseRepository {
return DatabaseRepository()
}
+
+ @Provides
+ @Singleton
+ fun provideRepository(): Repository {
+ return DatabaseRepository()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
new file mode 100644
index 0000000..6acd933
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
@@ -0,0 +1,122 @@
+package com.example.hpostesting.presentation.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.navigation.findNavController
+import androidx.recyclerview.widget.AsyncListDiffer
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.RecyclerView
+import com.example.hpostesting.data.DataHolder
+import com.example.hpostesting.data.constant.Constants
+import com.example.hpostesting.data.model.patient.HemoCubeTestData
+import com.example.hpostesting.data.model.patient.UserData
+import `in`.sminnovations.hpostesting.R
+import `in`.sminnovations.hpostesting.databinding.OfflineUserListViewBinding
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Date
+import java.util.Locale
+
+class OfflineUserListAdapter(private val view: View, private val batLevel: Int) :
+ RecyclerView.Adapter() {
+
+ inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
+ RecyclerView.ViewHolder(binding.root)
+
+ private val differCallback = object : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(
+ oldItem: HemoCubeTestData, newItem: HemoCubeTestData
+ ): Boolean {
+ return oldItem._id == newItem._id
+ }
+
+ override fun areContentsTheSame(
+ oldItem: HemoCubeTestData, newItem: HemoCubeTestData
+ ): Boolean {
+ return oldItem == newItem
+ }
+ }
+
+ val differ = AsyncListDiffer(this, differCallback)
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OfflineUserListViewHolder {
+ return OfflineUserListViewHolder(
+ OfflineUserListViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ )
+ }
+
+ override fun getItemCount(): Int {
+ return differ.currentList.size
+ }
+
+ override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) {
+ val userList = differ.currentList[position]
+ holder.binding.apply {
+ userID.text = "User ID: ${userList._id}"
+ bloodGroup.text = "Blood group: ${userList.bloodGroup}"
+ time.text = "Time: ${userList.incubationTime}"
+ userCard.setOnClickListener {
+ if (batLevel < 40) {
+ Toast.makeText(
+ view.context,
+ "Battery level is low than 40%, please charge the device to continue testing",
+ Toast.LENGTH_SHORT
+ ).show()
+ return@setOnClickListener
+ }
+ if (userList.testStatus != null) {
+ if (userList.testStatus!!) {
+ Toast.makeText(
+ view.context,
+ "Test has been already conducted for this user",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ if (userList.incubationTime != "") {
+ if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
+ Toast.makeText(
+ view.context,
+ "Incubation has not completed 15 minutes",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
+ Toast.makeText(
+ view.context,
+ "Incubation crossed 30 minutes, need to repeat the incubation",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ DataHolder.selectedTest = UserData(
+ _id = userList._id,
+ bloodGroup = userList.bloodGroup,
+ incubationTime = userList.incubationTime
+ )
+ view.findNavController()
+ .navigate(R.id.action_nav_home_to_mainActivity)
+ }
+ } else {
+ Toast.makeText(
+ view.context,
+ "Incubation not started for this user",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun isBetween15And30Minutes(createdAt: String): Long {
+ val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
+ val createdAtDate: Date = formatter.parse(createdAt)!!
+
+ val currentTime = Calendar.getInstance().time
+
+ val diffMillis = currentTime.time - createdAtDate.time
+
+ return diffMillis / (60 * 1000)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
index 1a6995f..93f7414 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
@@ -20,6 +20,7 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.KitScanActivity
+import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel
@@ -33,6 +34,7 @@ import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import java.text.SimpleDateFormat
+import java.util.Calendar
import java.util.Date
import java.util.Locale
@@ -43,7 +45,9 @@ class HomeFragment : Fragment() {
private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter
- private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level
+ private var batLevel: Int =
+ 0 // Initialize with a default value, or obtain the actual battery level
+ private lateinit var adapter: OfflineUserListAdapter
private lateinit var sharedPreference: SharedPreferences
@@ -73,6 +77,19 @@ class HomeFragment : Fragment() {
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteHemoCubeIncompleteRegistrations(userData)
+ if (userData.isNotEmpty()) {
+ val userList = mutableListOf()
+ userData.forEach {
+ if (it.testStatus == false) {
+ userList.add(it)
+ }
+ }
+ val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
+ val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+ adapter = OfflineUserListAdapter(binding.root, batLevel)
+ adapter.differ.submitList(userList)
+ binding.rvOrderOffline.adapter = adapter
+ }
}
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) {
@@ -120,10 +137,18 @@ class HomeFragment : Fragment() {
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
- if (userId.length >= 18) {
- val userData = UserData(_id = userId)
- DataHolder.selectedTest = userData
- findNavController().navigate(R.id.action_nav_home_to_mainActivity)
+ val bloodGroup = binding.etBloodGroup.text
+ if (userId.length >= 18 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) {
+ hemoCubeViewModel.addUser(
+ HemoCubeTestData(
+ _id = userId, bloodGroup = bloodGroup.toString(), incubationTime = SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
+ ).format(Calendar.getInstance().time).toString()
+ )
+ )
+// val userData = UserData(_id = userId)
+// DataHolder.selectedTest = userData
+// findNavController().navigate(R.id.action_nav_home_to_mainActivity)
} else {
val errorMessage = getString(R.string.user_id_error_message)
Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show()
@@ -155,10 +180,12 @@ class HomeFragment : Fragment() {
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
- rvAdapter = view?.let {
- UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions,
- it, batLevel, requireActivity())
- }!!
+ rvAdapter = view?.let {
+ UserListAdapter(
+ requireContext(), hemoCubeViewModel, recyclerViewOptions,
+ it, batLevel, requireActivity()
+ )
+ }!!
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
@@ -206,8 +233,9 @@ class HomeFragment : Fragment() {
val partition = dateFormat.format(currentDate)
val searchTerm = partition + search
val searchField = field + "Search"
- val query = Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
- .endAt(searchTerm + "\uf8ff")
+ val query =
+ Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm)
+ .endAt(searchTerm + "\uf8ff")
query.get().addOnSuccessListener {
userSearchTrace.stop()
}
@@ -218,7 +246,14 @@ class HomeFragment : Fragment() {
batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
rvAdapter = view?.let {
- UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions, it, batLevel, requireActivity())
+ UserListAdapter(
+ requireContext(),
+ hemoCubeViewModel,
+ recyclerViewOptions,
+ it,
+ batLevel,
+ requireActivity()
+ )
}!!
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
@@ -272,7 +307,8 @@ class HomeFragment : Fragment() {
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
- val uploadDataVisibility = if (userDataList.any { !it.localFlag }) View.VISIBLE else View.GONE
+ val uploadDataVisibility =
+ if (userDataList.any { !it.localFlag && it.testStatus == true}) View.VISIBLE else View.GONE
binding.uploadData.visibility = uploadDataVisibility
}
}
@@ -331,7 +367,7 @@ class HomeFragment : Fragment() {
private fun deleteHemoCubeIncompleteRegistrations(userDataList: List) {
userDataList.forEach { userData ->
- if (userData.testTime?.isEmpty() == true) {
+ if (userData._id.isEmpty()) {
hemoCubeViewModel.deleteById(userData._id)
}
}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
index 735fcc6..d392a37 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
@@ -5,7 +5,6 @@ import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -20,7 +19,6 @@ import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.dashboard.DashboardActivity
-import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import com.google.firebase.crashlytics.ktx.crashlytics
@@ -35,7 +33,7 @@ class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences
- val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
+ private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private var isOnline = false
private var currentDeviceData: DeviceData? = null
private var resultData: String = ""
@@ -51,7 +49,13 @@ class HemoCubeFragment : Fragment() {
private var led2SampleForDevice = 0.0
private var led3SampleForDevice = 0.0
private var led4SampleForDevice = 0.0
+ private var fittedAbs1 = 0.0
+ private var fittedAbs2 = 0.0
+ private var fittedAbs3 = 0.0
+ private var fittedAbs4 = 0.0
+ private var _predictedDenovixRatio = 0.0
private var validationError = false
+ private var deviceHardwareId = ""
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
@@ -95,7 +99,7 @@ class HemoCubeFragment : Fragment() {
binding.btnSamplestart.setOnClickListener {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
- binding.tvSubtitle4.text = "Sample Started"
+// binding.tvSubtitle4.text = "Sample Started"
}
startSampleProcess()
it.visibility = View.GONE
@@ -287,6 +291,7 @@ class HemoCubeFragment : Fragment() {
val slData = stringData.split(" ")
if (slData.size > 1) {
val hardwareId = slData[1].trim()
+ deviceHardwareId = hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
@@ -317,12 +322,16 @@ class HemoCubeFragment : Fragment() {
}
stringData.contains("#SC") -> {
- binding.tvSubtitle4.text = "Sample Completed"
+ hemoCubeViewModel.messages.postValue("Sample Completed \nGathering data")
fetchResult()
testingTrace.stop()
}
resultData.contains("REND") -> {
+ hemoCubeViewModel.messages.postValue(
+ "Data collected \n" +
+ " Processing data"
+ )
val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
var bufferIntensity = resultLines[1].split(' ')[1].trim()
led1BufferForDevice = if (isUsingExistingBuffer) {
@@ -408,7 +417,58 @@ class HemoCubeFragment : Fragment() {
val led4Average = log10(led4BufferForDevice?.div(led4SampleForDevice!!) ?: 0.0)
val deviceRatio = led3Average / led1Average
- if (led1Average < 0 || led2Average < 0 || led3Average < 0 || led4Average < 0) {
+ if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)?.get(0)!!
+ || led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(1)?.get(0)!!
+ || led3BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(2)?.get(0)!!
+ || led4BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(3)?.get(0)!!
+ ) {
+ validationError = true
+ activity?.runOnUiThread {
+ binding.errorMessage.text = "Error: Invalid Test. Improper buffer reading (low)"
+ binding.errorMessage.visibility = View.VISIBLE
+ }
+ }
+
+ if (led1BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)?.get(1)!!
+ || led2BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(1)?.get(1)!!
+ || led3BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(2)?.get(1)!!
+ || led4BufferForDevice > Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(3)?.get(1)!!
+ ) {
+ validationError = true
+ activity?.runOnUiThread {
+ binding.errorMessage.text =
+ "Error: Invalid Test. Improper buffer reading (high)"
+ binding.errorMessage.visibility = View.VISIBLE
+ }
+ }
+
+ var gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(0)
+ var constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(0)?.get(1)
+ fittedAbs1 = gradient?.times(led1Average)?.plus(constant!!)!!
+
+ gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(0)
+ constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(1)?.get(1)
+ fittedAbs2 = gradient?.times(led2Average)?.plus(constant!!)!!
+
+ gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(0)
+ constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(2)?.get(1)
+ fittedAbs3 = gradient?.times(led3Average)?.plus(constant!!)!!
+
+ gradient = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(0)
+ constant = Constants.DEVICE_CONFIGURATION[deviceHardwareId]?.get(3)?.get(1)
+ fittedAbs4 = gradient?.times(led4Average)?.plus(constant!!)!!
+
+ _predictedDenovixRatio = fittedAbs3?.div(fittedAbs1!!)!!
+
+ if (fittedAbs1!! <= fittedAbs2!!) {
+ validationError = true
+ activity?.runOnUiThread {
+ binding.errorMessage.text = "Error: Invalid Test. Problem with de-oxygenation"
+ binding.errorMessage.visibility = View.VISIBLE
+ }
+ }
+
+ if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Negative Abs. Retake Blank Reading"
@@ -416,30 +476,6 @@ class HemoCubeFragment : Fragment() {
}
}
- if (led1BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND
- || led2BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND
- || led3BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND
- || led4BufferForDevice < Constants.BUFFER_LED_LOWER_BOUND
- ) {
- validationError = true
- activity?.runOnUiThread {
- binding.errorMessage.text = "Error: Invalid Test. Blank reading is too low"
- binding.errorMessage.visibility = View.VISIBLE
- }
- }
-
- if (led1BufferForDevice > Constants.BUFFER_LED_HIGHER_BOUND
- || led2BufferForDevice > Constants.BUFFER_LED_HIGHER_BOUND
- || led3BufferForDevice > Constants.BUFFER_LED_HIGHER_BOUND
- || led4BufferForDevice > Constants.BUFFER_LED_HIGHER_BOUND
- ) {
- validationError = true
- activity?.runOnUiThread {
- binding.errorMessage.text = "Error: Invalid Test. Blank reading is too high"
- binding.errorMessage.visibility = View.VISIBLE
- }
- }
-
DataHolder.hemoCubeTestData?.apply {
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
led1Buffer = led1BufferForDevice
@@ -455,29 +491,42 @@ class HemoCubeFragment : Fragment() {
this.led2Average = led2Average
this.led3Average = led3Average
this.led4Average = led4Average
+ this.abs1 = fittedAbs1
+ this.abs2 = fittedAbs2
+ this.abs3 = fittedAbs3
+ this.abs4 = fittedAbs4
this.deviceRatio = deviceRatio
this.calculatedRatio = calculateRatio(deviceRatio)
+ this.predictedDenovixRatio = _predictedDenovixRatio
this.coefficients = currentDeviceData?.coefficients?.get(0)
.toString() + ", " + currentDeviceData?.coefficients?.get(1).toString()
this.classificationResult = findResult(calculatedRatio)
- hemoCubeViewModel.messages.postValue(this.classificationResult)
+ this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
+ hemoCubeViewModel.messages.postValue(this.prdClassification)
this.resultData = deviceLog
- if (!isUsingExistingBuffer) {
- with(sharedPreferences.edit()) {
- putString(Constants.BUFFER_VALUE_1, led1BufferForDevice.toString())
- putString(Constants.BUFFER_VALUE_2, led2BufferForDevice.toString())
- putString(Constants.BUFFER_VALUE_3, led3BufferForDevice.toString())
- putString(Constants.BUFFER_VALUE_4, led4BufferForDevice.toString())
- apply()
- }
+ this.batteryLevel = hemoCubeViewModel.getBatteryLevel().toString()
+ this.batteryCapacity = hemoCubeViewModel.getBatteryCapacity(requireContext()).toString()
+ this.batteryMaxCapacity = hemoCubeViewModel.getBatteryMaxCapacity(requireContext()).toString()
+ this.batteryTemperature = hemoCubeViewModel.getBatteryTemperature().toString()
+ this.batteryVoltage = hemoCubeViewModel.getBatteryVoltage(requireContext()).toString()
+ }
+
+ if (!isUsingExistingBuffer) {
+ with(sharedPreferences.edit()) {
+ putString(Constants.BUFFER_VALUE_1, led1BufferForDevice.toString())
+ putString(Constants.BUFFER_VALUE_2, led2BufferForDevice.toString())
+ putString(Constants.BUFFER_VALUE_3, led3BufferForDevice.toString())
+ putString(Constants.BUFFER_VALUE_4, led4BufferForDevice.toString())
+ apply()
}
- if (!validationError) {
- activity?.runOnUiThread {
- binding.btnSubmit.visibility = View.VISIBLE
- binding.btnSubmit.isEnabled = true
- binding.btnSubmit.isClickable = true
- binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
- }
+ }
+
+ if (!validationError) {
+ activity?.runOnUiThread {
+ binding.btnSubmit.visibility = View.VISIBLE
+ binding.btnSubmit.isEnabled = true
+ binding.btnSubmit.isClickable = true
+ binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
}
}
} catch (e: Exception) {
@@ -490,7 +539,7 @@ class HemoCubeFragment : Fragment() {
}
}
- private fun findResult(calculatedRatio: Double?): String {
+ fun findResult(calculatedRatio: Double?): String {
try {
hemoCubeViewModel.messages.postValue("result classification")
if (calculatedRatio != null) {
@@ -519,6 +568,31 @@ class HemoCubeFragment : Fragment() {
return "INVALID"
}
+ private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
+ try {
+ hemoCubeViewModel.messages.postValue("result classification")
+ if (predictedDenovixRatio != null) {
+ if (predictedDenovixRatio in 0.0..0.16)
+ return "Normal"
+ if (predictedDenovixRatio in 0.16..0.165)
+ return "Negative Borderline"
+ if (predictedDenovixRatio in 0.165..0.235)
+ return "Sickle Cell Trait"
+ if (predictedDenovixRatio in 0.235..0.24)
+ return "Positive Borderline"
+ if (predictedDenovixRatio in 0.24..1.0)
+ return "Sickle Cell Disease"
+ } else {
+ return "INVALID"
+ }
+ } catch (e: Exception) {
+ showToast("error while performing classification")
+ Firebase.crashlytics.recordException(e)
+ return "ERROR"
+ }
+ return "INVALID"
+ }
+
private fun showToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
index 4a7dd6b..b4b4305 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
@@ -1,7 +1,10 @@
package com.example.hpostesting.presentation.hemocube
import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
import android.content.SharedPreferences
+import android.os.BatteryManager
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
@@ -15,8 +18,10 @@ import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.BufferCheckData
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
+import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository
+import com.example.hpostesting.data.repository.Repository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
@@ -27,7 +32,7 @@ import javax.inject.Inject
@HiltViewModel
class HemoCubeViewModel @Inject constructor(
private val hemoCubeDao: HemoCubeDao,
- private val repository: DatabaseRepository,
+ private val repository: Repository,
context: Context,
) : ViewModel() {
var isServiceConnected = false
@@ -46,6 +51,11 @@ class HemoCubeViewModel @Inject constructor(
get() = _networkStatusLiveData
val fireBaseUpload = MutableLiveData()
val fireBaseBulkUpload = MutableLiveData()
+
+ private val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
+ context.registerReceiver(null, ifilter)
+ }
+
fun uploadHemoCubeResultToDatabase(isOnline: Boolean, testStatus: Boolean, kitSerial: String?) =
viewModelScope.launch {
if (kitSerial != null) {
@@ -105,10 +115,21 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.led2Average = DataHolder.hemoCubeTestData?.led2Average
testDetails?.led3Average = DataHolder.hemoCubeTestData?.led3Average
testDetails?.led4Average = DataHolder.hemoCubeTestData?.led4Average
+ testDetails?.abs1 = DataHolder.hemoCubeTestData?.abs1
+ testDetails?.abs2 = DataHolder.hemoCubeTestData?.abs2
+ testDetails?.abs3 = DataHolder.hemoCubeTestData?.abs3
+ testDetails?.abs4 = DataHolder.hemoCubeTestData?.abs4
testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio
+ testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
+ testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
+ testDetails?.batteryLevel = DataHolder.hemoCubeTestData?.batteryLevel.toString()
+ testDetails?.batteryCapacity = DataHolder.hemoCubeTestData?.batteryCapacity.toString()
+ testDetails?.batteryMaxCapacity = DataHolder.hemoCubeTestData?.batteryMaxCapacity.toString()
+ testDetails?.batteryTemperature = DataHolder.hemoCubeTestData?.batteryTemperature.toString()
+ testDetails?.batteryVoltage = DataHolder.hemoCubeTestData?.batteryVoltage.toString()
}
private fun addResultTestToDb() {
@@ -189,7 +210,56 @@ class HemoCubeViewModel @Inject constructor(
hemoCubeDao.updateFieldById(id = userId, true)
}
+ fun addUser(userData: HemoCubeTestData) = viewModelScope.launch {
+ hemoCubeDao.insertAll(userData)
+ }
+
fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId)
}
+
+ fun getBatteryLevel(): Float? {
+ val batteryPct: Float? = batteryStatus?.let { intent ->
+ val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
+ val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
+ level * 100 / scale.toFloat()
+ }
+
+ return batteryPct
+ }
+
+ fun getBatteryTemperature(): Float? {
+ val batteryTemp: Float? = batteryStatus?.let { intent ->
+ val temperature = intent?.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0) ?: 0
+ temperature.toFloat() / 10
+ }
+
+ return batteryTemp
+ }
+
+ fun getBatteryVoltage(context: Context): Float {
+ val batteryIntent = context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
+ val voltage = batteryIntent?.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0) ?: 0
+
+ // milli-volts to volts
+ return voltage.toFloat() / 1000
+ }
+
+ fun getBatteryCapacity(context: Context): Int {
+ val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
+ val currentCapacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
+
+ return currentCapacity
+ }
+
+ fun getBatteryMaxCapacity(context: Context): Float {
+ val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
+ val designCapacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+ val currentCapacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
+
+ // Calculate the estimated maximum battery capacity in mAh
+ val maxCapacity = currentCapacity.toFloat() / designCapacity.toFloat() * 100
+
+ return maxCapacity
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 9aa32ec..87f4636 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -22,7 +22,7 @@
android:id="@+id/internetNotAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:visibility="gone"
+ android:visibility="visible"
android:padding="24dp">
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@+id/til_blood_group" />
+
+
@@ -74,7 +106,7 @@
android:id="@+id/internetAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:visibility="visible"
+ android:visibility="gone"
android:padding="24dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5f1e0da..0d6d018 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -183,10 +183,10 @@
User List
User ID
Aadhar ID
- Internet not available, please enter the user ID manually
- User ID should be 18 digits
- Upload DB Registration
- Do you want to upload the local DB Registration to the cloud?
+ Internet not available, please enter the user ID and blood group manually
+ User ID should be 18 digits and please select the blood group
+ Upload DB Tests
+ Do you want to upload the local DB tests to the cloud?
Upload
Cancel
Upload done successfully
diff --git a/app/src/test/java/com/example/hpostesting/HemoCubeViewModelTest.kt b/app/src/test/java/com/example/hpostesting/HemoCubeViewModelTest.kt
new file mode 100644
index 0000000..012036e
--- /dev/null
+++ b/app/src/test/java/com/example/hpostesting/HemoCubeViewModelTest.kt
@@ -0,0 +1,127 @@
+package com.example.hpostesting
+
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import androidx.lifecycle.LiveData
+import com.example.hpostesting.data.dao.HemoCubeDao
+import com.example.hpostesting.data.model.Response
+import com.example.hpostesting.data.model.patient.HemoCubeTestData
+import com.example.hpostesting.data.model.patient.toHemoCubeTestData
+import com.example.hpostesting.data.repository.DatabaseRepository
+import com.example.hpostesting.data.repository.Repository
+import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
+import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
+import com.example.hpostesting.presentation.hemocube.HemocubeActivity
+import com.example.hpostesting.util.TestCoroutineRule
+import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@ExperimentalCoroutinesApi
+class HemoCubeViewModelTest {
+
+ // Add rule for testing LiveData
+ @get:Rule
+ val rule = InstantTaskExecutorRule()
+
+ // Add rule for testing coroutines
+ @get:Rule
+ val coroutineRule = TestCoroutineRule()
+
+ // Mock dependencies
+ @Mock
+ lateinit var hemoCubeDao: HemoCubeDao
+
+ @Mock
+ lateinit var repository: Repository
+
+ // Mock context
+ @Mock
+ lateinit var context: Context
+
+ // Mock LiveData for testing
+ @Mock
+ lateinit var networkStatusLiveData: LiveData
+
+ // Initialize the ViewModel
+ lateinit var viewModel: HemoCubeViewModel
+
+ private lateinit var hemoCubeFragment: HemoCubeFragment
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+// viewModel = HemoCubeViewModel(hemoCubeDao, repository, context)
+ hemoCubeFragment = HemoCubeFragment()
+ }
+
+ @Test
+ fun `uploadHemoCubeResultToDatabase with online status should call addResultTestToDb`() =
+ coroutineRule.runBlockingTest {
+ // Mock data and setup
+ val isOnline = true
+ val testStatus = true
+ val kitSerial = "12345"
+
+ // Mock the necessary methods
+ `when`(repository.addTestToDatabase(viewModel.testDetails!!))
+ .thenReturn(Response.Success("Success"))
+
+ // Call the function to be tested
+ viewModel.uploadHemoCubeResultToDatabase(isOnline, testStatus, kitSerial)
+
+ // Verify that addResultTestToDb is called
+ advanceUntilIdle()
+ assertEquals("Local", viewModel.fireBaseUpload.value)
+ }
+
+ // Similar tests can be written for other methods in HemoCubeViewModel
+
+ @Mock
+ private lateinit var mockSharedPreferences: SharedPreferences
+
+ @Mock
+ private lateinit var mockActivity: HemocubeActivity // Replace with your actual Activity class
+
+ @Mock
+ private lateinit var mockBinding: FragmentHemoCubeReferenceBinding // Replace with your actual Binding class
+
+ @Test
+ fun `findResult with valid input`() {
+ // Arrange
+ val validString = "valid string"
+ val fullReadOutput = "full read output"
+ `when`(mockSharedPreferences.getString(anyString(), anyString())).thenReturn("dummy_value")
+ `when`(mockActivity.runOnUiThread(any())).thenAnswer {
+ val runnable = it.getArgument(0, Runnable::class.java)
+ runnable.run()
+ }
+
+ // Act
+ val result = hemoCubeFragment.findResult(calculatedRatio = 0.06)
+
+ // Assert
+ // Add appropriate assertions based on the behavior you expect
+// verify(mockSharedPreferences).edit()
+// verify(mockBinding).btnSubmit.visibility = View.VISIBLE
+// verify(mockBinding).btnSubmit.isEnabled = true
+ // Add more verifications as needed
+
+ assertEquals("Normal", result)
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt b/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt
index 72ec827..2be9212 100644
--- a/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt
+++ b/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt
@@ -11,91 +11,91 @@ import java.math.RoundingMode
import java.text.DecimalFormat
class TestRightViewModelTest {
- private val viewModel = TestRightViewModel()
- private val data = InputData()
-
- @Test
- fun test_mapDeviceConstants() {
- viewModel.mapDeviceConstants(data.inputRead)
- assertEquals("0", DataHolder.deviceConstant!!.a)
- assertEquals("1.69989422e-06", DataHolder.deviceConstant!!.b)
- assertEquals("1.60642711e-01", DataHolder.deviceConstant!!.c)
- assertEquals("3.85754470e+02", DataHolder.deviceConstant!!.d)
- }
-
- @Test
- fun test_mapPixelNumberToWavelength() {
- viewModel.mapDeviceConstants(data.inputRead)
- viewModel.mapPixelNumberToWavelength()
-
- val outputList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
-
- assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, DataHolder.wavelengthToPixelArray.size)
- assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, outputList.size)
-
- val df = DecimalFormat("#.###")
- df.roundingMode = RoundingMode.FLOOR
-
- for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
- assertEquals(df.format(outputList[i]), df.format(DataHolder.wavelengthToPixelArray[i]))
- }
-
- }
-
+// private val viewModel = TestRightViewModel()
+// private val data = InputData()
+//
// @Test
-// fun test_mapIntensityValues() {
-// val inputReference = TestDataGenerator().getInputReferenceMapIntensityValues()
-// val inputSample = TestDataGenerator().getInputSampleMapIntensityValues()
-//
-// viewModel.mapIntensityValues(inputReference, true)
-// viewModel.mapIntensityValues(inputSample, false)
-//
-// val outputReference = TestDataGenerator().getOutputReferenceMapIntensityValues()
-// val outputSample = TestDataGenerator().getOutputSampleMapIntensityValues()
-//
-// assertEquals(outputReference, DataHolder.intensityReferenceArray)
-// assertEquals(outputSample, viewModel.intensitySampleArray)
+// fun test_mapDeviceConstants() {
+// viewModel.mapDeviceConstants(data.inputRead)
+// assertEquals("0", DataHolder.deviceConstant!!.a)
+// assertEquals("1.69989422e-06", DataHolder.deviceConstant!!.b)
+// assertEquals("1.60642711e-01", DataHolder.deviceConstant!!.c)
+// assertEquals("3.85754470e+02", DataHolder.deviceConstant!!.d)
+// }
+//
+// @Test
+// fun test_mapPixelNumberToWavelength() {
+// viewModel.mapDeviceConstants(data.inputRead)
+// viewModel.mapPixelNumberToWavelength()
+//
+// val outputList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
+//
+// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, DataHolder.wavelengthToPixelArray.size)
+// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, outputList.size)
+//
+// val df = DecimalFormat("#.###")
+// df.roundingMode = RoundingMode.FLOOR
+//
+// for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
+// assertEquals(df.format(outputList[i]), df.format(DataHolder.wavelengthToPixelArray[i]))
+// }
+//
+// }
+//
+//// @Test
+//// fun test_mapIntensityValues() {
+//// val inputReference = TestDataGenerator().getInputReferenceMapIntensityValues()
+//// val inputSample = TestDataGenerator().getInputSampleMapIntensityValues()
+////
+//// viewModel.mapIntensityValues(inputReference, true)
+//// viewModel.mapIntensityValues(inputSample, false)
+////
+//// val outputReference = TestDataGenerator().getOutputReferenceMapIntensityValues()
+//// val outputSample = TestDataGenerator().getOutputSampleMapIntensityValues()
+////
+//// assertEquals(outputReference, DataHolder.intensityReferenceArray)
+//// assertEquals(outputSample, viewModel.intensitySampleArray)
+//// }
+//
+// @Test
+// fun test_mapWavelengthToAbsorbance() {
+//
+// viewModel.mapDeviceConstants(data.inputRead)
+// viewModel.mapPixelNumberToWavelength()
+// viewModel.mapIntensityValues(TestDataGenerator().getInputReferenceMapIntensityValues(), true)
+// viewModel.mapIntensityValues(TestDataGenerator().getInputSampleMapIntensityValues(), false)
+// viewModel.patientDetails = PatientData("Surya", 2, "Male", TestRightResultType.UNDEFINED)
+// viewModel.mapWavelengthToAbsorbance()
+//
+// val wavelengthList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
+// val absorbanceList = TestDataGenerator().getOutputMapWavelengthToAbsorbance()
+//
+// val df = DecimalFormat("#.###")
+// df.roundingMode = RoundingMode.FLOOR
+//
+// assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, viewModel.wavelengthToAbsorbance.size)
+// for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
+// assertEquals(df.format(wavelengthList[i]), df.format(viewModel.wavelengthToAbsorbance[i][0]))
+// assertEquals(df.format(absorbanceList[i]), df.format(viewModel.wavelengthToAbsorbance[i][1]))
+// }
+// }
+//
+//
+// @Test
+// fun testRightViewModel_calculateDataForCSV() {
+//
+// viewModel.mapDeviceConstants(data.inputRead)
+// viewModel.mapPixelNumberToWavelength()
+// viewModel.mapIntensityValues(data.printForReference, true)
+// viewModel.mapIntensityValues(data.printForSample, false)
+//// viewModel.patientDetails = PatientData("Surya", 2, "Male", null)
+//// viewModel.calculateResults()
+// viewModel.mapWavelengthToAbsorbance()
+//
+// for (each in viewModel.wavelengthToAbsorbance){
+// println(each[0].toString() + " -> " + each[1])
+// }
// }
-
- @Test
- fun test_mapWavelengthToAbsorbance() {
-
- viewModel.mapDeviceConstants(data.inputRead)
- viewModel.mapPixelNumberToWavelength()
- viewModel.mapIntensityValues(TestDataGenerator().getInputReferenceMapIntensityValues(), true)
- viewModel.mapIntensityValues(TestDataGenerator().getInputSampleMapIntensityValues(), false)
- viewModel.patientDetails = PatientData("Surya", 2, "Male", TestRightResultType.UNDEFINED)
- viewModel.mapWavelengthToAbsorbance()
-
- val wavelengthList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
- val absorbanceList = TestDataGenerator().getOutputMapWavelengthToAbsorbance()
-
- val df = DecimalFormat("#.###")
- df.roundingMode = RoundingMode.FLOOR
-
- assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, viewModel.wavelengthToAbsorbance.size)
- for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
- assertEquals(df.format(wavelengthList[i]), df.format(viewModel.wavelengthToAbsorbance[i][0]))
- assertEquals(df.format(absorbanceList[i]), df.format(viewModel.wavelengthToAbsorbance[i][1]))
- }
- }
-
-
- @Test
- fun testRightViewModel_calculateDataForCSV() {
-
- viewModel.mapDeviceConstants(data.inputRead)
- viewModel.mapPixelNumberToWavelength()
- viewModel.mapIntensityValues(data.printForReference, true)
- viewModel.mapIntensityValues(data.printForSample, false)
-// viewModel.patientDetails = PatientData("Surya", 2, "Male", null)
-// viewModel.calculateResults()
- viewModel.mapWavelengthToAbsorbance()
-
- for (each in viewModel.wavelengthToAbsorbance){
- println(each[0].toString() + " -> " + each[1])
- }
- }
}
\ No newline at end of file
diff --git a/app/src/test/java/com/example/hpostesting/util/TestCoroutineRule.kt b/app/src/test/java/com/example/hpostesting/util/TestCoroutineRule.kt
new file mode 100644
index 0000000..cb20d2c
--- /dev/null
+++ b/app/src/test/java/com/example/hpostesting/util/TestCoroutineRule.kt
@@ -0,0 +1,28 @@
+package com.example.hpostesting.util
+
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestCoroutineDispatcher
+import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.setMain
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+
+@ExperimentalCoroutinesApi
+class TestCoroutineRule : TestWatcher(), TestCoroutineScope by TestCoroutineScope() {
+
+ private val testCoroutineDispatcher = TestCoroutineDispatcher()
+
+ override fun starting(description: Description?) {
+ super.starting(description)
+ Dispatchers.setMain(testCoroutineDispatcher)
+ }
+
+ override fun finished(description: Description?) {
+ super.finished(description)
+ Dispatchers.resetMain()
+ cleanupTestCoroutines()
+ }
+}
\ No newline at end of file