Compare commits

...

2 Commits

7 changed files with 317 additions and 27 deletions

View File

@@ -47,6 +47,7 @@ object Constants {
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 34 const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 34
const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM = 9 const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM = 9
const val MAXIMUM_TEST_ALLOWED_SINGLE_TEST = 0
const val RANGE_IN_RESULT_CALCULATIONS = 10 const val RANGE_IN_RESULT_CALCULATIONS = 10
@@ -1586,6 +1587,7 @@ object Constants {
//Trueheme for 10mm //Trueheme for 10mm
//Before changing below values review before //Before changing below values review before
//classification borderline metric //classification borderline metric
const val TEST_FOR_10MM = "SMI/SC-2-D10/"
const val positiveBoderLineMetricCheck10mmMin = 1.3 const val positiveBoderLineMetricCheck10mmMin = 1.3
const val positiveBoderLineMetricCheck10mmMax = 1.66 const val positiveBoderLineMetricCheck10mmMax = 1.66
const val negativeBoderLineMetricCheck10mmMin = 2.0 const val negativeBoderLineMetricCheck10mmMin = 2.0
@@ -1603,6 +1605,7 @@ object Constants {
const val sickleCellDiseaseMax10mm = 0.7 const val sickleCellDiseaseMax10mm = 0.7
//Trueheme for 2mm //Trueheme for 2mm
//classification borderline metric //classification borderline metric
const val TEST_FOR_2MM = "SMI/SC/"
const val positiveBoderLineMetricCheck2mmMin = 0.8 const val positiveBoderLineMetricCheck2mmMin = 0.8
const val positiveBoderLineMetricCheck2mmMax = 1.1 const val positiveBoderLineMetricCheck2mmMax = 1.1
const val negativeBoderLineMetricCheck2mmMin = 1.5 const val negativeBoderLineMetricCheck2mmMin = 1.5
@@ -1619,6 +1622,25 @@ object Constants {
const val sickleCellDiseaseMin2mm = 0.45 const val sickleCellDiseaseMin2mm = 0.45
const val sickleCellDiseaseMax2mm = 0.7 const val sickleCellDiseaseMax2mm = 0.7
//Trueheme for 10mm Single Test
//classification borderline metric
const val singleTest = "SMI/SC-ST/"
const val positiveBoderLineMetricCheck2mmStMin = 1.3
const val positiveBoderLineMetricCheck2mmStMax = 1.66
const val negativeBoderLineMetricCheck2mmStMin = 2.0
const val negativeBoderLineMetricCheck2mmStMax = 2.4
//classification device ratio
const val normalMinSt2mm = 0.07
const val normalMaxSt2mm = 0.23
const val negativeBorderlineMinSt2mm = 0.23
const val negativeBorderlineMaxSt2mm = 0.27
const val sickleCellTraitMinSt2mm = 0.27
const val sickleCellTraitMaxSt2mm = 0.31
const val positiveForSickleCellMinSt2mm = 0.31
const val positiveForSickleCellMaxSt2mm = 0.39
const val sickleCellDiseaseMinSt2mm = 0.39
const val sickleCellDiseaseMaxSt2mm = 0.7
const val min2mmLed1 = 0.34 const val min2mmLed1 = 0.34
const val max2mmLed1 = 1.48 const val max2mmLed1 = 1.48
const val min2mmLed2 = 0.04 const val min2mmLed2 = 0.04

View File

@@ -38,15 +38,16 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
} }
override fun exportDataToCSV( override fun exportDataToCSV(
fileName: String, dataList: List<HemoCubeTestData>, filePath: String, dataList: List<HemoCubeTestData>,
): Boolean { ): Boolean {
try { try {
val formattedFileName = fileName.replace( // Create the file directly from the provided path
Regex("[^a-zA-Z0-9.-]"), val file = File(filePath)
"_"
) // Replace special characters with underscores // Ensure parent directory exists
val filePath = File(getExternalStorageDirectory(), formattedFileName) file.parentFile?.mkdirs()
val writer = FileWriter(filePath)
val writer = FileWriter(file)
val csvWriter = CSVWriter(writer) val csvWriter = CSVWriter(writer)
// Write CSV header // Write CSV header
val header = arrayOf( val header = arrayOf(
@@ -103,8 +104,8 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
csvWriter.writeNext(header) csvWriter.writeNext(header)
// Filter and write data rows where testStatus is true // Filter and write data rows where testStatus is true
val filteredDataList = dataList.filter { it.testStatus == true } // val filteredDataList = dataList.filter { it.testStatus == true }
for (data in filteredDataList) { for (data in dataList) {
val row = arrayOf( val row = arrayOf(
data._id, data._id,
data.name, data.name,
@@ -226,8 +227,8 @@ class LocalFileDataSourceImpl @Inject constructor() : LocalFileDataSource {
csvWriter.writeNext(header) csvWriter.writeNext(header)
// Filter and write data rows where testStatus is true // Filter and write data rows where testStatus is true
val filteredDataList = dataList.filter { it.testStatus == true } //val filteredDataList = dataList.filter { it.testStatus == true }
for (data in filteredDataList) { for (data in dataList) {
val row = arrayOf( val row = arrayOf(
data._id, data._id,
data.name, data.name,

View File

@@ -24,6 +24,9 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.Constants.TEST_FOR_10MM
import com.example.hpostesting.data.constant.Constants.TEST_FOR_2MM
import com.example.hpostesting.data.constant.Constants.singleTest
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.test.TestType import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.main_base.DashboardActivity import com.example.hpostesting.presentation.main_base.DashboardActivity
@@ -52,7 +55,7 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
private var fromWhere = "Home" private var fromWhere = "Home"
private val TAG = "KitScanActivity" private val TAG = "KitScanActivity"
private lateinit var binding: ActivityKitScanBinding private lateinit var binding: ActivityKitScanBinding
private var maxTest = 9
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
var sdkHandler: SDKHandler? = null var sdkHandler: SDKHandler? = null
@@ -71,20 +74,27 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
} }
private fun processScannedData(contents: String) {//edited auto selection of cuvette size private fun processScannedData(contents: String) {//edited auto selection of cuvette size
if(contents.contains("SMI/SC/")){ if(contents.contains(TEST_FOR_2MM)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm") putString(Constants.CUVETTE_SIZE, "2mm")
apply() apply()
} }
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents) binding.nameEditText.setText(contents)
}else if(contents.contains("SMI/SC-2-D10/")){ }else if(contents.contains(TEST_FOR_10MM)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm") putString(Constants.CUVETTE_SIZE, "10mm")
apply() apply()
} }
Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents) binding.nameEditText.setText(contents)
}else if(contents.contains(singleTest)){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mmSt")
apply()
}
Toast.makeText(this, "Selected cuvette size: 2mm for single test", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(contents)
}else{ }else{
Toast.makeText(this, R.string.invalid_kit, Toast.LENGTH_LONG).show() Toast.makeText(this, R.string.invalid_kit, Toast.LENGTH_LONG).show()
} }
@@ -133,10 +143,12 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
setContentView(binding.root) setContentView(binding.root)
binding.toolbar.title = "Kit Serial Number" binding.toolbar.title = "Kit Serial Number"
fromWhere = intent.getStringExtra("fromWhere").toString() fromWhere = intent.getStringExtra("fromWhere").toString()
val maxTest = if(sharedPreference.getString(Constants.CUVETTE_SIZE, "10mm").toString() == "2mm"){ if(sharedPreference.getString(Constants.CUVETTE_SIZE, "10mm").toString() == "2mm"){
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE maxTest = Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE
}else{ }else if(sharedPreference.getString(Constants.CUVETTE_SIZE, "10mm").toString() == "10mm"){
Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM maxTest = Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE10MM
} else if(sharedPreference.getString(Constants.CUVETTE_SIZE, "10mmSt").toString() == "10mmSt"){
maxTest = Constants.MAXIMUM_TEST_ALLOWED_SINGLE_TEST
} }
val time = timeDifference(sharedPreference.getString(Constants.KIT_TIME, "").toString()) val time = timeDifference(sharedPreference.getString(Constants.KIT_TIME, "").toString())
val kitNum = sharedPreference.getString(Constants.KIT_NUMBER, "").toString() val kitNum = sharedPreference.getString(Constants.KIT_NUMBER, "").toString()
@@ -212,19 +224,27 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
binding.btnGo.setOnClickListener { binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim() val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) { if (serialNumber.isNotEmpty() && isSerialValid(serialNumber)) {
if(serialNumber.contains("SMI/SC/")){ if(serialNumber.contains(TEST_FOR_2MM)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "2mm") putString(Constants.CUVETTE_SIZE, "2mm")
apply() apply()
} }
Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Selected cuvette size: 2mm", Toast.LENGTH_SHORT).show()
}else if(serialNumber.contains("SMI/SC-2-D10/")){ }else if(serialNumber.contains(TEST_FOR_10MM)){
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mm") putString(Constants.CUVETTE_SIZE, "10mm")
apply() apply()
} }
Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show() Toast.makeText(this, "Selected cuvette size: 10mm", Toast.LENGTH_SHORT).show()
}else if(serialNumber.contains(singleTest)){
with(sharedPreference.edit()) {
putString(Constants.CUVETTE_SIZE, "10mmSt")
apply()
}
Toast.makeText(this, "Selected cuvette size: 2mm for single test", Toast.LENGTH_SHORT).show()
binding.nameEditText.setText(serialNumber)
} }
val kitTime = SimpleDateFormat( val kitTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time).toString() ).format(Calendar.getInstance().time).toString()
@@ -351,16 +371,21 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
// } // }
private fun isSerialValid(s: String): Boolean { private fun isSerialValid(s: String): Boolean {
if (s.contains("SMI/SC/")) { if (s.contains(TEST_FOR_2MM)) {
if(s.length != 17){ if(s.length != 17){
binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC/000/00/000" binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC/000/00/000"
return false return false
} }
}else if(s.contains("SMI/SC-2-D10/")){ }else if(s.contains(TEST_FOR_10MM)){
if(s.length != 27){ if(s.length != 27){
binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC-2-D10/000000/000/000" binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC-2-D10/000000/000/000"
return false return false
} }
}else if(s.contains(singleTest)){
if(s.length != 27){
binding.nameEditText.error = "Invalid Kit Serial Number, correct example SMI/SC-ST/000000/000/000"
return false
}
}else{ }else{
return false return false
} }

View File

@@ -14,17 +14,23 @@
package com.example.hpostesting.presentation.main_base package com.example.hpostesting.presentation.main_base
import android.content.Context import android.content.Context
import android.content.DialogInterface
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri
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
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
@@ -33,20 +39,33 @@ import androidx.preference.SwitchPreferenceCompat
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.firebase.FirebaseConfig import com.example.hpostesting.firebase.FirebaseConfig
import com.example.hpostesting.firebase.FirebaseManager import com.example.hpostesting.firebase.FirebaseManager
import com.example.hpostesting.presentation.trueheme_test.TrueHemeTestViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.ktx.storage
import com.google.firebase.storage.ktx.storageMetadata
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
private var isLanguageChanged = false private var isLanguageChanged = false
class SlideshowFragment : Fragment() { class SlideshowFragment : Fragment() {
private var selectedItem = "10mm" private var selectedItem = "10mm"
private val values = arrayOf("10mm", "2mm") private val values = arrayOf("10mm", "2mm", "10mmSt")
private lateinit var binding: FragmentSlideshowBinding private lateinit var binding: FragmentSlideshowBinding
private val trueHemeTestViewModel: TrueHemeTestViewModel by activityViewModels()
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView( override fun onCreateView(
@@ -59,7 +78,9 @@ class SlideshowFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.btnDownload.setOnClickListener {
sendData()
}
binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME, "")) binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME, ""))
selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE, "10mm").toString() selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE, "10mm").toString()
binding.btnGo.setOnClickListener { binding.btnGo.setOnClickListener {
@@ -81,8 +102,10 @@ class SlideshowFragment : Fragment() {
val pos: Int val pos: Int
if (selectedItem == "10mm") { if (selectedItem == "10mm") {
pos = 0 pos = 0
} else { } else if (selectedItem == "2mm"){
pos = 1 pos = 1
} else {
pos = 2
} }
binding.spinnerCuvette.adapter = adapter binding.spinnerCuvette.adapter = adapter
@@ -114,6 +137,111 @@ class SlideshowFragment : Fragment() {
childFragmentManager.beginTransaction().replace(binding.container.id, PrefsFragment()) childFragmentManager.beginTransaction().replace(binding.container.id, PrefsFragment())
.commit() .commit()
} }
private fun sendData() {
//This data will saved in firebase storage check in HPOS-Prod
val dialog = AlertDialog.Builder(requireContext())
.setTitle("Downloading")
.setMessage("Please wait...")
.setCancelable(false)
.create()
dialog.show()
downloadLocalDBData(dialog)
}
private fun downloadLocalDBData(dialog: DialogInterface) {
var csvDownloaded = false
trueHemeTestViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (!csvDownloaded) {
val downloadList = mutableListOf<HemoCubeTestData>()
userDataList.forEach { userData ->
Log.d("DownloadDebug", "userData: $userData, isCSVCreated: ${userData.isCSVCreated}")
downloadList.add(userData)
}
if (downloadList.isNotEmpty()) {
// Set flag to prevent multiple executions due to observer
csvDownloaded = true
// Launch coroutine to handle CSV creation and upload
lifecycleScope.launch {
try {
// Call suspend function to create CSV and wait for result
val csvFile = trueHemeTestViewModel.createCSVNew(downloadList, requireContext())
if (csvFile != null && csvFile.exists() && csvFile.length() > 0) {
uploadToFirebaseStorage(csvFile)
Toast.makeText(
requireContext(),
"CSV file created successfully at ${csvFile.absolutePath}",
Toast.LENGTH_LONG
).show()
} else {
csvDownloaded = false // Reset flag if failed
Toast.makeText(
requireContext(),
"CSV file creation failed, please try again",
Toast.LENGTH_SHORT
).show()
}
} catch (e: Exception) {
csvDownloaded = false // Reset flag if exception
e.printStackTrace()
Toast.makeText(
requireContext(),
"Error creating CSV file: ${e.message}",
Toast.LENGTH_SHORT
).show()
} finally {
dialog.dismiss()
}
}
} else {
Toast.makeText(requireContext(), "No data to download", Toast.LENGTH_SHORT).show()
dialog.dismiss()
}
}
}
}
private fun uploadToFirebaseStorage(file: File) {
// Get Firebase Storage reference
val storage = Firebase.storage
val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val storageRef = storage.reference.child("!!!csv_files/hemocube_data_$timestamp.csv")
// Create file metadata
val metadata = storageMetadata {
contentType = "text/csv"
}
// Upload file
val uploadTask = storageRef.putFile(Uri.fromFile(file), metadata)
uploadTask
.addOnSuccessListener {
Toast.makeText(
requireContext(),
"CSV file uploaded to Firebase successfully",
Toast.LENGTH_SHORT
).show()
}
.addOnFailureListener { exception ->
Log.e("FirebaseUpload", "Upload failed", exception)
Toast.makeText(
requireContext(),
"Failed to upload CSV to Firebase",
Toast.LENGTH_SHORT
).show()
}
.addOnProgressListener { taskSnapshot ->
val progress = (100.0 * taskSnapshot.bytesTransferred / taskSnapshot.totalByteCount)
Log.d("FirebaseUpload", "Upload is $progress% done")
}
}
} }
class PrefsFragment : PreferenceFragmentCompat() { class PrefsFragment : PreferenceFragmentCompat() {

View File

@@ -32,6 +32,20 @@ import androidx.lifecycle.MutableLiveData
import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.Result import com.example.hpostesting.util.Result
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.Constants.negativeBoderLineMetricCheck2mmStMax
import com.example.hpostesting.data.constant.Constants.negativeBoderLineMetricCheck2mmStMin
import com.example.hpostesting.data.constant.Constants.negativeBorderlineMaxSt2mm
import com.example.hpostesting.data.constant.Constants.negativeBorderlineMinSt2mm
import com.example.hpostesting.data.constant.Constants.normalMaxSt2mm
import com.example.hpostesting.data.constant.Constants.normalMinSt2mm
import com.example.hpostesting.data.constant.Constants.positiveBoderLineMetricCheck2mmStMax
import com.example.hpostesting.data.constant.Constants.positiveBoderLineMetricCheck2mmStMin
import com.example.hpostesting.data.constant.Constants.positiveForSickleCellMaxSt2mm
import com.example.hpostesting.data.constant.Constants.positiveForSickleCellMinSt2mm
import com.example.hpostesting.data.constant.Constants.sickleCellDiseaseMaxSt2mm
import com.example.hpostesting.data.constant.Constants.sickleCellDiseaseMinSt2mm
import com.example.hpostesting.data.constant.Constants.sickleCellTraitMaxSt2mm
import com.example.hpostesting.data.constant.Constants.sickleCellTraitMinSt2mm
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.constant.TestStatus import com.example.hpostesting.data.constant.TestStatus
import com.example.hpostesting.data.model.TestState import com.example.hpostesting.data.model.TestState
@@ -1196,6 +1210,20 @@ class TrueHemeTestFragment : Fragment() {
binding.btnSamplestart.isEnabled = true binding.btnSamplestart.isEnabled = true
return return
} }
}else if(cuvetteSizeSP == "2mmSt"){
inRange2mmLed1 = led1Average in min2mmLed1..max2mmLed1
inRange2mmLed2 = led2Average in min2mmLed2..max2mmLed2
if(!inRange2mmLed1 || !inRange2mmLed2){
trueHemeTestViewModel.messages.postValue("Absorbance out-of-Range - Repeat test with adequate blood volume and Incubation time")
this.testStatusCode = TestStatus.BUFFER_PRINT_COMPLETED.code
binding.testing.visibility = View.GONE
binding.btnPlaceRefreshbuffer.visibility = View.GONE
binding.btnPlacebuffer.visibility = View.GONE
binding.btnSamplestart.visibility = View.VISIBLE
binding.btnSamplestart.isClickable = true
binding.btnSamplestart.isEnabled = true
return
}
} }
} }
} }
@@ -1478,6 +1506,25 @@ class TrueHemeTestFragment : Fragment() {
return "Positive for Sickle Cell. Confirm with HPLC" return "Positive for Sickle Cell. Confirm with HPLC"
} }
} }
}else if(cuvetteSizeSP == "2mmSt"){
if (deviceRatioClass == "Negative Borderline") {
if (borderlineMetric < negativeBoderLineMetricCheck2mmStMin){//1.34
return "Sickle Cell Trait"
}else if(borderlineMetric > negativeBoderLineMetricCheck2mmStMax){
return "Normal"
}else if(borderlineMetric > negativeBoderLineMetricCheck2mmStMin && borderlineMetric < negativeBoderLineMetricCheck2mmStMax){
return "Negative borderline. Confirm with HPLC"
}
}
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
if (borderlineMetric < positiveBoderLineMetricCheck2mmStMin){//1.34
return "Sickle Cell Disease"
}else if(borderlineMetric > positiveBoderLineMetricCheck2mmStMax){
return "Sickle Cell Trait"
}else if(borderlineMetric > positiveBoderLineMetricCheck2mmStMin && borderlineMetric < positiveBoderLineMetricCheck2mmStMax){
return "Positive for Sickle Cell. Confirm with HPLC"
}
}
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -1548,6 +1595,22 @@ class TrueHemeTestFragment : Fragment() {
if (ratio in sickleCellDiseaseMin2mm..sickleCellDiseaseMax2mm){ if (ratio in sickleCellDiseaseMin2mm..sickleCellDiseaseMax2mm){
return "Sickle Cell Disease" return "Sickle Cell Disease"
} }
}else if(cuvetteSize == "2mmSt"){
if (ratio in normalMinSt2mm..normalMaxSt2mm) {
return "Normal"
}
if (ratio in negativeBorderlineMinSt2mm..negativeBorderlineMaxSt2mm){
return "Negative Borderline"
}
if (ratio in sickleCellTraitMinSt2mm..sickleCellTraitMaxSt2mm){
return "Sickle Cell Trait"
}
if (ratio in positiveForSickleCellMinSt2mm..positiveForSickleCellMaxSt2mm){//0.36
return "Positive for Sickle Cell. HPLC for Confirmation"
}
if (ratio in sickleCellDiseaseMinSt2mm..sickleCellDiseaseMaxSt2mm){
return "Sickle Cell Disease"
}
} }
} else { } else {

View File

@@ -53,11 +53,15 @@ import com.example.hpostesting.util.NetworkMonitor
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.Headers import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.ResponseBody import okhttp3.ResponseBody
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
@@ -775,7 +779,44 @@ class TrueHemeTestViewModel @Inject constructor(
return maxCapacity return maxCapacity
} }
suspend fun createCSVNew(data: List<HemoCubeTestData>, context: Context): File? {
return withContext(Dispatchers.IO) {
try {
val timestamp = System.currentTimeMillis()
val fileName = "hemocube_data_$timestamp.csv"
// Create file in app's external files directory
val appFile = File(context.getExternalFilesDir(null), fileName)
// Ensure this file is used by localFileDataSource
val exportSuccess = localFileDataSource.exportDataToCSV(appFile.absolutePath, data)
if (exportSuccess) {
// Update database records
data.forEach { item ->
hemoCubeDao.updateCSVFieldById(
item._id,
true
)
}
// Verify file exists and has content
if (appFile.exists() && appFile.length() > 0) {
return@withContext appFile
} else {
Log.e("CSVCreation", "File creation verified failed: exists=${appFile.exists()}, size=${appFile.length()}")
return@withContext null
}
} else {
Log.e("CSVCreation", "exportDataToCSV returned false")
return@withContext null
}
} catch (e: Exception) {
Log.e("CSVCreation", "Error creating CSV", e)
return@withContext null
}
}
}
fun createCSV(hemoCubeTestData: List<HemoCubeTestData>, appContext: Context) = fun createCSV(hemoCubeTestData: List<HemoCubeTestData>, appContext: Context) =
viewModelScope.launch { viewModelScope.launch {
val fileName = "HPOS${getCurrentDate()}.csv" val fileName = "HPOS${getCurrentDate()}.csv"

View File

@@ -88,12 +88,22 @@
app:layout_constraintBottom_toBottomOf="@id/spinnerCuvette" app:layout_constraintBottom_toBottomOf="@id/spinnerCuvette"
app:layout_constraintStart_toEndOf="@id/spinnerCuvette" app:layout_constraintStart_toEndOf="@id/spinnerCuvette"
app:layout_constraintTop_toTopOf="@id/spinnerCuvette" /> app:layout_constraintTop_toTopOf="@id/spinnerCuvette" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:text="Send Data To Server"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spinnerCuvette"
/>
<FrameLayout <FrameLayout
android:id="@+id/container" android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/btn_add_size" app:layout_constraintTop_toBottomOf="@+id/btn_download"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/> android:layout_marginTop="10dp"/>