Compare commits

..

14 Commits

Author SHA1 Message Date
chandrashekhar reddy
12e022a00a app version 132 - Added changes according to single test and also added upload csv to firebase storage 2025-02-26 16:34:22 +05:30
chandrashekhar reddy
88cdc01978 app version 132 - Added changes according to single test and also added upload csv to firebase storage 2025-02-24 19:02:08 +05:30
sathwikcs
736dff2b11 Fixed the issue where dialogue is showing wrong 2025-02-20 18:23:10 +05:30
sathwikcs
20dd1e41eb Fixed the issue where app wil crash when switched to pre pod 2025-02-19 18:41:11 +05:30
sathwikcs
ad6670a1e8 Merge remote-tracking branch 'origin/dev-server-2.1.132' into dev-server-2.1.132 2025-02-19 15:42:43 +05:30
sathwikcs
e6f8ab69e9 Fixed the issue where app wil crash when switched to pre pod 2025-02-19 15:42:23 +05:30
Sathwik C S
ccd2138f66 Update file README.md 2025-02-18 09:31:30 +00:00
sathwikcs
d54436996d added dev icon 2025-02-18 14:53:36 +05:30
sathwikcs
52a555a63a Changes in josn - default : prod 2025-02-18 14:53:14 +05:30
sathwikcs
8e80cfe525 SettingsFragment.kt 2025-02-18 14:52:02 +05:30
sathwikcs
f26f54e51d Added the developer shared pref 2025-02-18 14:51:31 +05:30
sathwikcs
1d029b8ff8 removed the selector drop down 2025-02-18 14:50:40 +05:30
sathwikcs
c88efd148b App version Tap manager 2025-02-18 14:50:08 +05:30
sathwikcs
cb27983d21 NetworkStatusLiveData.kt has been removed 2025-02-17 12:38:11 +05:30
14 changed files with 519 additions and 167 deletions

View File

@@ -1,5 +1,5 @@
# This version has the new network checker implemented # Latest hpos app version
## current version : 2.1.131-network ## current version : 2.1.132
### Release key ### Release key

View File

