diff --git a/app/src/debug/res/drawable/downloads.xml b/app/src/debug/res/drawable/downloads.xml
new file mode 100644
index 0000000..37f8230
--- /dev/null
+++ b/app/src/debug/res/drawable/downloads.xml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/data/CsvWriter.kt b/app/src/main/java/com/example/hpostesting/data/CsvWriter.kt
new file mode 100644
index 0000000..c7f3c4e
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/data/CsvWriter.kt
@@ -0,0 +1,50 @@
+package com.example.hpostesting.data
+
+import android.content.Context
+import android.os.Environment
+import java.io.File
+import java.io.FileWriter
+import java.io.IOException
+
+class CsvWriter(private val context: Context) {
+
+ fun writeCsv(fileName: String, data: List>): Boolean {
+ try {
+ val filePath = File(getExternalStorageDirectory(), fileName)
+ val writer = FileWriter(filePath)
+
+ // Write header row
+ val header = arrayOf(
+ "ID",
+ "Blood Group",
+ "Birth Year",
+ "Classification Result",
+ "Test Time",
+ "User Image URL",
+ "Name"
+ )
+ writer.write(header.joinToString(",") + "\n")
+
+ // Write data rows
+ for (line in data) {
+ writer.write(line.joinToString(",") + "\n")
+ }
+
+ writer.close()
+ return true
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return false
+ }
+ }
+
+ private fun getExternalStorageDirectory(): File {
+ val folder = File(Environment.getExternalStorageDirectory(), "HposFolder")
+
+ if (!folder.exists()) {
+ folder.mkdirs()
+ }
+
+ return folder
+ }
+}
diff --git a/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt b/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt
index 7ebe1d6..189d4ef 100644
--- a/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt
+++ b/app/src/main/java/com/example/hpostesting/data/dao/HemoCubeDao.kt
@@ -26,4 +26,7 @@ interface HemoCubeDao {
@Query("UPDATE hemo_cube_test_table SET molbioFlag = :newValue WHERE _id = :id")
suspend fun updateMolbioFlag(id: String, newValue: Boolean)
+
+ @Query("UPDATE hemo_cube_test_table SET isCSVCreated = :newValue WHERE _id = :id")
+ suspend fun updateCSVFieldById(id: String, newValue: Boolean)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt b/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
index b380365..c31736d 100644
--- a/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
+++ b/app/src/main/java/com/example/hpostesting/data/dao/MyDataBase.kt
@@ -8,7 +8,7 @@ import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
-@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], version = 21, exportSchema = false)
+@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], version = 22, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
diff --git a/app/src/main/java/com/example/hpostesting/data/datasource/LocalFileDataSource.kt b/app/src/main/java/com/example/hpostesting/data/datasource/LocalFileDataSource.kt
index 39ccd8c..cdc1f38 100644
--- a/app/src/main/java/com/example/hpostesting/data/datasource/LocalFileDataSource.kt
+++ b/app/src/main/java/com/example/hpostesting/data/datasource/LocalFileDataSource.kt
@@ -1,8 +1,11 @@
package com.example.hpostesting.data.datasource
+import android.os.Environment
+import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.opencsv.CSVWriter
import java.io.File
import java.io.FileWriter
+import java.io.IOException
class LocalFileDataSource {
@@ -20,4 +23,107 @@ class LocalFileDataSource {
writer.close()
}
+
+ fun exportDataToCSV(
+ fileName: String, dataList: List
+ ): Boolean {
+ try {
+ val formattedFileName = fileName.replace(Regex("[^a-zA-Z0-9.-]"), "_") // Replace special characters with underscores
+ val filePath = File(getExternalStorageDirectory(), formattedFileName)
+ val writer = FileWriter(filePath)
+ val csvWriter = CSVWriter(writer)
+ // Write CSV header
+ val header = arrayOf(
+ "_id",
+ "name",
+ "incubationTime",
+ "bloodGroup",
+ "birthYear", // Include other fields from the data class
+ "state",
+ "abhaId",
+ "userImageURL",
+ "location",
+ "reportUploadTime",
+ "testType",
+ "testTime",
+ "testStatus",
+ "gender",
+ "localFlag", // Add more fields as necessary
+ "deviceId",
+ "appVersion",
+ "deviceSerialNumber",
+ "deviceType",
+ "kitSerial",
+ "resultData",
+ "led1Buffer",
+ "led2Buffer",
+ "led1Sample",
+ "led2Sample",
+ "led1Average",
+ "led2Average",
+ "deviceRatio",
+ "calculatedRatio",
+ "coefficients",
+ "classificationResult",
+ "errorMessages",
+ "batteryLevel"
+ )
+ csvWriter.writeNext(header)
+
+ // Write data rows
+ for (data in dataList) {
+ val row = arrayOf(
+ data._id,
+ data.name,
+ data.incubationTime,
+ data.bloodGroup,
+ data.birthYear, // Include other fields similarly
+ data.state,
+ data.abhaId,
+ data.userImageURL,
+ data.location?.toString(),
+ data.reportUploadTime ?: "",
+ data.testType ?: "",
+ data.testTime ?: "",
+ data.testStatus?.toString() ?: "",
+ data.gender,
+ data.localFlag.toString(),
+ data.deviceId ?: "",
+ data.appVersion ?: "",
+ data.deviceSerialNumber,
+ data.deviceType,
+ data.kitSerial,
+ data.resultData,
+ data.led1Buffer?.toString() ?: "",
+ data.led2Buffer?.toString() ?: "",
+ data.led1Sample?.toString() ?: "",
+ data.led2Sample?.toString() ?: "",
+ data.led1Average?.toString() ?: "",
+ data.led2Average?.toString() ?: "",
+ data.deviceRatio?.toString() ?: "",
+ data.calculatedRatio?.toString() ?: "",
+ data.coefficients ?: "",
+ data.classificationResult
+ )
+ csvWriter.writeNext(row)
+ }
+ writer.close()
+ return true
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return false
+ }
+ }
+
+ private fun getExternalStorageDirectory(): File {
+ val folder = File(Environment.getExternalStorageDirectory(), "HposFolder")
+
+ if (!folder.exists()) {
+ folder.mkdirs()
+ }
+
+ return folder
+ }
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt
index 52c7a5f..f55caf9 100644
--- a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt
+++ b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt
@@ -81,4 +81,5 @@ data class HemoCubeTestData(
var solution: String? = "",
var concentration: String? = "",
var volume: String? = "",
+ var isCSVCreated: Boolean = false
)
diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
index a434558..1cadeb6 100644
--- a/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
+++ b/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt
@@ -10,6 +10,8 @@ data class UserData(
var _id: String = "",
var name: String = "",
var incubationTime: String = "",
+ var gender: String = "",
+ var state: String = "",
var birthYear: String = "",
var abhaId: String = "",
var bloodGroup: String = "",
@@ -46,7 +48,11 @@ data class UserData(
fun UserData.toHemoCubeTestData() = HemoCubeTestData(
_id = _id,
name = name,
+ bloodGroup = bloodGroup,
birthYear = birthYear,
+ gender = gender,
+ state = state,
+ abhaId = abhaId,
userImageURL = userImageURL,
testStatus = testStatus,
location = location,
diff --git a/app/src/main/java/com/example/hpostesting/data/model/test/ViewModelModule.kt b/app/src/main/java/com/example/hpostesting/data/model/test/ViewModelModule.kt
new file mode 100644
index 0000000..7250b18
--- /dev/null
+++ b/app/src/main/java/com/example/hpostesting/data/model/test/ViewModelModule.kt
@@ -0,0 +1,29 @@
+package com.example.hpostesting.di
+
+import android.content.Context
+import com.example.hpostesting.data.repository.DatabaseRepository
+import com.example.hpostesting.data.dao.UserDao
+import com.example.hpostesting.domain.SaveRawData
+import com.example.hpostesting.domain.SaveRawDataTest
+import com.example.hpostesting.presentation.testRight.TestRightViewModel
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ViewModelComponent
+import dagger.hilt.android.qualifiers.ApplicationContext
+
+@Module
+@InstallIn(ViewModelComponent::class)
+object ViewModelModule {
+
+ @Provides
+ fun provideTestRightViewModel(
+ saveRawData: SaveRawData,
+ saveRawDataTest: SaveRawDataTest,
+ databaseRepository: DatabaseRepository,
+ userDao: UserDao,
+ context: Context
+ ): TestRightViewModel {
+ return TestRightViewModel(saveRawData, saveRawDataTest, databaseRepository, userDao, context)
+ }
+}
diff --git a/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt b/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt
index 710ae5f..40a7074 100644
--- a/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt
+++ b/app/src/main/java/com/example/hpostesting/data/repository/DatabaseRepository.kt
@@ -202,4 +202,8 @@ class DatabaseRepository @Inject constructor(
// Find the DeviceData object with the specified deviceId
return allDeviceDataList.find { it.deviceId == deviceId }
}
+
+ override fun addTestToDatabase(testDetails: UserData): Any {
+ TODO("Not yet implemented")
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/data/repository/LocalFileRepository.kt b/app/src/main/java/com/example/hpostesting/data/repository/LocalFileRepository.kt
index 6290bf0..2a8553f 100644
--- a/app/src/main/java/com/example/hpostesting/data/repository/LocalFileRepository.kt
+++ b/app/src/main/java/com/example/hpostesting/data/repository/LocalFileRepository.kt
@@ -1,6 +1,12 @@
package com.example.hpostesting.data.repository
+import android.os.Environment
import com.example.hpostesting.data.datasource.LocalFileDataSource
+import com.example.hpostesting.data.model.patient.HemoCubeTestData
+import com.opencsv.CSVWriter
+import java.io.File
+import java.io.FileWriter
+import java.io.IOException
class LocalFileRepository(private val localFileDataSource: LocalFileDataSource) {
fun saveCsvToDisk(filepath: String, contents: ArrayList>) =
@@ -8,4 +14,7 @@ class LocalFileRepository(private val localFileDataSource: LocalFileDataSource)
fun saveTextToDisk(filepath: String, contents: String) =
localFileDataSource.saveTextToDisk(filepath, contents)
+
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt b/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt
index f809295..3c60abf 100644
--- a/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt
+++ b/app/src/main/java/com/example/hpostesting/data/repository/Repository.kt
@@ -19,4 +19,6 @@ interface Repository {
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response
suspend fun getDeviceDataById(deviceId: String): DeviceData?
+ abstract fun addTestToDatabase(testDetails: UserData): Any
+// suspend fun addToDatabase(data: PatientDetails)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt b/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt
index bb0b369..ca277e2 100644
--- a/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt
+++ b/app/src/main/java/com/example/hpostesting/domain/di/AppModule.kt
@@ -170,4 +170,10 @@ object AppModule {
@Provides
@Singleton
fun provideLogFileManager(context: Context): LogFileManager = LogFileManager(context)
+
+ @Provides
+ @Singleton
+ fun provideLocalFileDataSource(): LocalFileDataSource {
+ return LocalFileDataSource()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
index f1481a5..4031909 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
@@ -1,6 +1,8 @@
package com.example.hpostesting.presentation.adapter
import android.content.Context
+import android.annotation.SuppressLint
+import android.content.res.Resources
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
index 6591f33..331bd23 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
@@ -22,11 +22,11 @@ import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.NatsManager
+import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.android.material.navigation.NavigationView
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
-import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
@@ -205,6 +205,8 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
}
+
+
override fun onResume() {
super.onResume()
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
index a2fd65e..0210a51 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
@@ -53,11 +53,9 @@ class HomeFragment : Fragment() {
private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter
- private var batLevel: Int =
- 0 // Initialize with a default value, or obtain the actual battery level
+ private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter
-
-
+ private val homeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var sharedPreference: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@@ -105,7 +103,7 @@ class HomeFragment : Fragment() {
binding.rvOrderOffline.adapter = adapter
}
}
- viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
+ viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE
@@ -120,6 +118,19 @@ class HomeFragment : Fragment() {
setUserId()
}
}
+ viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected ->
+// if (isConnected) {
+// binding.internetAvailableCL.visibility = View.VISIBLE
+// binding.internetNotAvailableCL.visibility = View.GONE
+// loadUserData()
+// setSearch()
+// checkForLocalDBData()
+// } else {
+ binding.internetAvailableCL.visibility = View.GONE
+ binding.internetNotAvailableCL.visibility = View.VISIBLE
+ setUserId()
+// }
+ }
hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
@@ -134,9 +145,32 @@ class HomeFragment : Fragment() {
binding.btnLogout.setOnClickListener {
logoutUser(requireContext())
}
+
+
binding.uploadData.setOnClickListener {
showUploadDialog(requireContext())
}
+ hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
+
+ val btnSaveLocalVisibility =
+ if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE
+
+ binding.btnSaveLocal.visibility = btnSaveLocalVisibility
+
+ binding.btnSaveLocal.setOnClickListener {
+ if (btnSaveLocalVisibility == View.VISIBLE) {
+ // Execute the action when the button is visible (testStatus is true for at least one user)
+ showDownloadDialog(requireContext())
+ } else {
+ // Handle the case when the button is not visible
+ Toast.makeText(
+ requireContext(),
+ "No test details stored locally",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ }
binding.btnNewKit.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
@@ -568,4 +602,82 @@ class HomeFragment : Fragment() {
super.onDestroyView()
_binding = null
}
+
+ private fun downloadCsv() {
+ context?.let { context ->
+ val success = homeViewModel.getLocalUserDataForCsv(context)
+ if (success) {
+ // Provide feedback to the user if needed
+ Toast.makeText(context, "CSV file downloaded successfully", Toast.LENGTH_SHORT).show()
+ } else {
+ // Handle the case where CSV file generation failed
+ Toast.makeText(context, "Failed to download CSV file", Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ private fun showDownloadDialog(context: Context) {
+ val builder = AlertDialog.Builder(context)
+ builder.setTitle(R.string.download_db_registration_title)
+ builder.setMessage(R.string.download_db_registration_message)
+
+ builder.setPositiveButton(R.string.downloadcsv) { dialog, _ ->
+ downloadLocalDBData(dialog)
+ }
+
+ builder.setNegativeButton(R.string.cancel) { dialog, _ ->
+ dialog.dismiss()
+ }
+
+ val dialog = builder.create()
+ dialog.show()
+ }
+
+
+
+
+ private fun downloadLocalDBData(dialog: DialogInterface) {
+ var csvDownloaded = false
+ hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
+ try {
+ if (!csvDownloaded) {
+
+
+ val downloadList = mutableListOf()
+
+ userDataList.forEach { userData ->
+ if(userData.testStatus == true) {
+// if (!userData.isCSVCreated) {
+ downloadList.add(userData) // Add the userData to downloadList
+ }
+// }
+ }
+
+ if (downloadList.isNotEmpty()) {
+ // Call ViewModel function to create CSV with filtered data
+ hemoCubeViewModel.createCSV(downloadList, requireContext())
+ csvDownloaded = true
+ Toast.makeText(
+ requireContext(),
+ "CSV file downloaded successfully",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ Toast.makeText(
+ requireContext(),
+ "No data to download",
+ Toast.LENGTH_SHORT
+ )
+ .show()
+ }
+ }
+
+ } catch (e: Exception) {
+ e.printStackTrace()
+ Toast.makeText(requireContext(), "Error downloading CSV file", Toast.LENGTH_SHORT).show()
+ } finally {
+ dialog.dismiss()
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/ui/home/HomeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/ui/home/HomeViewModel.kt
deleted file mode 100644
index 4b02588..0000000
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/ui/home/HomeViewModel.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.example.hpostesting.presentation.dashboard.ui.home
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-
-class HomeViewModel : ViewModel() {
-
- private val _text = MutableLiveData().apply {
- value = "This is home Fragment"
- }
- val text: LiveData = _text
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
index 0769fb2..53a442f 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt
@@ -43,6 +43,7 @@ class HemoCubeFragment : Fragment() {
private var resultData: String = ""
private var currentResultData: String = ""
private var isUsingExistingBuffer = false
+ private var loginId: String = ""
private var isTestOngoing = false
private var startListening = MutableLiveData(false)
private val testingTrace = Firebase.performance.newTrace("testing_trace")
@@ -1026,8 +1027,8 @@ class HemoCubeFragment : Fragment() {
}
private fun calculateRatio(ratio: Double): Double {
- val coefficient1 = currentDeviceData?.coefficients?.get(0) ?: 0.0
- val coefficient2 = currentDeviceData?.coefficients?.get(1) ?: 0.0
+ val coefficient1: Double = (Constants.COEFFICIENTS[loginId]?.get(0)?.get(0)) as Double
+ val coefficient2: Double = (Constants.COEFFICIENTS[loginId]?.get(1)?.get(0)) as Double
return coefficient1 * ratio + coefficient2
}
}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
index 2e89400..e674147 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
@@ -13,12 +13,14 @@ import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
+import com.example.hpostesting.data.CsvWriter
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao
+import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.log.UploadLogsResponse
import com.example.hpostesting.data.model.login.LoginRequest
@@ -37,6 +39,7 @@ import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.Repository
import com.example.hpostesting.domain.CheckUpdateWorker
import com.example.hpostesting.domain.LogFileManager
+import com.example.hpostesting.data.repository.LocalFileRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
@@ -45,6 +48,7 @@ import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.ResponseBody
import java.text.SimpleDateFormat
import java.util.Calendar
+import java.util.Date
import java.util.Locale
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@@ -56,6 +60,7 @@ class HemoCubeViewModel @Inject constructor(
private val repository: Repository,
private val databaseRepository: DatabaseRepository,
private val logFileManager: LogFileManager,
+ private val localFileDataSource: LocalFileDataSource,
context: Context,
) : ViewModel() {
var isServiceConnected = false
@@ -271,6 +276,10 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.predictedDenovixRatio = DataHolder.hemoCubeTestData?.predictedDenovixRatio
testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio
testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients
+ testDetails?.incubationTime = DataHolder.hemoCubeTestData?.incubationTime.toString()
+ testDetails?.name = DataHolder.hemoCubeTestData?.name.toString()
+ testDetails?.birthYear = DataHolder.hemoCubeTestData?.birthYear.toString()
+ testDetails?.userImageURL = DataHolder.hemoCubeTestData?.userImageURL.toString()
testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!!
testDetails?.prdClassification = DataHolder.hemoCubeTestData?.prdClassification.toString()
testDetails?.deviceRatioClass = DataHolder.hemoCubeTestData?.deviceRatioClass.toString()
@@ -403,6 +412,59 @@ class HemoCubeViewModel @Inject constructor(
hemoCubeBufferDao.updateFieldById(id = bufferId, true)
}
+
+ fun getLocalUserDataForCsv(context: Context): Boolean {
+ val localUserDataLiveData: LiveData> = hemoCubeDao.getAll()
+
+ // Observe the LiveData to get the actual data when available
+ localUserDataLiveData.observeForever { localUserData ->
+ localUserData?.let {
+ val csvData = mutableListOf>()
+
+ it.forEach { userData ->
+ csvData.add(
+ arrayOf(
+ userData._id,
+ userData.name,
+ userData.bloodGroup,
+ userData.birthYear,
+ userData.classificationResult,
+ userData.testTime.toString(),
+ userData.userImageURL
+ )
+ )
+ }
+
+ val csvWriter = CsvWriter(context)
+ csvWriter.writeCsv("userData.csv", csvData)
+
+ // Remove the observer to avoid leaks
+ localUserDataLiveData.removeObserver {}
+ }
+ }
+
+ return true // Assuming success, you might want to modify this based on your actual logic
+ }
+
+ private fun getCurrentDate(): String {
+ val dateFormat = SimpleDateFormat("dd-MM-yy", Locale.getDefault())
+ val currentDate = Date()
+ return dateFormat.format(currentDate)
+ }
+
+ fun createCSV(hemoCubeTestData: List, appContext: Context) =
+ viewModelScope.launch {
+ val fileName = "HPOS${getCurrentDate()}.csv"
+ if (localFileDataSource.exportDataToCSV(fileName, hemoCubeTestData)) {
+ hemoCubeTestData.forEach { data ->
+ data.localFlag = true
+ hemoCubeDao.updateCSVFieldById(
+ data._id,
+ true
+ )
+ }
+ }
+ }
fun getBatteryLevel(): Float? {
val batteryPct: Float? = batteryStatus?.let { intent ->
diff --git a/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightResults.kt b/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightResults.kt
index fdb8e9a..c841e16 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightResults.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightResults.kt
@@ -135,7 +135,7 @@ class TestRightResults : Fragment() {
}
}
}
- viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
+ viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isNetworkAvailable ->
val deviceStaticId = sharedPreference.getString(Constants.USER_ID, "")
if (isNetworkAvailable) {
viewModel.uploadResultToDatabase(requireContext(), true, deviceStaticId!!)
diff --git a/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightViewModel.kt
index baf2b05..19af4da 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightViewModel.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/testRight/TestRightViewModel.kt
@@ -26,6 +26,7 @@ import com.example.hpostesting.domain.TestRightResultCalculation
import com.example.hpostesting.util.MyUtils
import com.google.firebase.storage.FirebaseStorage
import dagger.hilt.android.lifecycle.HiltViewModel
+import dagger.hilt.android.scopes.ViewModelScoped
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import java.io.File
@@ -43,9 +44,10 @@ class TestRightViewModel @Inject constructor(
private val saveRawDataTest: SaveRawDataTest,
private val repository: DatabaseRepository,
private val userDao: UserDao,
- context: Context
+ context: Context?
) : ViewModel() {
+
var isServiceConnected = false
val progressBar = MutableLiveData(false)
@@ -54,10 +56,10 @@ class TestRightViewModel @Inject constructor(
val fireBaseUpload = MutableLiveData()
- val testDetails = DataHolder.selectedTest
+ var testDetails = DataHolder.selectedTest
- private val _networkStatusLiveData = NetworkStatusLiveData(context)
- val networkStatusLiveData: LiveData
+ private val _networkStatusLiveData = context?.let { NetworkStatusLiveData(it) }
+ val networkStatusLiveData: NetworkStatusLiveData?
get() = _networkStatusLiveData
val allUserData = userDao.getAll()
@@ -439,7 +441,7 @@ class TestRightViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(testDetails)) {
- is Response.Success -> {
+ is Response.Success<*> -> {
fireBaseUpload.postValue("Success")
}
@@ -448,43 +450,45 @@ class TestRightViewModel @Inject constructor(
}
}
- fun uploadResultToDatabase(context: Context, isOnline: Boolean,deviceSerialNumber: String) = viewModelScope.launch {
- val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName()
- val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName()
- testDetails?.csvPath = csvFilePath
- testDetails?.reportPath = logTxtFilePath
- testDetails?.deviceSerialNumber = deviceSerialNumber
- if (isOnline) {
- val storageRef = FirebaseStorage.getInstance().reference
- val storageTestDetailsRef = storageRef.child("${testDetails?._id}/")
+ fun uploadResultToDatabase(context: Context, isOnline: Boolean, deviceSerialNumber: String) =
+ viewModelScope.launch {
+ val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName()
+ val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName()
+ testDetails?.csvPath = csvFilePath
+ testDetails?.reportPath = logTxtFilePath
+ testDetails?.deviceSerialNumber = deviceSerialNumber
+ if (isOnline) {
+ val storageRef = FirebaseStorage.getInstance().reference
+ val storageTestDetailsRef = storageRef.child("${testDetails?._id}/")
- try {
- val csvFileUri = Uri.fromFile(File(csvFilePath))
- val logTxtFileUri = Uri.fromFile(File(logTxtFilePath))
+ try {
+ val csvFileUri = Uri.fromFile(File(csvFilePath))
+ val logTxtFileUri = Uri.fromFile(File(logTxtFilePath))
- val csvUploadTask =
- storageTestDetailsRef.child(csvFileUri.lastPathSegment!!).putFile(csvFileUri)
- .await()
- val logUploadTask = storageTestDetailsRef.child(logTxtFileUri.lastPathSegment!!)
- .putFile(logTxtFileUri).await()
+ val csvUploadTask =
+ storageTestDetailsRef.child(csvFileUri.lastPathSegment!!)
+ .putFile(csvFileUri)
+ .await()
+ val logUploadTask = storageTestDetailsRef.child(logTxtFileUri.lastPathSegment!!)
+ .putFile(logTxtFileUri).await()
- val csvUri = csvUploadTask.storage.downloadUrl.await().toString()
- val logUri = logUploadTask.storage.downloadUrl.await().toString()
- val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber }
- testDetails?.csvPath = csvUri
- testDetails?.reportPath = logUri
+ val csvUri = csvUploadTask.storage.downloadUrl.await().toString()
+ val logUri = logUploadTask.storage.downloadUrl.await().toString()
+ val serialNumber = Constants.STATICID.firstOrNull { it == deviceSerialNumber }
+ testDetails?.csvPath = csvUri
+ testDetails?.reportPath = logUri
- addResultTestToDb()
- } catch (exception: Exception) {
- // Handle the exception appropriately (e.g., log the error, display an error message)
+ addResultTestToDb()
+ } catch (exception: Exception) {
+ // Handle the exception appropriately (e.g., log the error, display an error message)
+ }
+ } else {
+ testDetails?.testTime = SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
+ ).format(Calendar.getInstance().time)
+ userDao.insertAll(testDetails!!)
}
- } else {
- testDetails?.testTime = SimpleDateFormat(
- "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
- ).format(Calendar.getInstance().time)
- userDao.insertAll(testDetails!!)
}
- }
fun bulkUploadResultToDatabase(userData: UserData) = viewModelScope.launch {
val storageRef = FirebaseStorage.getInstance().reference
@@ -519,7 +523,7 @@ class TestRightViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) {
- is Response.Success -> {
+ is Response.Success<*> -> {
fireBaseUpload.postValue("Success")
}
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 34910da..21e268f 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -100,6 +100,17 @@
app:layout_constraintTop_toBottomOf="@+id/btn_submit"
tools:listitem="@layout/offline_user_list_view" />
+
+
+
+ tools:text="UserID: Mariya" />
+
-
+ app:layout_constraintTop_toBottomOf="@id/teststatus"
+ tools:text="startedAt: yyyy-MM-dd HH:mm:ss" />
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d8672c6..9e5ded7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -193,6 +193,10 @@
Do you want to upload the local DB tests to the cloud?
Upload
Cancel
+
+ Download CSV
+ Download DB Tests
+ Do you want to download the local DB tests in CSV format?
Upload done successfully
Test Completed
Select Blood Group
diff --git a/app/src/test/java/com/example/hpostesting/HemocubeViewModelTest.kt b/app/src/test/java/com/example/hpostesting/HemocubeViewModelTest.kt
new file mode 100644
index 0000000..1a3d2e2
--- /dev/null
+++ b/app/src/test/java/com/example/hpostesting/HemocubeViewModelTest.kt
@@ -0,0 +1,60 @@
+package com.example.hpostesting
+
+import android.content.SharedPreferences
+import android.view.View
+import com.example.hpostesting.presentation.hemocube.HemoCubeFragment
+import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
+import com.example.hpostesting.presentation.hemocube.HemocubeActivity
+import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+class HemocubeViewModelTest {
+ @Mock
+ private lateinit var mockSharedPreferences: SharedPreferences
+
+ @Mock
+ private lateinit var mockActivity: HemocubeActivity // Replace with your actual Activity class
+
+ @Mock
+ private lateinit var mockBinding: FragmentHemoCubeReferenceBinding // Replace with your actual Binding class
+
+ private lateinit var hemoCubeFragment: HemoCubeFragment
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ hemoCubeFragment = HemoCubeFragment()
+ }
+
+ @Test
+ fun `handleValidResult with valid input`() {
+ // Arrange
+ val validString = "valid string"
+ val fullReadOutput = "full read output"
+ `when`(mockSharedPreferences.getString(anyString(), anyString())).thenReturn("dummy_value")
+ `when`(mockActivity.runOnUiThread(any())).thenAnswer {
+ val runnable = it.getArgument(0, Runnable::class.java)
+ runnable.run()
+ }
+
+ // Act
+ hemoCubeFragment.handleValidResult(validString, fullReadOutput)
+
+ // Assert
+ // Add appropriate assertions based on the behavior you expect
+ verify(mockSharedPreferences).edit()
+ verify(mockBinding).btnSubmit.visibility = View.VISIBLE
+ verify(mockBinding).btnSubmit.isEnabled = true
+ // Add more verifications as needed
+ }
+
+
+ // Add more test cases for different scenarios if needed
+}
\ No newline at end of file
diff --git a/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt b/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt
index 2be9212..5a95677 100644
--- a/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt
+++ b/app/src/test/java/com/example/hpostesting/TestRightViewModelTest.kt
@@ -1,19 +1,85 @@
package com.example.hpostesting
+import android.content.Context
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
-import com.example.hpostesting.data.model.PatientData
-import com.example.hpostesting.data.model.test.TestRightResultType
+import com.example.hpostesting.data.dao.UserDao
+import com.example.hpostesting.data.model.patient.UserData
+import com.example.hpostesting.data.repository.DatabaseRepository
+import com.example.hpostesting.domain.SaveRawData
+import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import junit.framework.Assert.assertEquals
+import org.junit.Before
import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
import java.math.RoundingMode
import java.text.DecimalFormat
class TestRightViewModelTest {
+<<<<<<< HEAD
// private val viewModel = TestRightViewModel()
// private val data = InputData()
//
+=======
+
+ @Mock
+ lateinit var mockContext: Context
+
+ @Mock
+ lateinit var mockRepository: DatabaseRepository
+
+ @Mock
+ lateinit var mockSaveRawData: SaveRawData
+
+ @Mock
+ lateinit var mockSaveRawDataTest: SaveRawDataTest
+
+ @Mock
+ lateinit var mockUserDao: UserDao
+
+ lateinit var viewModel: TestRightViewModel
+
+ @Before
+ fun setUp() {
+ // Initialize mocks
+ MockitoAnnotations.initMocks(this)
+
+ // Create the ViewModel with mock dependencies
+ viewModel = TestRightViewModel(mockSaveRawData,mockSaveRawDataTest,mockRepository,mockUserDao,mockContext)
+ }
+ private val data = InputData()
+
+ @Test
+ fun test_mapDeviceConstants() {
+ viewModel.mapDeviceConstants(data.inputRead)
+ assertEquals("0", DataHolder.deviceConstant!!.a)
+ assertEquals("1.69989422e-06", DataHolder.deviceConstant!!.b)
+ assertEquals("1.60642711e-01", DataHolder.deviceConstant!!.c)
+ assertEquals("3.85754470e+02", DataHolder.deviceConstant!!.d)
+ }
+
+ @Test
+ fun test_mapPixelNumberToWavelength() {
+ viewModel.mapDeviceConstants(data.inputRead)
+ viewModel.mapPixelNumberToWavelength()
+
+ val outputList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
+
+ assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, DataHolder.wavelengthToPixelArray.size)
+ assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, outputList.size)
+
+ val df = DecimalFormat("#.###")
+ df.roundingMode = RoundingMode.FLOOR
+
+ for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
+ assertEquals(df.format(outputList[i]), df.format(DataHolder.wavelengthToPixelArray[i]))
+ }
+
+ }
+
+>>>>>>> origin/Local-storing-data
// @Test
// fun test_mapDeviceConstants() {
// viewModel.mapDeviceConstants(data.inputRead)
@@ -96,6 +162,52 @@ class TestRightViewModelTest {
// println(each[0].toString() + " -> " + each[1])
// }
// }
+<<<<<<< HEAD
+=======
+
+ @Test
+ fun test_mapWavelengthToAbsorbance() {
+
+ viewModel.mapDeviceConstants(data.inputRead)
+ viewModel.mapPixelNumberToWavelength()
+ viewModel.mapIntensityValues(TestDataGenerator().getInputReferenceMapIntensityValues(), true)
+ val mapIntensityValues = viewModel.mapIntensityValues(
+ TestDataGenerator().getInputSampleMapIntensityValues(),
+ false
+ )
+ viewModel.testDetails = UserData("Surya", "2", "Male")
+ viewModel.mapWavelengthToAbsorbance()
+
+ val wavelengthList = TestDataGenerator().getOutputMapPixelNumberToWavelength()
+ val absorbanceList = TestDataGenerator().getOutputMapWavelengthToAbsorbance()
+
+ val df = DecimalFormat("#.###")
+ df.roundingMode = RoundingMode.FLOOR
+
+ assertEquals(Constants.TEST_RIGHT_TOTAL_PIXEL, viewModel.wavelengthToAbsorbance.size)
+ for (i in 0 until Constants.TEST_RIGHT_TOTAL_PIXEL){
+ assertEquals(df.format(wavelengthList[i]), df.format(viewModel.wavelengthToAbsorbance[i][0]))
+ assertEquals(df.format(absorbanceList[i]), df.format(viewModel.wavelengthToAbsorbance[i][1]))
+ }
+ }
+
+
+ @Test
+ fun testRightViewModel_calculateDataForCSV() {
+
+ viewModel.mapDeviceConstants(data.inputRead)
+ viewModel.mapPixelNumberToWavelength()
+ viewModel.mapIntensityValues(data.printForReference, true)
+ viewModel.mapIntensityValues(data.printForSample, false)
+// viewModel.patientDetails = PatientData("Surya", 2, "Male", null)
+// viewModel.calculateResults()
+ viewModel.mapWavelengthToAbsorbance()
+
+ for (each in viewModel.wavelengthToAbsorbance){
+ println(each[0].toString() + " -> " + each[1])
+ }
+ }
+>>>>>>> origin/Local-storing-data
}
\ No newline at end of file