Compare commits

..

12 Commits

Author SHA1 Message Date
Mariya
41798aa37b Digital Card button removed 2023-12-14 13:07:15 +05:30
Mariya
d6b3df25f8 gradle version changed 2023-12-13 20:53:34 +05:30
Mariya
0d7e8b0cd0 Merge remote-tracking branch 'origin/preprod' into preprod 2023-12-13 18:57:03 +05:30
Mariya
3c8570c46b gradle version changed 2023-12-13 18:56:40 +05:30
Pritimay Sarkar
96f9d4d6da coeffs for dev4 2023-12-13 18:55:41 +05:30
Mariya
e7505077ce Merge remote-tracking branch 'origin/preprod' into preprod
# Conflicts:
#	app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
2023-12-12 12:21:52 +05:30
Kaif
41e30cf178 Incremented the version number for giving testing release 2023-12-08 13:59:07 +05:30
Pritimay Sarkar
a34c095fde Merge remote-tracking branch 'origin/Feature_Develop_the_feature_to_shift_between_multiple_languages_in_testing_app' into preprod 2023-12-08 13:55:07 +05:30
Mariya
a3a5c0d6fb pending strings added 2023-12-04 15:49:39 +05:30
Kaif
fb5e6f3b49 Fixed string error 2023-12-01 16:22:13 +05:30
Kaif
8a22b44496 Added app version 2023-12-01 16:10:15 +05:30
Kaif
10d822c5d6 Kannada and Hindi language support added 2023-12-01 15:55:49 +05:30
24 changed files with 691 additions and 475 deletions

View File

@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting" applicationId "in.sminnovations.hpostesting"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 44 versionCode 48
versionName "2.1.44" versionName "2.1.48"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -133,4 +133,6 @@ dependencies {
implementation "com.squareup.retrofit2:retrofit:2.9.0" implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0" implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "androidx.preference:preference-ktx:1.2.1"
} }

View File

@@ -91,6 +91,18 @@ object Constants {
listOf(0.1964, 0.011565), // LED3, 555nm listOf(0.1964, 0.011565), // LED3, 555nm
listOf(1.0, 0.0) // LED4 listOf(1.0, 0.0) // LED4
), ),
"HCV-000-3003" to listOf(
listOf(0.723142, -0.09135), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.1964, 0.011565), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
"HCV-000-3004" to listOf(
listOf(1.6837, -1.1417), // LED1, 435nm
listOf(0.581462456, -0.58502), // LED2, 415nm
listOf(0.2241, -0.0106), // LED3, 555nm
listOf(1.0, 0.0) // LED4
),
) )
const val INCUBATION_TIME_MIN = 0 const val INCUBATION_TIME_MIN = 0
@@ -108,15 +120,18 @@ object Constants {
listOf(24500, 26250), listOf(24500, 26250),
listOf(24500, 26250), listOf(24500, 26250),
listOf(24500, 26250), listOf(24500, 26250),
),
"HCV-000-3003" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
),
"HCV-000-3004" to listOf(
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
listOf(24500, 26250),
) )
) )
val COEFFICIENTS: Map<String, List<List<Double>>> = mapOf(
"HC-V1-005" to listOf(
listOf(1.5,0.0),
listOf(0.0,0.0)
)
)
} }

View File

@@ -0,0 +1,30 @@
package com.example.hpostesting.data.constant
import android.content.Context
import android.content.SharedPreferences
import java.util.Locale
object LanguageManager {
private const val LANGUAGE_PREF_KEY = "language_pref"
fun setLocale(context: Context, languageCode: String) {
val locale = Locale(languageCode)
Locale.setDefault(locale)
val resources = context.resources
val configuration = resources.configuration
configuration.setLocale(locale)
context.createConfigurationContext(configuration)
}
fun persistLanguagePreference(context: Context, languageCode: String) {
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
prefs.edit().putString(LANGUAGE_PREF_KEY, languageCode).apply()
}
fun getSavedLanguage(context: Context): String {
val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
return prefs.getString(LANGUAGE_PREF_KEY, "en") ?: "en"
}
}

View File

@@ -11,6 +11,7 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemocubeActivity import com.example.hpostesting.presentation.hemocube.HemocubeActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity import com.example.hpostesting.presentation.testRight.TestRightActivity
@@ -44,6 +45,12 @@ class KitScanActivity : AppCompatActivity() {
binding.nameEditText.setText(contents) binding.nameEditText.setText(contents)
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View File

@@ -17,6 +17,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType import com.example.hpostesting.data.model.test.TestType
import com.google.android.gms.location.* import com.google.android.gms.location.*
@@ -44,6 +45,12 @@ class MainActivity : AppCompatActivity() {
} }
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)

View File