@@ -20,8 +20,8 @@ android {
applicationId "in.sminnovations.hpostesting.server" applicationId "in.sminnovations.hpostesting.server"
minSdk 30 minSdk 30
targetSdk 34 targetSdk 34
versionCode 133 versionCode 134
versionName "2.1.131" versionName "2.1.132"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -1,33 +1,33 @@
{ {
"project_info": { "project_info": {
"project_number": "650071678820", "project_number": "1012719870714",
"project_id": "hpos-af3cc", "project_id": "hpos-prod",
"storage_bucket": "hpos-af3cc.appspot.com" "storage_bucket": "hpos-prod.appspot.com"
}, },
"client": [ "client": [
{ {
"client_info": { "client_info": {
"mobilesdk_app_id": "1:650071678820:android:f6fd45e2f6a63aef6c6471", "mobilesdk_app_id": "1:1012719870714:android:d8d7c962d96f4097de5f43",
"android_client_info": { "android_client_info": {
"package_name": "in.sminnovations.hpostesting.server" "package_name": "in.sminnovations.hpostesting.server"
} }
}, },
"oauth_client": [ "oauth_client": [
{ {
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", "client_id": "1012719870714-uli6cdjea3lfnnueh6e4r15i10ei1vlj.apps.googleusercontent.com",
"client_type": 3 "client_type": 3
} }
], ],
"api_key": [ "api_key": [
{ {
"current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" "current_key": "AIzaSyA_O0oZGzy3Kiw9fiLQ3OFPME-xQJP88vs"
} }
], ],
"services": { "services": {
"appinvite_service": { "appinvite_service": {
"other_platform_oauth_client": [ "other_platform_oauth_client": [
{ {
"client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", "client_id": "1012719870714-uli6cdjea3lfnnueh6e4r15i10ei1vlj.apps.googleusercontent.com",
"client_type": 3 "client_type": 3
} }
] ]

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

@@ -14,6 +14,7 @@ package com.example.hpostesting.firebase
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Process import android.os.Process
import androidx.core.content.edit
import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions import com.google.firebase.FirebaseOptions
import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.FirebaseFirestore
@@ -27,8 +28,8 @@ import javax.inject.Inject
class FirebaseManager @Inject constructor(private val context: Context) { class FirebaseManager @Inject constructor(private val context: Context) {
private val sharedPreferences = private val sharedPreferencesServerConfig = context.getSharedPreferences("FirebaseConfigPrefs", Context.MODE_PRIVATE)
context.getSharedPreferences("FirebaseConfigPrefs", Context.MODE_PRIVATE) private val sharedPreferencesDev = context.getSharedPreferences("DevMode",Context.MODE_PRIVATE)
private var currentFirestore: FirebaseFirestore = FirebaseFirestore.getInstance() private var currentFirestore: FirebaseFirestore = FirebaseFirestore.getInstance()
private var currentStorage: FirebaseStorage = FirebaseStorage.getInstance() private var currentStorage: FirebaseStorage = FirebaseStorage.getInstance()
@@ -36,7 +37,7 @@ class FirebaseManager @Inject constructor(private val context: Context) {
private val defaultServers = listOf( private val defaultServers = listOf(
// i have it in different place look down // i have it in different place look down
firebaseConfig1, firebaseConfig2, firebaseConfig3, firebaseConfigProd, firebaseConfigDev , firebaseConfigQaQc, firebaseConfigPreProd
) )
init { init {
@@ -44,6 +45,18 @@ class FirebaseManager @Inject constructor(private val context: Context) {
switchServer(lastSelectedServer) switchServer(lastSelectedServer)
} }
fun setDevModeOn(state : Boolean){
sharedPreferencesDev.edit {
putBoolean( "isDevModeOn",state )
}
}
fun getDevMode(): Boolean {
return sharedPreferencesDev.getBoolean("isDevModeOn",false)
}
fun getCurrentFirestore(): FirebaseFirestore = currentFirestore fun getCurrentFirestore(): FirebaseFirestore = currentFirestore
fun getCurrentStorage(): FirebaseStorage = currentStorage fun getCurrentStorage(): FirebaseStorage = currentStorage
@@ -73,7 +86,7 @@ class FirebaseManager @Inject constructor(private val context: Context) {
} }
private fun saveSelectedServer(firebaseConfig: FirebaseConfig) { private fun saveSelectedServer(firebaseConfig: FirebaseConfig) {
with(sharedPreferences.edit()) { with(sharedPreferencesServerConfig.edit()) {
putString("selectedServerName", firebaseConfig.serverName) putString("selectedServerName", firebaseConfig.serverName)
putString("projectId", firebaseConfig.projectId) putString("projectId", firebaseConfig.projectId)
putString("appId", firebaseConfig.appId) putString("appId", firebaseConfig.appId)
@@ -93,12 +106,12 @@ class FirebaseManager @Inject constructor(private val context: Context) {
fun getLastSelectedServer(): FirebaseConfig { fun getLastSelectedServer(): FirebaseConfig {
val selectedServerName = val selectedServerName =
sharedPreferences.getString("selectedServerName", defaultServers.first().serverName) sharedPreferencesServerConfig.getString("selectedServerName", defaultServers.first().serverName)
val projectId = sharedPreferences.getString("projectId", defaultServers.first().projectId) val projectId = sharedPreferencesServerConfig.getString("projectId", defaultServers.first().projectId)
val appId = sharedPreferences.getString("appId", defaultServers.first().appId) val appId = sharedPreferencesServerConfig.getString("appId", defaultServers.first().appId)
val apiKey = sharedPreferences.getString("apiKey", defaultServers.first().apiKey) val apiKey = sharedPreferencesServerConfig.getString("apiKey", defaultServers.first().apiKey)
val storageBucket = val storageBucket =
sharedPreferences.getString("storageBucket", defaultServers.first().storageBucket) sharedPreferencesServerConfig.getString("storageBucket", defaultServers.first().storageBucket)
return FirebaseConfig( return FirebaseConfig(
serverName = selectedServerName ?: defaultServers.first().serverName, serverName = selectedServerName ?: defaultServers.first().serverName,
@@ -128,7 +141,7 @@ fun delayedRestart(context: Context) {
} }
} }
private val firebaseConfig1 = FirebaseConfig( private val firebaseConfigDev = FirebaseConfig(
serverName = "dev", serverName = "dev",
apiKey = "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I", apiKey = "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I",
appId = "1:650071678820:android:a53292637abb7c0d6c6471", appId = "1:650071678820:android:a53292637abb7c0d6c6471",
@@ -136,7 +149,7 @@ private val firebaseConfig1 = FirebaseConfig(
storageBucket = "hpos-af3cc.appspot.com" storageBucket = "hpos-af3cc.appspot.com"
) )
private val firebaseConfig2 = FirebaseConfig( private val firebaseConfigQaQc = FirebaseConfig(
serverName = "qc-qa", serverName = "qc-qa",
apiKey = "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs", apiKey = "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs",
appId = "1:1004619739289:android:3dbcefb10ea99654e5c808", appId = "1:1004619739289:android:3dbcefb10ea99654e5c808",
@@ -144,10 +157,18 @@ private val firebaseConfig2 = FirebaseConfig(
storageBucket = "hpos-qa.appspot.com" storageBucket = "hpos-qa.appspot.com"
) )
private val firebaseConfig3 = FirebaseConfig( private val firebaseConfigProd = FirebaseConfig(
serverName = "prod", serverName = "prod",
apiKey = "AIzaSyA_O0oZGzy3Kiw9fiLQ3OFPME-xQJP88vs",
appId = "1:1012719870714:android:d8d7c962d96f4097de5f43",
projectId = "hpos-prod",
storageBucket = "hpos-prod.appspot.com"
)
private val firebaseConfigPreProd = FirebaseConfig(
serverName = "pre prod",
apiKey = "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38", apiKey = "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38",
appId = "1:121176529204:android:a7bc0842f61e5095bbed61", appId = "1:121176529204:android:e6841fdac57bdc95bbed61",
projectId = "hpos-preprod", projectId = "hpos-preprod",
storageBucket = "hpos-preprod.appspot.com" storageBucket = "hpos-preprod.appspot.com"
) )

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,14 +143,19 @@ 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()
// Toast.makeText(this@KitScanActivity,"Test MAx time"+ time+"-Test count-"+kitNum,Toast.LENGTH_SHORT).show() // Toast.makeText(this@KitScanActivity,"Test MAx time"+ time+"-Test count-"+kitNum,Toast.LENGTH_SHORT).show()
// if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
// moveToNext()
// }else{
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") { if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
moveToNext() moveToNext()
}else{ }else{
@@ -209,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()
@@ -348,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

@@ -2,7 +2,7 @@ package com.example.hpostesting.presentation.main_base
class AppVersionTapManager { class AppVersionTapManager {
private var tapCount = 0 private var tapCount = 0
private val maxTapCount = 5 private val maxTapCount = 5
fun registerTap(onMaxTapsReached: () -> Unit) { fun registerTap(onMaxTapsReached: () -> Unit) {

View File

@@ -13,37 +13,59 @@
package com.example.hpostesting.presentation.main_base package com.example.hpostesting.presentation.main_base
import android.app.AlertDialog
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
import androidx.preference.PreferenceManager
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.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(
@@ -56,9 +78,10 @@ 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 {
var labname = binding.nameEditText.text.toString() var labname = binding.nameEditText.text.toString()
@@ -79,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
@@ -97,6 +122,7 @@ class SlideshowFragment : Fragment() {
// Do nothing here // Do nothing here
} }
} }
binding.spinnerCuvette.setSelection(pos) binding.spinnerCuvette.setSelection(pos)
binding.btnAddSize.setOnClickListener { binding.btnAddSize.setOnClickListener {
with(sharedPreferences.edit()) { with(sharedPreferences.edit()) {
@@ -111,26 +137,132 @@ 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() {
private lateinit var tapManager: AppVersionTapManager private lateinit var tapManager: AppVersionTapManager
private var isServerSelectionVisible = false
private lateinit var serverPreference: Preference private lateinit var serverPreference: Preference
private lateinit var currentServerPreference: Preference private lateinit var currentServerPreference: Preference
lateinit var firebaseManager: FirebaseManager lateinit var firebaseManager: FirebaseManager
private var topDevMode = false
lateinit var databaseRepository: DatabaseRepository lateinit var databaseRepository: DatabaseRepository
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
firebaseManager = FirebaseManager(requireContext()) firebaseManager = FirebaseManager(requireContext())
databaseRepository = (activity as DashboardActivity).databaseRepository databaseRepository = (activity as DashboardActivity).databaseRepository
tapManager = AppVersionTapManager() tapManager = AppVersionTapManager()
topDevMode = firebaseManager.getDevMode()
val sharedPreference = val sharedPreference =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext()) val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
val currentServer = firebaseManager.getLastSelectedServer().serverName val currentServer = firebaseManager.getLastSelectedServer().serverName
// Language Preference // Language Preference
val languagePreference = ListPreference(requireContext()).apply { val languagePreference = ListPreference(requireContext()).apply {
key = "language_preference" key = "language_preference"
@@ -140,52 +272,102 @@ class PrefsFragment : PreferenceFragmentCompat(){
entryValues = arrayOf("en", "kn", "hi") entryValues = arrayOf("en", "kn", "hi")
setDefaultValue("en") setDefaultValue("en")
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_translate_24) icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_translate_24)
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val languageCode = newValue as String val languageCode = newValue as String
updateLanguage(requireContext(), languageCode) updateLanguage(requireContext(), languageCode)
true true
} }
} }
val servers = firebaseManager.getAvailableServers()
val serverNames = servers.map { it.serverName }.toTypedArray()
val serverSelectorPreference = CustomDialogPreference(requireContext()).apply {
key = "server_preference"
title = "Select the Server"
summary = "Current server: $currentServer"
setEntries(serverNames)
setEntryValues(serverNames)
setValue(currentServer)
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_sync_24)
setOnPreferenceChangeListener { newValue ->
val preferenceConfig = servers.find { it.serverName == newValue }
switchFirebaseServer(preferenceConfig!!)
true
}
}
// Add preferences to screen
preferenceScreen.addPreference(languagePreference) preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(languagePreference)
val developerToggle = SwitchPreferenceCompat(requireContext()).apply {
title = "Developer Options"
summary = "Enable or disable developer options"
icon =
ContextCompat.getDrawable(requireContext(), R.drawable.baseline_developer_mode_24)
key = "developer_options" // Unique key for SharedPreferences
// Load toggle state from SharedPreferences
isChecked = firebaseManager.getDevMode()
setOnPreferenceChangeListener { _, newValue ->
val isEnabled = newValue as Boolean
firebaseManager.setDevModeOn(isEnabled)
if (!isEnabled) {
preferenceScreen.removePreference(this)
preferenceScreen.removePreference(serverSelectorPreference)
}
if (!firebaseManager.getDevMode() && currentServer != "prod"){
val prodConfig = servers.find { it.serverName == "prod" }
switchFirebaseServer(prodConfig!!)
}
true
}
}
val appVersionPreference = Preference(requireContext()).apply { val appVersionPreference = Preference(requireContext()).apply {
title = "App Version" title = "App Version"
summary = summary =
getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) +"->"+currentServer+"]" getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + "->" + currentServer + "]"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_info_24) icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_info_24)
setOnPreferenceClickListener { setOnPreferenceClickListener {
if ((sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN")) { tapManager.registerTap {
tapManager.registerTap { firebaseManager.setDevModeOn(true)
if (!isServerSelectionVisible) {
showServerSelection()
}
}
} else {
val devConfig = servers.find { it.serverName == "dev" }
if (firebaseManager.getDevMode() && currentServer != "dev") {
Toast.makeText(requireContext(), "Now you are a Developer", Toast.LENGTH_SHORT).show()
Toast.makeText(requireContext(), "Setting Up developer Environmnet", Toast.LENGTH_SHORT).show()
switchFirebaseServer(devConfig!!)
}
if (preferenceScreen.findPreference<SwitchPreferenceCompat>("developer_options") == null) {
preferenceScreen.addPreference(developerToggle)
}
if (preferenceScreen.findPreference<ListPreference>("server_preference") == null) {
preferenceScreen.addPreference(serverSelectorPreference)
}
developerToggle.isChecked = true
updateServerPreference(currentServer)
} }
true true
} }
} }
preferenceScreen.addPreference(appVersionPreference) preferenceScreen.addPreference(appVersionPreference)
if (firebaseManager.getDevMode()) {
developerToggle.isChecked = true // Ensure it's checked
currentServerPreference = Preference(requireContext()).apply { preferenceScreen.addPreference(developerToggle)
key = "current_server_preference" preferenceScreen.addPreference(serverSelectorPreference)
title = "Current Server"
summary = "No server selected"
isVisible = false
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_done_24)
setOnPreferenceClickListener {
// (activity as? DashboardActivity)?.sendData("hello test data")
// Toast.makeText(context, "data sent", Toast.LENGTH_SHORT).show() this was used to send the basic data as test data
true
}
} }
preferenceScreen.addPreference(currentServerPreference)
setPreferenceScreen(preferenceScreen) setPreferenceScreen(preferenceScreen)
if (isLanguageChanged) { if (isLanguageChanged) {
@@ -194,58 +376,23 @@ class PrefsFragment : PreferenceFragmentCompat(){
} }
private fun showServerSelection() { private fun updateServerPreference(newServer: String) {
val currentServer = firebaseManager.getLastSelectedServer().serverName (findPreference<CustomDialogPreference>("server_preference"))?.let { pref ->
serverPreference = Preference(requireContext()).apply { pref.setValue(newServer)
title = "Select Server" pref.summary = "Current server: $newServer"
summary = "Choose your server"
icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_sync_24)
setOnPreferenceClickListener {
showServerSelectionDialog()
true
}
} }
preferenceScreen.addPreference(serverPreference)
currentServerPreference.isVisible = true
currentServerPreference.summary = "Current Server: $currentServer"
Toast.makeText(requireContext(), "Server selection now available", Toast.LENGTH_SHORT).show()
} }
private fun showServerSelectionDialog() {
val servers = firebaseManager.getAvailableServers()
val serverNames = servers.map { it.serverName }.toTypedArray()
val builder = AlertDialog.Builder(requireContext())
builder.setTitle("Select Server")
.setItems(serverNames) { _, which ->
val selectedServer = servers[which]
switchFirebaseServer(selectedServer)
}
.setNegativeButton("Cancel", null)
.show()
}
private fun switchFirebaseServer(firebaseConfig: FirebaseConfig) { private fun switchFirebaseServer(firebaseConfig: FirebaseConfig) {
firebaseManager.switchServer(firebaseConfig) firebaseManager.switchServer(firebaseConfig)
Toast.makeText(requireContext(), "Switched to ${firebaseConfig.serverName}, Please wait for few seconds", Toast.LENGTH_SHORT).show() Toast.makeText(
Toast.makeText(requireContext(), "Restart needed restarting the app", Toast.LENGTH_SHORT).show() requireContext(),
firebaseManager.restartApp() "Switched to ${firebaseConfig.serverName}, Please wait for few seconds",
currentServerPreference.summary = "Current Server: ${firebaseConfig.serverName}" Toast.LENGTH_SHORT
).show()
} Toast.makeText(requireContext(), "Restart needed restarting the app", Toast.LENGTH_SHORT)
private fun switchCurrentServer(serverCode: String) {
Toast.makeText(requireContext(), "Switched to server: $serverCode", Toast.LENGTH_SHORT)
.show() .show()
currentServerPreference.summary = "Current Server: $serverCode" firebaseManager.restartApp()
} }
private fun updateLanguage(context: Context, languageCode: String) { private fun updateLanguage(context: Context, languageCode: String) {
@@ -275,3 +422,47 @@ class PrefsFragment : PreferenceFragmentCompat(){
} }
// CustomDialogPreference.kt
class CustomDialogPreference(context: Context) : Preference(context) {
private var entries: Array<String> = arrayOf()
private var entryValues: Array<String> = arrayOf()
private var currentValue: String = ""
private var onValueChangeListener: ((String) -> Boolean)? = null
fun setEntries(entries: Array<String>) {
this.entries = entries
}
fun setEntryValues(values: Array<String>) {
this.entryValues = values
}
fun setValue(value: String) {
currentValue = value
persistString(value)
}
fun setOnPreferenceChangeListener(listener: (String) -> Boolean) {
onValueChangeListener = listener
}
override fun onClick() {
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(title)
builder.setSingleChoiceItems(entries, entries.indexOf(currentValue)) { dialog, which ->
val newValue = entryValues[which]
if (onValueChangeListener?.invoke(newValue) == true) {
setValue(newValue)
dialog.dismiss()
}
}
builder.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
builder.show()
}
}

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
}
} }
} }
} }
@@ -1390,6 +1418,7 @@ class TrueHemeTestFragment : Fragment() {
apply() apply()
} }
} }
trueHemeTestViewModel.updateLocalData()
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
@@ -1477,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) {
@@ -1547,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"
@@ -795,4 +836,11 @@ class TrueHemeTestViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
} }
fun updateLocalData() {
viewModelScope.launch {
parseData()
hemoCubeDao.updateTest(testDetails!!)
}
}
} }

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M7,5h10v2h2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99L7,1c-1.1,0 -2,0.9 -2,2v4h2L7,5zM15.41,16.59L20,12l-4.59,-4.59L14,8.83 17.17,12 14,15.17l1.41,1.42zM10,15.17L6.83,12 10,8.83 8.59,7.41 4,12l4.59,4.59L10,15.17zM17,19L7,19v-2L5,17v4c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-4h-2v2z"/>
</vector>

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"/>

View File

@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- RadioGroup to select servers -->
<RadioGroup
android:id="@+id/radioGroupServers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical">
<!-- Radio Buttons for each server option -->
<RadioButton
android:id="@+id/radioButtonInternal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Internal" />
<RadioButton
android:id="@+id/radioButtonClinical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clinical" />
<RadioButton
android:id="@+id/radioButtonCustomer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Customer" />
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>