Compare commits

...

13 Commits

Author SHA1 Message Date
Mariya
37c8dde5bd Added code in manifest file for launcher 2024-02-08 15:44:27 +05:30
Mariya
5f460f6aa3 Added code for firefox and Files redirection 2024-02-08 15:30:51 +05:30
Pritimay Sarkar
ad625992a7 fix pipeline 2024-02-08 14:41:27 +05:30
Pritimay Sarkar
db518007b3 Merge branch 'dev' of https://gitlab.com/sminnovations/hpos into dev 2024-02-08 12:33:49 +05:30
Pritimay Sarkar
4d09bad516 log addititonal data in diagnostics and auto dac 2024-02-08 12:33:36 +05:30
Mariya
aad33e3907 Merge remote-tracking branch 'origin/dev' into dev 2024-02-08 11:59:06 +05:30
Mariya
52279c4419 code removed from manifest for molbio 2024-02-08 11:58:45 +05:30
Pritimay Sarkar
190a72e407 Merge branch 'dev' of https://gitlab.com/sminnovations/hpos into dev 2024-02-07 17:19:33 +05:30
Pritimay Sarkar
4aa6fb020b display device ratio and slope ratio 2024-02-07 16:25:34 +05:30
Mariya
044a545979 code added in manifest file 2024-02-07 13:01:09 +05:30
Mariya
1f9f8060cb manifest file changes and drawable file added for release apk 2024-02-06 16:48:19 +05:30
Pritimay Sarkar
4fef75b937 add new thresholds with additonal method and unit tests 2024-02-06 13:44:00 +05:30
Mariya
42b33c9397 Added code for scan , Issue fixed 2024-02-05 17:23:33 +05:30
17 changed files with 188 additions and 68 deletions

View File