@@ -2,6 +2,7 @@ package com.example.hpostesting.presentation
import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.example.hpostesting.presentation.dashboard.DashboardActivity
import android.Manifest import android.Manifest
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
@@ -14,6 +15,7 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.util.MyUtils import com.example.hpostesting.util.MyUtils
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
@@ -32,6 +34,12 @@ class SplashActivity : AppCompatActivity() {
private var allPermissionsGranted = false private var allPermissionsGranted = false
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivitySplashBinding.inflate(layoutInflater) binding = ActivitySplashBinding.inflate(layoutInflater)

View File

@@ -1,8 +1,6 @@
package com.example.hpostesting.presentation.adapter package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.res.Resources
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -28,9 +26,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() { RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) : inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root)
}
private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() { private val differCallback = object : DiffUtil.ItemCallback<HemoCubeTestData>() {
override fun areItemsTheSame( override fun areItemsTheSame(
@@ -58,58 +54,61 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
return differ.currentList.size return differ.currentList.size
} }
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) { override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) {
val userList = differ.currentList[position] val userList = differ.currentList[position]
holder.binding.apply { holder.binding.apply {
userID.text = "User ID: ${userList._id}" userID.text = "User ID: ${userList._id}"
bloodGroup.text = "Blood group: ${userList.bloodGroup}" bloodGroup.text = "Blood group: ${userList.bloodGroup}"
time.text = "Time: ${isBetween15And30Minutes(userList.incubationTime)} \n Started at: ${ time.text = "Time: ${userList.incubationTime}"
SimpleDateFormat("HH:mm:ss").format(
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).parse(userList.incubationTime)!!
)
}"
if (userList.testStatus!!) {
teststatus.text = view.context.getString(R.string.test_concluded)
} else {
teststatus.text = view.context.getString(R.string.test_pending)
}
userCard.setOnClickListener { userCard.setOnClickListener {
if (batLevel < 40) { if (batLevel < 40) {
showWarningToast(R.string.low_battery_warning) Toast.makeText(
} else { view.context,
if (userList.testStatus != null) { context?.getString(R.string.low_battery_warning),
if (userList.testStatus!!) { Toast.LENGTH_SHORT
showWarningToast(R.string.test_already_conducted) ).show()
} else { return@setOnClickListener
if (userList.incubationTime != "") { }
val incubationTimeDiff = isBetween15And30Minutes(userList.incubationTime) if (userList.testStatus != null) {
if (incubationTimeDiff < 15) { if (userList.testStatus!!) {
showWarningToast(R.string.incubation_not_completed) Toast.makeText(
} else if (incubationTimeDiff > 30) { view.context,
showWarningToast(R.string.incubation_crossed_30_minutes) context?.getString(R.string.test_already_conducted),
} else { Toast.LENGTH_SHORT
DataHolder.selectedTest = UserData( ).show()
_id = userList._id, } else {
bloodGroup = userList.bloodGroup, if (userList.incubationTime != "") {
incubationTime = userList.incubationTime if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
) Toast.makeText(
view.findNavController() view.context,
.navigate(R.id.action_nav_home_to_mainActivity) context?.getString(R.string.incubation_not_completed),
} Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else { } else {
showWarningToast(R.string.incubation_not_started) 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,
context?.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
} }
} }
} }
} }
} }
} }
@@ -123,25 +122,4 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
return diffMillis / (60 * 1000) return diffMillis / (60 * 1000)
} }
private fun showWarningToast(resId: Int) {
val contextToUse = view.context ?: return
val message = try {
contextToUse.getString(resId)
} catch (e: Resources.NotFoundException) {
"Resource not found for ID: $resId"
}
Toast.makeText(
contextToUse,
message,
Toast.LENGTH_SHORT
).show()
}
} }

View File

@@ -94,13 +94,13 @@ class UserListAdapter(
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
.setView(dialogView) .setView(dialogView)
.setTitle("Add Blood Group") .setTitle(R.string.blood_group)
val etBloodGroup = dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group) val etBloodGroup = dialogView.findViewById<AutoCompleteTextView>(R.id.et_blood_group)
builder.setPositiveButton("OK") { dialog, which -> builder.setPositiveButton(R.string.ok) { dialog, which ->
val bloodGroup = etBloodGroup.text.toString() val bloodGroup = etBloodGroup.text.toString()
if (bloodGroup.equals("Select Blood Group") || bloodGroup.isNullOrBlank()) { if (bloodGroup.equals("Select Blood Group") ||bloodGroup.equals("ರಕ್ತ ಗುಂಪು ಆಯ್ಕೆಮಾಡಿ") || bloodGroup.isNullOrBlank()) {
if (view != null) { if (view != null) {
etBloodGroup.error =view.context.getString(R.string.blood_group_error) etBloodGroup.error =view.context.getString(R.string.blood_group_error)
} }
@@ -166,7 +166,7 @@ class UserListAdapter(
// Handle the selected blood group here // Handle the selected blood group here
} }
builder.setNegativeButton("Cancel") { dialog, which -> builder.setNegativeButton(R.string.cancel) { dialog, which ->
dialog.dismiss() dialog.dismiss()
} }

View File

@@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
@@ -73,6 +74,12 @@ open class HemocubeBufferCheckActivity : AppCompatActivity() {
} }
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityHemocubeBinding.inflate(layoutInflater) binding = ActivityHemocubeBinding.inflate(layoutInflater)

View File

@@ -1,5 +1,6 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.widget.Toast import android.widget.Toast
@@ -10,6 +11,7 @@ import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.constant.LanguageManager
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.google.firebase.appdistribution.FirebaseAppDistribution import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException import com.google.firebase.appdistribution.FirebaseAppDistributionException
@@ -24,6 +26,12 @@ class DashboardActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding private lateinit var binding: ActivityDashboardBinding
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View File

@@ -138,7 +138,6 @@ class HomeFragment : Fragment() {
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString() val userId = binding.userId.text.toString()
val bloodGroup = binding.etBloodGroup.text val bloodGroup = binding.etBloodGroup.text
if (userId.length >= 18 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) { if (userId.length >= 18 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) {
hemoCubeViewModel.addUser( hemoCubeViewModel.addUser(
HemoCubeTestData( HemoCubeTestData(
@@ -163,10 +162,10 @@ class HomeFragment : Fragment() {
val dateFormat = SimpleDateFormat("yyyy-MM-dd") val dateFormat = SimpleDateFormat("yyyy-MM-dd")
val currentDate = Date() val currentDate = Date()
val formattedDate = dateFormat.format(currentDate) val formattedDate = dateFormat.format(currentDate)
// val query = Firebase.firestore.collection("patientData") val query = Firebase.firestore.collection("patientData")
// .whereGreaterThanOrEqualTo("createdAt", formattedDate) .whereGreaterThanOrEqualTo("createdAt", formattedDate)
// .orderBy("createdAt", Query.Direction.DESCENDING) .orderBy("createdAt", Query.Direction.DESCENDING)
val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false) // val query = Firebase.firestore.collection("patientData").whereEqualTo("testStatus", false)
query.get().addOnSuccessListener { query.get().addOnSuccessListener {
if (it.documents.isEmpty()) { if (it.documents.isEmpty()) {
binding.pendingTest.visibility = View.VISIBLE binding.pendingTest.visibility = View.VISIBLE

View File

@@ -1,47 +1,66 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.widget.Toast
import android.view.View import androidx.preference.ListPreference
import android.view.ViewGroup import androidx.preference.Preference
import androidx.fragment.app.Fragment import androidx.preference.PreferenceFragmentCompat
import androidx.lifecycle.ViewModelProvider import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.dashboard.ui.slideshow.SlideshowViewModel import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding private var isLanguageChanged = false
class SlideshowFragment : Fragment() { class SlideshowFragment : PreferenceFragmentCompat() {
private var _binding: FragmentSlideshowBinding? = null override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
// This property is only valid between onCreateView and val languagePreference = ListPreference(requireContext())
// onDestroyView. languagePreference.key = "language_preference"
private val binding get() = _binding!! languagePreference.title = getString(R.string.app_language)
languagePreference.summary = getString(R.string.select_language)
languagePreference.entries = arrayOf("English", "Kannada", "Hindi")
languagePreference.entryValues = arrayOf("en", "kn", "hi")
languagePreference.setDefaultValue("en")
override fun onCreateView( languagePreference.onPreferenceChangeListener =
inflater: LayoutInflater, Preference.OnPreferenceChangeListener { _, newValue ->
container: ViewGroup?, val languageCode = newValue as String
savedInstanceState: Bundle?, updateLanguage(requireContext(), languageCode)
): View { true
val slideshowViewModel = }
ViewModelProvider(this).get(SlideshowViewModel::class.java)
_binding = FragmentSlideshowBinding.inflate(inflater, container, false) preferenceScreen.addPreference(languagePreference)
val root: View = binding.root setPreferenceScreen(preferenceScreen)
val pInfo = requireActivity().packageManager.getPackageInfo( // App Version Preference
requireActivity().packageName, 0 val appVersionPreference = Preference(requireContext())
) appVersionPreference.title = "App Version"
val version = pInfo.versionName appVersionPreference.summary = getAppVersion(requireContext())
binding.textSlideshow.text = version
// val textView: TextView = binding.textSlideshow preferenceScreen.addPreference(languagePreference)
// slideshowViewModel.text.observe(viewLifecycleOwner) { preferenceScreen.addPreference(appVersionPreference)
// textView.text = it setPreferenceScreen(preferenceScreen)
// }
return root if (isLanguageChanged) {
Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show()
}
} }
override fun onDestroyView() { private fun updateLanguage(context: Context, languageCode: String) {
super.onDestroyView() LanguageManager.persistLanguagePreference(context, languageCode)
_binding = null LanguageManager.setLocale(context, languageCode)
requireActivity().recreate() // Recreate activity to apply language changes
isLanguageChanged = true
}
private fun getAppVersion(context: Context): String {
return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
pInfo.versionName
} catch (e: PackageManager.NameNotFoundException) {
"N/A"
}
} }
} }

View File

@@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.hemocube.HemoCubeFragment import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
@@ -77,6 +78,12 @@ class DiagnosticsActivity : AppCompatActivity() {
} }
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityDiagnosticsBinding.inflate(layoutInflater) binding = ActivityDiagnosticsBinding.inflate(layoutInflater)

View File

@@ -14,6 +14,7 @@ import android.os.IBinder
import android.view.Menu import android.view.Menu
import androidx.activity.viewModels import androidx.activity.viewModels
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
@@ -21,8 +22,15 @@ import `in`.sminnovations.hpostesting.databinding.ActivityDigitalCardBinding
import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding import `in`.sminnovations.hpostesting.databinding.ActivityHemocubeBinding
class DigitalCardActivity : AppCompatActivity() { class DigitalCardActivity : AppCompatActivity() {
private lateinit var binding: ActivityDigitalCardBinding private lateinit var binding: ActivityDigitalCardBinding
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityDigitalCardBinding.inflate(layoutInflater) binding = ActivityDigitalCardBinding.inflate(layoutInflater)

View File

@@ -5,7 +5,6 @@ import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -34,16 +33,30 @@ class HemoCubeFragment : Fragment() {
private lateinit var binding: FragmentHemoCubeReferenceBinding private lateinit var binding: FragmentHemoCubeReferenceBinding
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData()
private var isOnline = false private var isOnline = false
private var currentDeviceData: DeviceData? = null private var currentDeviceData: DeviceData? = null
private var resultData: String = "" private var resultData: String = ""
private var deviceSerialNo: String = ""
private var coefficient: String? = ""
private var isUsingExistingBuffer = false private var isUsingExistingBuffer = false
private var isTestOngoing = false private var isTestOngoing = false
private var startListening = MutableLiveData<Boolean>(false) private var startListening = MutableLiveData<Boolean>(false)
val testingTrace = Firebase.performance.newTrace("testing_trace") private val testingTrace = Firebase.performance.newTrace("testing_trace")
private var led1BufferForDevice = 0.0
private var led2BufferForDevice = 0.0
private var led3BufferForDevice = 0.0
private var led4BufferForDevice = 0.0
private var led1SampleForDevice = 0.0
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 = ""
private var allErrorMessages = ""
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
@@ -57,8 +70,9 @@ class HemoCubeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initViews() initViews()
listenToHemoCube()
getDeviceInfo()
observeViewModel() observeViewModel()
checkAndStartProcess()
} }
private fun initViews() { private fun initViews() {
@@ -70,11 +84,6 @@ class HemoCubeFragment : Fragment() {
isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "") isOnline, true, sharedPreferences.getString(Constants.KIT_NUMBER, "")
) )
} }
if (isTestOngoing) {
// binding.btnKit.visibility = View.GONE
// binding.btnKit.isEnabled = false
// binding.btnKit.isClickable = false
}
binding.tvTitle2.visibility = View.GONE binding.tvTitle2.visibility = View.GONE
binding.etAbhaId.visibility = View.GONE binding.etAbhaId.visibility = View.GONE
@@ -83,27 +92,57 @@ class HemoCubeFragment : Fragment() {
binding.btnGo.visibility = View.GONE binding.btnGo.visibility = View.GONE
// binding.btnSubmit.isEnabled = false // binding.btnSubmit.isEnabled = false
// binding.btnSubmit.isClickable = false // binding.btnSubmit.isClickable = false
binding.btnPlacebuffer.visibility = View.GONE
binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}" binding.tvName.text = "Name: ${testDetails?.name}\n ID: ${testDetails?._id}"
Log.e("nametext", binding.tvName.text.toString()) binding.tvSubtitle4.text = "Config"
binding.btnSamplestart.setOnClickListener {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Sample Started"
}
startSampleProcess()
it.visibility = View.GONE
}
binding.btnPlacebuffer.setOnClickListener {
if (isBufferValueAvailable()) {
showBufferAlertDialog()
} else {
activity?.runOnUiThread {
binding.tvSubtitle4.visibility = View.VISIBLE
// binding.tvSubtitle4.text = "Buffer Started"
}
checkAndStartProcess()
it.visibility = View.GONE
}
}
} }
private fun observeViewModel() { private fun observeViewModel() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
showToast("Test Results Uploaded Successfully") showToast(R.string.test_upload)
val i = Intent(
requireContext().applicationContext, DashboardActivity::class.java activity?.runOnUiThread {
) binding.btnSubmit.visibility = View.GONE
startActivity(i) val i = Intent(
(activity as HemocubeActivity).finish() requireContext().applicationContext, DashboardActivity::class.java
)
startActivity(i)
}
} }
if (result == "Local") { if (result == "Local") {
showToast("Internet not available, test details stored locally") showToast(R.string.internt_not_local)
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) startActivity(Intent(requireActivity(), DashboardActivity::class.java))
} }
if (result == "Error") { if (result == "Error") {
showToast("Error uploading data, test details stored locally") showToast(R.string.error_local)
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) startActivity(Intent(requireActivity(), DashboardActivity::class.java))
} }
@@ -118,25 +157,13 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable -> hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
apply { apply {
// if (isNetworkAvailable) { DataHolder.hemoCubeTestData?.let {
// Online mode currentDeviceData?.coefficients?.let { coefficients ->
DataHolder.hemoCubeTestData?.let { val coefficient1 = coefficients[0]
currentDeviceData?.coefficients?.let { coefficients -> val coefficient2 = coefficients[1]
val coefficient1 = coefficients[0] val result = coefficient1 * coefficient2
val coefficient2 = coefficients[1]
val result = coefficient1 * coefficient2
// Process result in online mode
}
} }
// } else { }
// // Offline mode
// val coefficient1 = Constants.COEFFICIENTS[deviceSerialNo]?.get(0)?.get(0).toString().toDoubleOrNull() ?: 0.0
// val coefficient2 = Constants.COEFFICIENTS[deviceSerialNo]?.get(1)?.get(0).toString().toDoubleOrNull() ?: 0.0
// val result = coefficient1 * coefficient2
//
// // Process result in offline mode
// }
isOnline = isNetworkAvailable isOnline = isNetworkAvailable
} }
} }
@@ -144,51 +171,48 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.messages.observe(viewLifecycleOwner) { hemoCubeViewModel.messages.observe(viewLifecycleOwner) {
binding.tvSubtitle4.text = it binding.tvSubtitle4.text = it
} }
// startListening.observe(viewLifecycleOwner) {
// if (it) {
// lifecycleScope.launch {
// delay(1000)
// if (binding.tvSubtitle4.text.toString().isEmpty()) {
// (activity as HemocubeActivity).reconnectDevice()
// if (isBufferValueAvailable()) {
// showBufferAlertDialog()
// } else {
// listenToHemoCube()
// startBufferProcess()
// }
// }
// }
// }
// }
} }
private fun checkAndStartProcess() { private fun checkAndStartProcess() {
if (isBufferValueAvailable()) { startBufferProcess()
showBufferAlertDialog()
} else {
listenToHemoCube()
startBufferProcess()
}
} }
private fun isBufferValueAvailable(): Boolean { private fun isBufferValueAvailable(): Boolean {
return if (sharedPreferences.getString( return try {
Constants.BUFFER_VALUE_1, "" if (sharedPreferences.getString(
) != "" && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") != "" Constants.BUFFER_VALUE_1, ""
) { ) != "" && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") != ""
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "") && sharedPreferences.getString(Constants.BUFFER_VALUE_3, "") != ""
?.toDouble()!! > 0.0 && sharedPreferences.getString(Constants.BUFFER_VALUE_2, "") && sharedPreferences.getString(Constants.BUFFER_VALUE_4, "") != ""
?.toDouble()!! > 0.0 ) {
} else { sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_2,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_3,
""
)
?.toDouble()!! > 0.0 && sharedPreferences.getString(
Constants.BUFFER_VALUE_4,
""
)
?.toDouble()!! > 0.0
} else {
false
}
} catch (e: Exception) {
showToast(R.string.error_exist)
false false
} }
} }
private fun showBufferAlertDialog() { private fun showBufferAlertDialog() {
val title = "WARNING" val title = "WARNING"
val message = "Do you want to continue with existing buffer?" val message = getString(R.string.do_exist)
val negativeText = getString(R.string.no) val negativeText = getString(R.string.no)
val positiveText = "Yes" val positiveText = getString(R.string.yes)
UIUtils.createAlertDialog(requireContext(), UIUtils.createAlertDialog(requireContext(),
title, title,
@@ -197,13 +221,15 @@ class HemoCubeFragment : Fragment() {
positiveText, positiveText,
object : MyDialogListener { object : MyDialogListener {
override fun onClickNegativeButton() { override fun onClickNegativeButton() {
listenToHemoCube()
startBufferProcess() startBufferProcess()
} }
override fun onClickPositiveButton() { override fun onClickPositiveButton() {
listenToHemoCube() activity?.runOnUiThread {
startSampleProcess() binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.tvSubtitle4.text = getString(R.string.place_sample)
}
isUsingExistingBuffer = true isUsingExistingBuffer = true
} }
}) })
@@ -234,47 +260,123 @@ class HemoCubeFragment : Fragment() {
} }
}) })
} catch (e: Exception) { } catch (e: Exception) {
showToast("test is going on") showToast(R.string.test_ongoing)
Firebase.crashlytics.recordException(e) Firebase.crashlytics.recordException(e)
} }
} }
private fun getDeviceInfo() {
hemoCubeViewModel.progressBar.postValue(true)
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.getDeviceId,
object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {
data?.let {
val stringData = String(it)
hemoCubeViewModel.messages.postValue(stringData)
binding.tvSubtitle4.text = stringData
}
}
override fun onUsbError(e: Exception?) {
hemoCubeViewModel.progressBar.postValue(false)
}
})
}
private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) { private fun handleUsbData(stringData: String, fullReadOutput: StringBuilder) {
if (stringData.contains("#")) { if (stringData.contains("#")) {
hemoCubeViewModel.messages.postValue(stringData)
isTestOngoing = true isTestOngoing = true
} }
resultData += stringData resultData += stringData
when { when {
stringData.contains("#Buffer Completed") -> showStartSampleDialog() stringData.contains("SN") -> {
stringData.contains("#Sample Completed") -> { val slData = stringData.split(" ")
if (slData.size > 1) {
val hardwareId = slData[1].trim()
deviceHardwareId = hardwareId
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId)
apply()
}
}
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE
}
hemoCubeViewModel.messages.postValue(getString(R.string.start))
}
stringData.contains("#BS") -> {
hemoCubeViewModel.messages.postValue(getString(R.string.buffer_started))
}
stringData.contains("#BC") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.buffer_completed)
binding.btnSamplestart.visibility = View.VISIBLE
}
}
stringData.contains("#SS") -> {
activity?.runOnUiThread {
binding.tvSubtitle4.text = getString(R.string.sample_started)
binding.btnSamplestart.visibility = View.GONE
}
}
stringData.contains("#SC") -> {
hemoCubeViewModel.messages.postValue(
getString(R.string.sample_completed) + "\n" + getString(R.string.gathering_data))
fetchResult() fetchResult()
testingTrace.stop() testingTrace.stop()
} }
stringData.contains("RESULT") || resultData.contains("REND") -> { resultData.contains("REND") -> {
var validString: String hemoCubeViewModel.messages.postValue(
val results: List<String> getString(R.string.data_collected_processing_data)
if (stringData.contains("RESULT")) { )
validString = isValidResult(stringData) val resultLines = resultData.split("\\s+(?=LB|LS)".toRegex())
if (validString.isEmpty()) { var bufferIntensity = resultLines[1].split(' ')[1].trim()
results = resultData.split("\n") led1BufferForDevice = if (isUsingExistingBuffer) {
validString = parseResult(results) sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()!!
}
} else { } else {
results = resultData.split("\n") bufferIntensity.toDoubleOrNull()!!
validString = parseResult(results)
} }
if (validString.isNotEmpty()) { bufferIntensity = resultLines[2].split(' ')[1].trim()
handleValidResult(validString, resultData) led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
} }
bufferIntensity = resultLines[3].split(' ')[1].trim()
led3BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_3, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
bufferIntensity = resultLines[4].split(' ')[1].trim()
led4BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_4, "")?.toDoubleOrNull()!!
} else {
bufferIntensity.toDoubleOrNull()!!
}
var sampleIntensity = resultLines[5].split(' ')[1].trim()
led1SampleForDevice = resultLines[5].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[6].split(' ')[1].trim()
led2SampleForDevice = resultLines[6].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[7].split(' ')[1].trim()
led3SampleForDevice = resultLines[7].split(' ')[1].trim().toDoubleOrNull()!!
sampleIntensity = resultLines[8].split(' ')[1].split('\r')[0].trim()
led4SampleForDevice =
resultLines[8].split(' ')[1].split('\r')[0].trim().toDoubleOrNull()!!
processResult()
} }
} }
} }
private fun showError() { private fun showError() {
activity?.runOnUiThread { activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(), UIUtils.createAlertDialog(requireContext(),
@@ -297,166 +399,248 @@ class HemoCubeFragment : Fragment() {
// If the test is ongoing, don't allow the back button action // If the test is ongoing, don't allow the back button action
// You can optionally show a message to the user indicating why the back button is disabled // You can optionally show a message to the user indicating why the back button is disabled
// For example, show a Toast or Snackbar. // For example, show a Toast or Snackbar.
showToast("Test is ongoing. Cannot go back.") showToast(R.string.test_go_noback)
} else { } else {
// If the test is not ongoing, you can trigger the back action of the hosting activity // If the test is not ongoing, you can trigger the back action of the hosting activity
activity?.onBackPressed() activity?.onBackPressed()
} }
} }
private fun showStartSampleDialog() { private fun processResult() {
activity?.runOnUiThread {
UIUtils.createAlertDialog(requireContext(),
"Start Sample",
"Do you want to start sample reading?",
getString(R.string.no),
"Yes",
object : MyDialogListener {
override fun onClickNegativeButton() {}
override fun onClickPositiveButton() {
listenToHemoCube()
startSampleProcess()
}
})
}
}
fun handleValidResult(validString: String, fullReadOutput: String) {
try { try {
val result = validString.split(" ") hemoCubeViewModel.messages.postValue(getString(R.string.processing_result))
val deviceLog = resultData val deviceLog = resultData
if (result.size == 8) {
val deviceSerialNo = result[2]
with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, deviceSerialNo)
apply()
}
val loginId = sharedPreferences.getString(Constants.USER_ID, "").toString()
if (checkDeviceIdMismatch(deviceSerialNo, loginId)) {
activity?.runOnUiThread {
binding.errorMessage.text = "Warning: Login Id is different"
binding.errorMessage.visibility = View.VISIBLE
}
}
val led1BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()
} else {
result[3].toDoubleOrNull()
}
val led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()
} else {
result[4].toDoubleOrNull()
}
val pInfo = requireActivity().packageManager.getPackageInfo(
requireActivity().packageName, 0
)
val version = pInfo.versionName
val led1Sample = result[5].toDoubleOrNull()
val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
val led2Average = log10(led2BufferForDevice?.div(led2Sample!!) ?: 0.0)
val deviceRatio = led1Average / led2Average
val coefficientsList = Constants.COEFFICIENTS[deviceSerialNo]
// if (coefficientsList != null) {
val coefficient1 = coefficientsList?.get(0)?.get(0).toString()
val coefficient2 = coefficientsList?.get(1)?.get(0).toString()
val coefficientsString = "$coefficient1,$coefficient2"
// if (led1BufferForDevice!! > 20000 && led1BufferForDevice < 24000 && led2BufferForDevice!! > 20000 && led2BufferForDevice < 24000) { val pInfo = requireActivity().packageManager.getPackageInfo(
// if (led1Sample!! < led1BufferForDevice && led1Sample < 24000 && led2Sample!! < led2BufferForDevice && led2Sample < 24000) { requireActivity().packageName, 0
// if (deviceRatio < 0.08) { )
// if (deviceRatio > 1.07) { val version = pInfo.versionName
//
// }
// }
// }
// }
if (led1Average < 0 || led2Average < 0) { val led1Average = log10(led1BufferForDevice.div(led1SampleForDevice))
activity?.runOnUiThread{ val led2Average = log10(led2BufferForDevice.div(led2SampleForDevice))
binding.errorMessage.text = "Warning: Negative Abs. Retake Blank Reading" val led3Average = log10(led3BufferForDevice.div(led3SampleForDevice))
binding.errorMessage.visibility = View.VISIBLE val led4Average = log10(led4BufferForDevice.div(led4SampleForDevice))
} val deviceRatio = led3Average / led1Average
}
DataHolder.hemoCubeTestData?.apply { if (led1BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(0)
deviceId = deviceSerialNo ?.get(0)!!
led1Buffer = led1BufferForDevice || led2BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
led2Buffer = led2BufferForDevice 1
appVersion = version )?.get(0)!!
this.led1Sample = led1Sample || led3BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
this.led2Sample = led2Sample 2
this.led1Average = led1Average )?.get(0)!!
this.led2Average = led2Average || led4BufferForDevice < Constants.BUFFER_INTENSITY_THRESHOLDS[deviceHardwareId]?.get(
this.deviceRatio = deviceRatio 3
this.calculatedRatio = calculateRatio(deviceRatio) )?.get(0)!!
// this.coefficients = currentDeviceData?.coefficients?.get(0).toString() + ", " + currentDeviceData?.coefficients?.get(1).toString() ) {
this.coefficients = coefficientsString validationError = true
this.classificationResult = findResult(calculatedRatio) allErrorMessages += "Error: Invalid Test. Improper buffer reading (low)"
hemoCubeViewModel.messages.postValue(this.classificationResult) activity?.runOnUiThread {
this.resultData = deviceLog binding.errorMessage.text = getString(R.string.error_improper_buffer_low)
if (!isUsingExistingBuffer) { binding.errorMessage.visibility = View.VISIBLE
with(sharedPreferences.edit()) {
putString(Constants.BUFFER_VALUE_1, led1Buffer.toString())
putString(Constants.BUFFER_VALUE_2, led2Buffer.toString())
apply()
}
}
activity?.runOnUiThread {
binding.btnSubmit.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
binding.clParent.setBackgroundColor(Color.parseColor("#edfffd"))
}
} }
} }
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
allErrorMessages += "Error: Invalid Test. Improper buffer reading (high)" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text =
getString(R.string.error_improper_buffer_high)
binding.errorMessage.visibility = View.VISIBLE
binding.btnSubmit.isEnabled = true
binding.btnSubmit.isClickable = true
}
}
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
allErrorMessages += "Error: Invalid Test. Problem with de-oxygenation" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_invalid_test)
binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs1 < 0 || fittedAbs2 < 0 || fittedAbs3 < 0 || fittedAbs4 < 0) {
validationError = true
activity?.runOnUiThread {
binding.errorMessage.text = getString(R.string.error_negative_abs)
binding.errorMessage.visibility = View.VISIBLE
}
}
if (fittedAbs3 < 0.1) {
validationError = true
allErrorMessages += "Error: Low Hb. Repeat test" + "\n"
activity?.runOnUiThread {
binding.errorMessage.text = "Error: Low Hb. Repeat test"
binding.errorMessage.visibility = View.VISIBLE
}
}
DataHolder.hemoCubeTestData?.apply {
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()
led1Buffer = led1BufferForDevice
led2Buffer = led2BufferForDevice
led3Buffer = led3BufferForDevice
led4Buffer = led4BufferForDevice
appVersion = version
this.led1Sample = led1SampleForDevice
this.led2Sample = led2SampleForDevice
this.led3Sample = led3SampleForDevice
this.led4Sample = led4SampleForDevice
this.led1Average = led1Average
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)
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
hemoCubeViewModel.messages.postValue(this.prdClassification)
this.errorMessages = allErrorMessages
this.resultData = deviceLog
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"))
}
// }
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
"Error while processing device data", R.string.error_processing_device_data,
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
Firebase.crashlytics.recordException(e) Firebase.crashlytics.recordException(e)
} }
} }
private fun findResult(calculatedRatio: Double?): String { fun findResult(calculatedRatio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification")
if (calculatedRatio != null) { if (calculatedRatio != null) {
if (calculatedRatio < 0.05) if (calculatedRatio < 0.05)
return "Inconclusive. Very low Absorbance - Repeat test with Higher Blood Volume" return getString(R.string.error_repeat_test_higher_volume)
if (calculatedRatio in 0.05..0.155) if (calculatedRatio in 0.05..0.155)
return "Normal" return getString(R.string.normal)
if (calculatedRatio in 0.155..0.175) if (calculatedRatio in 0.155..0.175)
return "Negative Borderline. Repeat Test" return getString(R.string.negative_borderline)
if (calculatedRatio in 0.175..0.22) if (calculatedRatio in 0.175..0.22)
return "Sickle Cell Trait" return getString(R.string.sickle_cell_trait)
if (calculatedRatio in 0.22..0.25) if (calculatedRatio in 0.22..0.25)
return "Positive for Sickle Cell. HPLC for Confirmation" return getString(R.string.positive_for_sickle_cell)
if (calculatedRatio in 0.25..0.35) if (calculatedRatio in 0.25..0.35)
return "Sickle Cell Disease" return getString(R.string.sickle_cell_disease)
if (calculatedRatio > 0.35) if (calculatedRatio > 0.35)
return "Inconclusive. Repeat with test with lower volume of blood" return getString(R.string.error_repeat_test_lower_volume)
} else { } else {
return "NULL" return getString(R.string.invalid)
} }
} catch (e: Exception) { } catch (e: Exception) {
showToast("error while performing classification") showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e) Firebase.crashlytics.recordException(e)
return "ERROR" return getString(R.string.error)
} }
return "NULL" return getString(R.string.invalid)
} }
private fun showToast(message: String) { private fun absorbanceBasedClassification(predictedDenovixRatio: Double?): String {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() try {
hemoCubeViewModel.messages.postValue("result classification")
if (predictedDenovixRatio != null) {
if (predictedDenovixRatio in 0.0..0.16)
return getString(R.string.normal)
if (predictedDenovixRatio in 0.16..0.165)
return getString(R.string.negative_borderline)
if (predictedDenovixRatio in 0.165..0.235)
return getString(R.string.sickle_cell_trait)
if (predictedDenovixRatio in 0.235..0.24)
return getString(R.string.positive_borderline)
if (predictedDenovixRatio in 0.24..1.0)
return getString(R.string.sickle_cell_disease)
} else {
return getString(R.string.invalid)
}
} catch (e: Exception) {
showToast(R.string.error_classification)
Firebase.crashlytics.recordException(e)
return getString(R.string.error)
}
return getString(R.string.invalid)
}
private fun showToast(messageResId: Int) {
Toast.makeText(requireContext(), getString(messageResId), Toast.LENGTH_SHORT).show()
} }
private fun startBufferProcess() { private fun startBufferProcess() {
hemoCubeViewModel.progressBar.postValue(true) hemoCubeViewModel.progressBar.postValue(true)
activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.GONE
}
(activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer, (activity as HemocubeActivity).mService.sendAndListenToHemoCube(HemoCubeCommands.startBuffer,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) {} override fun onUsbRead(data: ByteArray?) {}
@@ -495,38 +679,14 @@ class HemoCubeFragment : Fragment() {
} }
private fun calculateRatio(ratio: Double): Double { private fun calculateRatio(ratio: Double): Double {
val coefficient1: Double = (Constants.COEFFICIENTS[deviceSerialNo]?.get(0) ?: 0.0) as Double val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
val coefficient2: Double = (Constants.COEFFICIENTS[deviceSerialNo]?.get(1) ?: 0.0) as Double val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0
return coefficient1 * ratio + coefficient2 return coefficient1 * ratio + coefficient2
} }
private fun parseResult(frames: List<String>): String {
val lines = mutableListOf<String>()
for (frame in frames.reversed()) {
if (frame.contains("REND") || frame.contains("RESULT")) lines += frame
if (frame.contains("RESULT")) {
break
}
}
val line = lines.reversed().joinToString("").trim()
if (line.contains("RESULT") && line.split(" ").size == 8) {
return line
}
return ""
}
private fun isValidResult(line: String): String {
return if (line.contains("RESULT") && line.split(" ").size == 8) {
line
} else {
""
}
}
private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean { private fun checkDeviceIdMismatch(deviceId: String, loginId: String): Boolean {
if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last()) if (!deviceId.isNullOrEmpty() && !loginId.isNullOrEmpty() && deviceId.last() != loginId.last())
return true return true
return false return false
} }
} }