@@ -14,13 +14,13 @@ android {
compileSdk 34 compileSdk 34
namespace 'in.sminnovations.hpostesting' namespace 'in.sminnovations.hpostesting'
// prod - production, preprod - preproduction, quality - qc, dev - development // dev - development, quality - qc, uat - User Acceptance Test, preprod - preproduction, prod - production
defaultConfig { defaultConfig {
applicationId "in.sminnovations.hpostesting.quality" applicationId "in.sminnovations.hpostesting.quality"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 99 versionCode 106
versionName "2.1.99" versionName "2.1.106"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -95,6 +95,7 @@
android:exported="false" android:exported="false"
android:label="@string/title_activity_dashboard" android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar" android:theme="@style/Theme.HPOS.NoActionBar"
android:screenOrientation="portrait"
tools:ignore="AppLinkUrlError,MissingClass"> tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter> <intent-filter>
@@ -119,8 +120,12 @@
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
<category android:name="android.intent.category.LAUNCHER_APP" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity

View File

@@ -8,7 +8,7 @@ object Constants {
const val ABHA_APP_PACKAGE = "in.ndhm.phr" const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTERGATION = false const val MOLBIO_INTEGRATION = false
const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in" const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in"
const val deviceProvisionPassword = "f2ab0e7f9d69" const val deviceProvisionPassword = "f2ab0e7f9d69"
const val DEVICE_ID_API = "deviceIDAPI" const val DEVICE_ID_API = "deviceIDAPI"

View File

@@ -5,5 +5,8 @@ data class DiagnosticsData (
var appVersion: String? = "", var appVersion: String? = "",
var deviceType: String = "HEMOCUBE", var deviceType: String = "HEMOCUBE",
var deviceData: String = "", var deviceData: String = "",
var devicePassword: String = "",
var deviceNatsToken: String = "",
var accessToken: String = "",
var runTime: String = "" var runTime: String = ""
) )

View File

@@ -223,26 +223,40 @@ class KitScanActivity : AppCompatActivity(), IDcsSdkApiDelegate {
notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value notifications_mask or DCSSDKDefs.DCSSDK_EVENT.DCSSDK_EVENT_BARCODE.value
sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask) sdkHandler!!.dcssdkSubsribeForEvents(notifications_mask)
mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList()) mScannerInfoList.addAll(sdkHandler!!.dcssdkGetAvailableScannersList())
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID) Log.e("scannersize",sdkHandler!!.dcssdkGetAvailableScannersList().size.toString())
if (mScannerInfoList.isNotEmpty()) {
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
} else {
Toast.makeText(this,"Error", Toast.LENGTH_LONG).show()
}
} }
fun pullTrigger() { private fun pullTrigger() {
if (!mScannerInfoList[0].isActive) { // Check if the list is not empty before accessing its elements
sdkHandler!!.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID) if (mScannerInfoList.isNotEmpty()) {
// Only proceed if the scanner is not active
if (!mScannerInfoList[0].isActive) {
sdkHandler?.dcssdkEstablishCommunicationSession(mScannerInfoList[0].scannerID)
}
val inXML = "<inArgs><scannerID> 1 </scannerID></inArgs>"
val outXML = StringBuilder()
val result: DCSSDK_RESULT =
sdkHandler!!.dcssdkExecuteCommandOpCodeInXMLForScanner(
DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER, inXML, outXML, mScannerInfoList[0].scannerID // Ensure you're using the correct scanner ID
)
if (result == DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS) {
Log.d("Scanning", "Success")
} else if (result == DCSSDK_RESULT.DCSSDK_RESULT_FAILURE) {
Log.d("Scanning", "Failed")
}
} else {
// Handle the case where the list is empty, perhaps notify the user or log an error
Log.e("ScannerError", "No scanners are connected or available.")
} }
val inXML = "<inArgs><scannerID> 1 </scannerID></inArgs>"
val outXML = StringBuilder()
val result: DCSSDK_RESULT =
sdkHandler!!.dcssdkExecuteCommandOpCodeInXMLForScanner(
DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER, inXML, outXML, 1
)
if (result == DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS) Log.d(
"Scanning",
"Success"
) else if (result == DCSSDK_RESULT.DCSSDK_RESULT_FAILURE) Log.d("Scanning", "Failed")
//new MyAsyncTask(1, DCSSDKDefs.DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_PULL_TRIGGER,null).execute(inXML);
} }
//this function is called if barcode is detected. //this function is called if barcode is detected.
override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) { override fun dcssdkEventBarcode(barcodeData: ByteArray?, barcodeType: Int, fromScannerID: Int) {
val result = String(barcodeData!!) val result = String(barcodeData!!)

View File

@@ -12,6 +12,7 @@ import android.view.ViewGroup
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Spinner import android.widget.Spinner
import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
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
@@ -30,6 +31,9 @@ class AssuranceControlsFragment: Fragment() {
binding = FragmentAssuranceControlsBinding.inflate(inflater, container, false) binding = FragmentAssuranceControlsBinding.inflate(inflater, container, false)
sharedPreferences = sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
DataHolder.hemoCubeTestData!!.solution = ""
DataHolder.hemoCubeTestData!!.volume = ""
return binding.root return binding.root
} }
@@ -42,7 +46,7 @@ class AssuranceControlsFragment: Fragment() {
// binding.btnSubmit.visibility = View.GONE // binding.btnSubmit.visibility = View.GONE
val solutionSpinner: Spinner = binding.spinnerSolutions val solutionSpinner: Spinner = binding.spinnerSolutions
val solutionOptions = arrayOf("Select solution", "Tartrazine", "AR") val solutionOptions = arrayOf("Select solution", "Tartrazine", "Acid Red")
val solutionAdapter = ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions) val solutionAdapter = ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions)
solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
solutionSpinner.adapter = solutionAdapter solutionSpinner.adapter = solutionAdapter
@@ -121,6 +125,13 @@ class AssuranceControlsFragment: Fragment() {
volumeSpinner.setSelection(volumePosition) volumeSpinner.setSelection(volumePosition)
binding.btnSubmit.setOnClickListener { binding.btnSubmit.setOnClickListener {
val selectedSolution = DataHolder.hemoCubeTestData!!.solution
val selectedVolume = DataHolder.hemoCubeTestData!!.volume
if (selectedSolution == "Select solution" || selectedVolume == "Select volume") {
Toast.makeText(requireContext(), "Please select both solution and volume", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
DataHolder.hemoCubeTestData!!.quickCapture = true DataHolder.hemoCubeTestData!!.quickCapture = true
val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val currentUnixTime = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Instant.now().epochSecond Instant.now().epochSecond

View File

@@ -105,8 +105,6 @@ class AutoDacFragment: Fragment() {
HemoCubeCommands.AUTO_DAC_COMMAND, HemoCubeCommands.AUTO_DAC_COMMAND,
object : UsbServiceListener { object : UsbServiceListener {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
} }
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
autoDacViewModel.progressBar.postValue(false) autoDacViewModel.progressBar.postValue(false)
@@ -148,6 +146,9 @@ class AutoDacFragment: Fragment() {
autoDacViewModel.addAutoDacDataToDb( autoDacViewModel.addAutoDacDataToDb(
DiagnosticsData( DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(), deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
devicePassword = sharedPreferences.getString(Constants.DEVICE_PASSWORD_API, "").toString(),
deviceNatsToken = sharedPreferences.getString(Constants.NATS_TOKEN, "").toString(),
accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString(),
deviceData = resultData, deviceData = resultData,
runTime = SimpleDateFormat( runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
@@ -169,7 +170,6 @@ class AutoDacFragment: Fragment() {
} }
} }
fun parseData(inputData: List<String>): List<Pair<String, String>> { fun parseData(inputData: List<String>): List<Pair<String, String>> {
val pattern = Regex("([A-Z]+)\\s(\\d+)") val pattern = Regex("([A-Z]+)\\s(\\d+)")
val parsedData = mutableListOf<Pair<String, String>>() val parsedData = mutableListOf<Pair<String, String>>()

View File

@@ -1,6 +1,7 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
@@ -14,12 +15,13 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.autodac.AutoDacActivity import com.example.hpostesting.presentation.autodac.AutoDacActivity
import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity import com.example.hpostesting.presentation.buffercheck.HemocubeBufferCheckActivity
import com.example.hpostesting.presentation.calibration.CalibrationActivity import com.example.hpostesting.presentation.calibration.CalibrationActivity
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity
import com.example.hpostesting.presentation.deviceinfo.DeviceActivity import com.example.hpostesting.presentation.deviceinfo.DeviceActivity
import com.example.hpostesting.presentation.deviceprovision.DeviceProvisionActivity
import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity import com.example.hpostesting.presentation.diagnostics.DiagnosticsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class GalleryFragment : Fragment() { class GalleryFragment : Fragment() {
private var _binding: FragmentGalleryBinding? = null private var _binding: FragmentGalleryBinding? = null
@@ -82,6 +84,19 @@ class GalleryFragment : Fragment() {
startActivity(Intent(requireContext(), DeviceActivity::class.java)) startActivity(Intent(requireContext(), DeviceActivity::class.java))
} }
binding.btnFirefox.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW)
intent.component = ComponentName("org.mozilla.firefox", "org.mozilla.gecko.BrowserApp")
startActivity(intent)
}
binding.btnFiles.setOnClickListener {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "file/*"
startActivity(intent)
}
userid = sharedPreferences.getString(Constants.USER_ID, "").toString() userid = sharedPreferences.getString(Constants.USER_ID, "").toString()
binding.tvSubtitle4.text = "Login ID : ${userid}" binding.tvSubtitle4.text = "Login ID : ${userid}"

View File

@@ -203,6 +203,7 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData()) hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs() hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate() hemoCubeViewModel.startPeriodicCheckUpdate()
} }
} }
} else { } else {

View File

@@ -114,7 +114,6 @@ class DeviceProvisionFragment : Fragment() {
} }
} }
private fun getDeviceId() { private fun getDeviceId() {
(activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube( (activity as DeviceProvisionActivity).mService.sendAndListenToHemoCube(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
@@ -146,14 +145,19 @@ class DeviceProvisionFragment : Fragment() {
} }
} }
fun extractV2HardwareId(input: String): String? {
val pattern = Regex("SNS\\s*(.*?)\\s*SNE")
val matchResult: MatchResult? = pattern.find(input)
return matchResult?.groups?.get(1)?.value
}
private fun handleUsbData() { private fun handleUsbData() {
when { when {
resultData.contains("SNE") -> { resultData.contains("SNE") -> {
val pattern = Regex("HPP1-\\d{4}") val hardwareId = extractV2HardwareId(resultData)
val matchResult = pattern.find(resultData)
val hardwareId = matchResult?.value
if (hardwareId.toString().length == 9) { if (!hardwareId.isNullOrBlank()) {
with(sharedPreferences.edit()) { with(sharedPreferences.edit()) {
putString(Constants.DEVICE_ID, hardwareId) putString(Constants.DEVICE_ID, hardwareId)
apply() apply()

View File

@@ -148,6 +148,9 @@ class DiagnosticsFragment : Fragment() {
if (resultData.contains("END") || fullReadOutput.contains("END")) { if (resultData.contains("END") || fullReadOutput.contains("END")) {
diagnosticsViewModel.addDiagnosticsDataToDb(DiagnosticsData( diagnosticsViewModel.addDiagnosticsDataToDb(DiagnosticsData(
deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(), deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString(),
devicePassword = sharedPreferences.getString(Constants.DEVICE_PASSWORD_API, "").toString(),
deviceNatsToken = sharedPreferences.getString(Constants.NATS_TOKEN, "").toString(),
accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString(),
deviceData = resultData, deviceData = resultData,
runTime = SimpleDateFormat( runTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()

View File

@@ -153,7 +153,7 @@ class HemoCubeFragment : Fragment() {
when (it) { when (it) {
is Result.Success -> { is Result.Success -> {
uploadedToMolbio = true uploadedToMolbio = true
if (Constants.MOLBIO_INTERGATION) { if (Constants.MOLBIO_INTEGRATION) {
it.data.data?.get(0)?.rawData?.let { it1 -> it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag( hemoCubeViewModel.updateMolbioFlag(
it1._id it1._id
@@ -805,8 +805,8 @@ class HemoCubeFragment : Fragment() {
calculatedPredictedDenovixRatio = fittedAbs3.div(fittedAbs1) calculatedPredictedDenovixRatio = fittedAbs3.div(fittedAbs1)
val slope = (led1Average - led2Average) / (435 - 415) val slope = (led4Average - led1Average) / (431-411)
val calculatedSlopeRatio = abs(led3Average / slope) val calculatedSlopeRatio = abs(led2Average / slope)
val slopeClass = slopeRatioClassification(calculatedSlopeRatio) val slopeClass = slopeRatioClassification(calculatedSlopeRatio)
if (fittedAbs1 <= fittedAbs2) { if (fittedAbs1 <= fittedAbs2) {
@@ -874,8 +874,8 @@ class HemoCubeFragment : Fragment() {
this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio) this.prdClassification = absorbanceBasedClassification(predictedDenovixRatio)
this.deviceRatioClass = deviceRatioClassification(deviceRatio) this.deviceRatioClass = deviceRatioClassification(deviceRatio)
this.slopeRatioClass = slopeClass this.slopeRatioClass = slopeClass
this.classificationResult = deviceRatioClass //findResult(calculatedRatio) this.classificationResult = findResultWithAdditionalMethods(deviceRatio, deviceRatioClass, slopeRatio)
hemoCubeViewModel.messages.postValue("${this.deviceRatioClass} ${if (led4Average < 0.17) " - Low Hb" else ""}\n") hemoCubeViewModel.messages.postValue("${this.classificationResult} \n Device Ratio: ${"%.3f".format(this.deviceRatio)} \n Slope Ratio: ${"%.3f".format(this.slopeRatio)}")
if (DataHolder.hemoCubeTestData?.testType == "HB") if (DataHolder.hemoCubeTestData?.testType == "HB")
hemoCubeViewModel.messages.postValue("Hb: $calculatedHb4") hemoCubeViewModel.messages.postValue("Hb: $calculatedHb4")
this.errorMessages = testState.allErrorMessages this.errorMessages = testState.allErrorMessages
@@ -909,50 +909,36 @@ class HemoCubeFragment : Fragment() {
} }
} }
fun findResult(calculatedRatio: Double?): String { fun findResultWithAdditionalMethods(deviceRatio: Double?, deviceRatioClass: String?, slopeRatio: Double?): String {
try { try {
hemoCubeViewModel.messages.postValue("result classification") // hemoCubeViewModel.messages.postValue("post classification checks")
if (calculatedRatio != null) { if (deviceRatio != null) {
if (calculatedRatio < 0.05) if (slopeRatio != null) {
return getString(R.string.error_repeat_test_higher_volume) if (deviceRatioClass == "Normal" && slopeRatio > 45.0)
if (calculatedRatio in 0.05..0.155) { return "Negative Borderline, Repeat Test"
return getString(R.string.normal)
} }
if (calculatedRatio in 0.155..0.175)
return getString(R.string.negative_borderline)
if (calculatedRatio in 0.175..0.22)
return getString(R.string.sickle_cell_trait)
if (calculatedRatio in 0.22..0.25)
return getString(R.string.positive_for_sickle_cell)
if (calculatedRatio in 0.25..0.35)
return getString(R.string.sickle_cell_disease)
if (calculatedRatio > 0.35)
return getString(R.string.error_repeat_test_lower_volume)
} else {
return getString(R.string.invalid)
} }
} catch (e: Exception) { } catch (e: Exception) {
showToast(R.string.error_classification) handleException(e)
Firebase.crashlytics.recordException(e) return "Error"
return getString(R.string.error)
} }
return getString(R.string.invalid) return deviceRatioClass.toString()
} }
fun deviceRatioClassification(ratio: Double?): String { fun deviceRatioClassification(ratio: Double?): String {
try { try {
if (ratio != null) { if (ratio != null) {
if (ratio in 0.1..0.29) { if (ratio in 0.001..0.23) {
// setSubtitleTextColor(R.color.green_2) // setSubtitleTextColor(R.color.green_2)
return "Normal" return "Normal"
} }
if (ratio in 0.29..0.32) if (ratio in 0.23..0.24)
return "Negative Borderline, Repeat Test" return "Negative Borderline, Repeat Test"
if (ratio in 0.32..0.35) if (ratio in 0.24..0.29)
return "Sickle Cell Trait" return "Sickle Cell Trait"
if (ratio in 0.35..0.38) if (ratio in 0.29..0.32)
return "Positive for Sickle Cell. HPLC for Confirmation" return "Positive for Sickle Cell. HPLC for Confirmation"
if (ratio in 0.38..0.5) if (ratio in 0.32..Double.POSITIVE_INFINITY)
return "Sickle Cell Disease" return "Sickle Cell Disease"
} else { } else {
return "Invalid" return "Invalid"

View File

@@ -156,7 +156,7 @@ class TrueHemeFragment : Fragment() {
when (it) { when (it) {
is Result.Success -> { is Result.Success -> {
uploadedToMolbio = true uploadedToMolbio = true
if (Constants.MOLBIO_INTERGATION) { if (Constants.MOLBIO_INTEGRATION) {
it.data.data?.get(0)?.rawData?.let { it1 -> it.data.data?.get(0)?.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag( hemoCubeViewModel.updateMolbioFlag(
it1._id it1._id

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="@color/primary"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

View File

@@ -108,4 +108,33 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_calibration" /> app:layout_constraintTop_toBottomOf="@id/btn_calibration" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_firefox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/Firefox"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_deviceProvision" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_files"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:clickable="false"
android:text="@string/Files"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_firefox" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -115,6 +115,8 @@
<string name="assurance_controls">Quality Assurance</string> <string name="assurance_controls">Quality Assurance</string>
<string name="calibration">Calibration</string> <string name="calibration">Calibration</string>
<string name="deviceProvision">Device Provision</string> <string name="deviceProvision">Device Provision</string>
<string name="Firefox">Firefox</string>
<string name="Files">Files</string>
<string name="deviceinfo">Device Information</string> <string name="deviceinfo">Device Information</string>
<string name="place_buffer">Start</string> <string name="place_buffer">Start</string>
<string name="Start_Sample">Start Sample</string> <string name="Start_Sample">Start Sample</string>

View File

@@ -318,28 +318,28 @@ class HemoCubeFragmentTest {
@Test @Test
fun testDeviceRatioClassificationNormal() { fun testDeviceRatioClassificationNormal() {
val ratio = 0.25 val ratio = 0.22
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Normal", result) assertEquals("Normal", result)
} }
@Test @Test
fun testDeviceRatioClassificationNegativeBorderline() { fun testDeviceRatioClassificationNegativeBorderline() {
val ratio = 0.31 val ratio = 0.235
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Negative Borderline, Repeat Test", result) assertEquals("Negative Borderline, Repeat Test", result)
} }
@Test @Test
fun testDeviceRatioClassificationSickleCellTrait() { fun testDeviceRatioClassificationSickleCellTrait() {
val ratio = 0.34 val ratio = 0.25
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Trait", result) assertEquals("Sickle Cell Trait", result)
} }
@Test @Test
fun testDeviceRatioClassificationPositiveForSickleCell() { fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.37 val ratio = 0.31
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result) assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
} }
@@ -357,4 +357,46 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Invalid", result) assertEquals("Invalid", result)
} }
@Test
fun findResultWithAdditionalMethods_ValidInput_ReturnsNegativeBorderlineRepeatTest() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)).thenReturn("Negative Borderline, Repeat Test")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)
assertEquals("Negative Borderline, Repeat Test", result)
}
@Test
fun findResultWithAdditionalMethods_NormalDeviceRatio_ReturnsNormalBelowSlopeRatioThreshold() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 70.0)).thenReturn("Negative Borderline, Repeat Test")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Normal", 30.0)
assertEquals("Normal", result)
}
@Test
fun findResultWithAdditionalMethods_NBL_ReturnsNBL() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Negative Borderline, Repeat Test", 70.0)
assertEquals("Negative Borderline, Repeat Test", result)
}
@Test
fun findResultWithAdditionalMethods_SCT_ReturnsSCT() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Trait", 70.0)
assertEquals("Sickle Cell Trait", result)
}
@Test
fun findResultWithAdditionalMethods_PBL_ReturnsPBL() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Positive for Sickle Cell. HPLC for Confirmation", 70.0)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
}
@Test
fun findResultWithAdditionalMethods_SCD_ReturnsSCD() {
// `when`(hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Abnormal", 70.0)).thenReturn("Invalid")
val result = hemoCubeFragment.findResultWithAdditionalMethods(0.5, "Sickle Cell Disease", 70.0)
assertEquals("Sickle Cell Disease", result)
}
} }