View File

@@ -166,8 +166,6 @@ class HemoCubeViewModel @Inject constructor(
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails) hemoCubeDao.insertAll(testDetails)
} }
else -> {}
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}") Log.e("Testdb", "Exception during data upload: ${e.message}")
@@ -192,8 +190,6 @@ class HemoCubeViewModel @Inject constructor(
Log.e("Testdb", "Error uploading data to Firestore: $response") Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
} }
else -> {}
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Testdb", "Exception during data upload: ${e.message}") Log.e("Testdb", "Exception during data upload: ${e.message}")

View File

@@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.testRight.UsbService import com.example.hpostesting.presentation.testRight.UsbService
import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber import com.hoho.android.usbserial.driver.UsbSerialProber
@@ -72,6 +73,12 @@ open class HemocubeActivity : AppCompatActivity() {
viewModel.isServiceConnected = false viewModel.isServiceConnected = false
} }
} }
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
super.attachBaseContext(newBase)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View File

@@ -34,7 +34,7 @@ class UsbService : Service() {
fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) { fun connect(driver: UsbSerialDriver, connection: UsbDeviceConnection) {
mPort = driver.ports[0] // Most devices have just one port (port 0) mPort = driver.ports[0] // Most devices have just one port (port 0)
mPort.open(connection) mPort.open(connection)
mPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE) mPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE)
isUsbConnected = true isUsbConnected = true
Log.d(TAG, "My Usb Connected ${mPort.driver}") Log.d(TAG, "My Usb Connected ${mPort.driver}")

View File

@@ -31,17 +31,17 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" /> app:layout_constraintTop_toBottomOf="@id/tv_title" />
<!-- <TextView--> <!-- <TextView-->
<!-- android:id="@+id/tv_subtitle3"--> <!-- android:id="@+id/tv_subtitle3"-->
<!-- style="@style/title2"--> <!-- style="@style/title2"-->
<!-- android:layout_width="0dp"--> <!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"--> <!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginHorizontal="24dp"--> <!-- android:layout_marginHorizontal="24dp"-->
<!-- android:layout_marginTop="16dp"--> <!-- android:layout_marginTop="16dp"-->
<!-- android:text="@string/step5"--> <!-- android:text="@string/step5"-->
<!-- app:layout_constraintEnd_toEndOf="parent"--> <!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"--> <!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />--> <!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle2" />-->
<TextView <TextView
android:id="@+id/tv_name" android:id="@+id/tv_name"
@@ -147,8 +147,35 @@
app:layout_constraintHorizontal_bias="1.0" app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/et_abha_id" app:layout_constraintStart_toEndOf="@id/et_abha_id"
app:layout_constraintTop_toTopOf="@id/et_abha_id" /> app:layout_constraintTop_toTopOf="@id/et_abha_id" />
<Button
android:visibility="gone"
android:id="@+id/btn_samplestart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/Start_Sample"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_placebuffer" />
<Button
android:id="@+id/btn_placebuffer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/place_buffer"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<Button <Button
android:visibility="gone" android:visibility="gone"
android:id="@+id/btn_submit" android:id="@+id/btn_submit"
@@ -178,62 +205,19 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_submit" /> app:layout_constraintTop_toBottomOf="@id/btn_submit" />
<!-- <com.google.android.material.textfield.TextInputLayout--> <Button
<!-- android:id="@+id/til_blood_group"--> android:visibility="gone"
<!-- style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"--> android:id="@+id/btn_digitalCard"
<!-- android:layout_width="match_parent"--> android:layout_width="wrap_content"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:layout_marginHorizontal="24dp"--> android:layout_marginHorizontal="16dp"
<!-- android:layout_marginTop="16dp"--> android:layout_marginTop="24dp"
<!-- app:layout_constraintEnd_toEndOf="parent"--> android:clickable="false"
<!-- app:layout_constraintStart_toStartOf="parent"--> android:text="DigitalCard View"
<!-- app:layout_constraintTop_toBottomOf="@id/tv_subtitle4">--> android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
<!-- <AutoCompleteTextView--> app:layout_constraintStart_toStartOf="parent"
<!-- android:id="@+id/et_blood_group"--> app:layout_constraintTop_toBottomOf="@id/error_message" />
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:hint="@string/select_blood_group"-->
<!-- android:inputType="none"-->
<!-- android:labelFor="@id/til_blood_group"-->
<!-- app:simpleItems="@array/blood_group" />-->
<!-- </com.google.android.material.textfield.TextInputLayout>-->
<!-- <Button-->
<!-- android:id="@+id/btn_kit"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_margin="10dp"-->
<!-- android:text="@string/new_kit"-->
<!-- android:textColor="@color/white"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- <Button-->
<!-- android:id="@+id/btn_buffer"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/new_buffer"-->
<!-- android:textColor="@color/white"-->
<!-- android:layout_margin="10dp"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintEnd_toStartOf="@id/btn_kit"/>-->
<!-- <Button-->
<!-- android:id="@+id/btn_read"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/read"-->
<!-- android:layout_margin="16dp"-->
<!-- android:clickable="false"-->
<!-- app:layout_constraintTop_toBottomOf="@id/btn_set_reference"-->
<!-- app:layout_constraintStart_toStartOf="parent" />-->
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -249,5 +233,5 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout> </layout>

View File

@@ -1,36 +1,9 @@
<!-- SlideshowFragment layout --> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.dashboard.SlideshowFragment"> tools:context="com.example.hpostesting.presentation.dashboard.SlideshowFragment">
<TextView </androidx.constraintlayout.widget.ConstraintLayout>
android:visibility="gone"
android:id="@+id/text_slideshow"
style="@style/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:textAlignment="center"
android:textSize="20sp"
android:text="@string/to_be_launched_in_next_version_of_the_app"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Language Settings -->
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/text_slideshow"
app:layout_constraintBottom_toBottomOf="parent">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -48,20 +48,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userID" app:layout_constraintTop_toBottomOf="@id/userID"
tools:text="UserID: MohamedKaif" /> tools:text="UserID: MohamedKaif" />
<TextView
android:id="@+id/teststatus"
android:layout_width="0dp"
android:layout_height="wrap_content"
style="@style/title1_1"
android:layout_marginTop="4dp"
android:layout_marginStart="16dp"
android:gravity="start"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bloodGroup"
tools:text="Test Status: Completed"/>
<TextView <TextView
android:id="@+id/time" android:id="@+id/time"
@@ -75,8 +61,9 @@
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/teststatus" app:layout_constraintTop_toBottomOf="@id/bloodGroup"
tools:text="startedAt: yyyy-MM-dd HH:mm:ss" /> tools:text="Test Status: Completed" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>

View File

@@ -255,5 +255,9 @@
<string name="place_sample">सैम्पल रखें</string> <string name="place_sample">सैम्पल रखें</string>
<string name="invalid">अमान्य</string> <string name="invalid">अमान्य</string>
<string name="error">त्रुटि</string> <string name="error">त्रुटि</string>
<string name="language_update">भाषा सफलतापूर्वक अपडेट की गई है</string>
<string name="select_language">अपनी पसंदीदा भाषा का चयन करें</string>
<string name="app_language">ऐप भाषा</string>
<string name="add_blood_group">रक्त समूह जोड़ें</string>
<string name="ok">ठीक है</string>
</resources> </resources>

View File

@@ -255,5 +255,11 @@
<string name="place_sample">ನಮೂನೆ ಇಟ್ಟುಕೊಳ್ಳಿ</string> <string name="place_sample">ನಮೂನೆ ಇಟ್ಟುಕೊಳ್ಳಿ</string>
<string name="invalid">ಅಮಾನ್ಯ</string> <string name="invalid">ಅಮಾನ್ಯ</string>
<string name="error">ದೋಷ</string> <string name="error">ದೋಷ</string>
<string name="language_update">ಭಾಷೆ ಯಶಸ್ವಿಯಾಗಿ ನವೀಕರಿಸಲಾಗಿದೆ</string>
<string name="select_language">ನಿಮ್ಮ ಆದರಿತ ಭಾಷೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</string>
<string name="app_language">ಅಪ್ಲಿಕೇಶನ್ ಭಾಷೆ</string>
<string name="add_blood_group">ರಕ್ತ ಗುಂಡನ್ನು ಸೇರಿಸಿ</string>
<string name="ok">ಸರಿ</string>
<!-- Add translations for other strings -->
</resources> </resources>

View File

@@ -155,6 +155,7 @@
<string name="is_patient_married_yes_no">Is Patient Married? (Yes/No)</string> <string name="is_patient_married_yes_no">Is Patient Married? (Yes/No)</string>
<string name="category">Category</string> <string name="category">Category</string>
<string name="blood_group">Blood Group</string> <string name="blood_group">Blood Group</string>
<string name="add_blood_group">Add Blood Group</string>
<string name="digital_card">Digital Counselling Card</string> <string name="digital_card">Digital Counselling Card</string>
<string name="patient_medical_records">Patient Medical Records</string> <string name="patient_medical_records">Patient Medical Records</string>
<string name="patient_address_details">Patient Address Details</string> <string name="patient_address_details">Patient Address Details</string>
@@ -255,5 +256,8 @@
<string name="place_sample">Place Sample</string> <string name="place_sample">Place Sample</string>
<string name="invalid">Invalid</string> <string name="invalid">Invalid</string>
<string name="error">Error</string> <string name="error">Error</string>
<string name="language_update">Language updated successfully</string>
<string name="select_language">Select your preferred language</string>
<string name="app_language">App Language</string>
<string name="ok">OK</string>
</resources> </resources>