1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-06-07 07:19:54 +00:00

misc: Cleanup Database

This commit is contained in:
Florian Bouillon 2023-01-07 23:34:15 +01:00
parent 9e463d7fd3
commit a9da9198be
Signed by: Florian Bouillon
GPG Key ID: BEEAF3722D0EBF64
13 changed files with 157 additions and 57 deletions

View File

@ -5,8 +5,6 @@ import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.dzeio.openhealth.data.food.Food
import com.dzeio.openhealth.data.food.FoodDao
import com.dzeio.openhealth.data.step.Step
@ -16,6 +14,11 @@ import com.dzeio.openhealth.data.water.WaterDao
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.data.weight.WeightDao
/**
* ROOM SQLite database for the application
*
* It may be replaced if I want to fully encrypt the database
*/
@Database(
entities = [
Weight::class,
@ -23,16 +26,16 @@ import com.dzeio.openhealth.data.weight.WeightDao
Step::class,
Food::class
],
// TODO: go back to version 1 when the app is published
version = 3,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 1, to = 2)
AutoMigration(from = 1, to = 2),
AutoMigration(from = 2, to = 3)
]
)
abstract class AppDatabase : RoomDatabase() {
// private val PREPOPULATE_DATA = listOf(Thing("1", "val"), Thing("2", "val 2"))
abstract fun weightDao(): WeightDao
abstract fun waterDao(): WaterDao
abstract fun stepDao(): StepDao
@ -40,42 +43,29 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun foodDao(): FoodDao
companion object {
/**
* database name duh
*/
private const val DATABASE_NAME = "open_health"
// For Singleton instantiation
@Volatile
private var instance: AppDatabase? = null
// get the Database instance
fun getInstance(context: Context): AppDatabase {
return instance ?: synchronized(this) {
instance ?: buildDatabase(context).also { instance = it }
}
}
// Create and pre-populate the database. See this article for more details:
// https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1#4785
/**
* build teh database
*/
private fun buildDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.addMigrations(MIGRATION_2_3)
// .addCallback(object : Callback() {
// override fun onCreate(db: SupportSQLiteDatabase) {
// super.onCreate(db)
// // moving to a new thread
// Executors.newSingleThreadExecutor().execute {
// getInstance(context).thingDao()
// .insert(PREPOPULATE_DATA)
// }
// }
// })
// .addMigrations(MIGRATION_2_3)
.build()
}
private val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Food ADD COLUMN serving TEXT NOT NULL")
database.execSQL("ALTER TABLE Food ADD COLUMN image TEXT")
database.execSQL("ALTER TABLE Food ")
}
}
}
}

View File

@ -1,23 +0,0 @@
package com.dzeio.openhealth.data.converters
import androidx.room.TypeConverter
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
object TiviTypeConverters {
private val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME
@TypeConverter
@JvmStatic
fun toOffsetDateTime(value: String?): OffsetDateTime? {
return value?.let {
return formatter.parse(value, OffsetDateTime::from)
}
}
@TypeConverter
@JvmStatic
fun fromOffsetDateTime(date: OffsetDateTime?): String? {
return date?.format(formatter)
}
}

View File

@ -10,23 +10,62 @@ import java.util.TimeZone
data class Food(
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
/**
* The product name
*/
var name: String,
/**
* The product serving text
*
* ex: `250ml`, `520g`, etc
*/
var serving: String,
/**
* the quantity taken by the user
*/
var quantity: Float,
/**
* the quantity of proteins there is for 100 quantity
*/
var proteins: Float,
/**
* the quantity of carbohydrates there is for 100 quantity
*/
var carbohydrates: Float,
/**
* the quantity of fat there is for 100 quantity
*/
var fat: Float,
/**
* the quantity of energy there is for 100 quantity
*/
var energy: Float,
/**
* the url of the image
* the url of the image of the product
*/
var image: String?,
/**
* When the entry was added to our Database
*/
var timestamp: Long = Calendar.getInstance(TimeZone.getTimeZone("UTC")).timeInMillis,
) {
companion object {
/**
* Transform an OpenFoodFact product to use for our Database
*/
fun fromOpenFoodFact(food: OFFProduct, quantity: Float? = null): Food {
// try to know how much was eaten by the user if not said
var eaten = quantity ?: food.servingQuantity ?: food.productQuantity ?: 0f
if (eaten == 0f) {
if (food.servingQuantity != null && food.servingQuantity != 0f) {
@ -37,11 +76,13 @@ data class Food(
}
return Food(
name = food.name,
// do some slight edit on the serving to remove strange entries like `100 g`
serving = (food.servingSize ?: food.quantity ?: "unknown").replace(Regex(" +"), ""),
quantity = eaten,
proteins = food.nutriments.proteins,
carbohydrates = food.nutriments.carbohydrates,
fat = food.nutriments.fat,
// handle case where the energy is not given in kcal but only in kj
energy = food.nutriments.energy ?: (food.nutriments.energyKJ * 0.2390057361).toFloat(),
image = food.image
)

View File

@ -10,9 +10,8 @@ class FoodRepository @Inject constructor(
private val dao: FoodDao,
private val offSource: OpenFoodFactService
) {
suspend fun findOnlineFood(name: String): Response<OFFResult> {
return offSource.searchProducts(name)
}
suspend fun searchOpenFoodFact(name: String): Response<OFFResult> =
offSource.searchProducts(name)
fun getAll() = dao.getAll()

View File

@ -3,14 +3,33 @@ package com.dzeio.openhealth.data.openfoodfact
import com.google.gson.annotations.SerializedName
data class OFFNutriments(
/**
* the quantity of carbohydrates in a 100g serving
*/
@SerializedName("carbohydrates_100g")
var carbohydrates: Float,
/**
* the energy in kcal in a 100g serving
*/
@SerializedName("energy-kcal_100g")
var energy: Float?,
/**
* the energy KL in a 100g serving
*/
@SerializedName("energy-kj_100g")
var energyKJ: Float,
/**
* the quantity of fat in a 100g serving
*/
@SerializedName("fat_100g")
var fat: Float,
/**
* the quantity of proteins in a 100g serving
*/
@SerializedName("proteins_100g")
var proteins: Float
)

View File

@ -3,26 +3,51 @@ package com.dzeio.openhealth.data.openfoodfact
import com.google.gson.annotations.SerializedName
data class OFFProduct(
/**
* the OFF product id
*/
@SerializedName("_id")
var id: String,
/**
* the product name
*/
@SerializedName("product_name")
var name: String,
/**
* the size of a serving
*/
@SerializedName("serving_size")
var servingSize: String?,
/**
* the size of a serving without the `g`, `ml`, etc
*/
@SerializedName("serving_quantity")
var servingQuantity: Float?,
/**
* the size of a serving
*/
@SerializedName("quantity")
var quantity: String?,
/**
* the size of a serving without the `g`, `ml`, etc
*/
@SerializedName("product_quantity")
var productQuantity: Float?,
/**
* the product nutriments
*/
@SerializedName("nutriments")
var nutriments: OFFNutriments,
/**
* the product image
*/
@SerializedName("image_url")
var image: String?
)

View File

@ -3,6 +3,9 @@ package com.dzeio.openhealth.data.openfoodfact
import com.google.gson.annotations.SerializedName
data class OFFResult(
/**
* the list of products
*/
@SerializedName("products")
var products: List<OFFProduct>
)

View File

@ -1,5 +1,6 @@
package com.dzeio.openhealth.data.openfoodfact
import com.dzeio.openhealth.BuildConfig
import com.google.gson.GsonBuilder
import retrofit2.Response
import retrofit2.Retrofit
@ -30,11 +31,17 @@ interface OpenFoodFactService {
}
}
@Headers("User-Agent: OpenHealth - Android - Version 1.0 - https://github.com/dzeiocom/OpenHealth")
/**
* Search a product by it's name
*/
@Headers("User-Agent: OpenHealth - Android - Version ${BuildConfig.VERSION_NAME} - https://github.com/dzeiocom/OpenHealth")
@GET("/cgi/search.pl?json=true&fields=_id,nutriments,product_name,serving_quantity,serving_size,quantity,product_quantity,image_url&action=process")
suspend fun searchProducts(@Query("search_terms2") name: String): Response<OFFResult>
@Headers("User-Agent: OpenHealth - Android - Version 1.0 - https://github.com/dzeiocom/OpenHealth")
/**
* Search a product by it's barcode
*/
@Headers("User-Agent: OpenHealth - Android - Version ${BuildConfig.VERSION_NAME} - https://github.com/dzeiocom/OpenHealth")
@GET("/api/v2/search?fields=_id,nutriments,product_name,serving_quantity")
suspend fun findByCode(@Query("code") code: String): Response<OFFResult>

View File

@ -12,6 +12,10 @@ import java.util.TimeZone
@Entity()
data class Step(
@PrimaryKey(autoGenerate = true) var id: Long = 0,
/**
* the raw number of step
*/
var value: Int = 0,
/**
* Timestamp down to an hour
@ -20,6 +24,12 @@ data class Step(
*/
@ColumnInfo(index = true)
var timestamp: Long = 0,
/**
* the source for the Entry
*
* note: Unused currently but kept for future usage
*/
var source: String = "OpenHealth"
) {

View File

@ -12,6 +12,11 @@ import com.dzeio.openhealth.Application
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.runBlocking
/**
* Class that allows us to get Sensor datas for the internal step counter
*
* TODO: rewrite to use the new libs
*/
class StepSource(
private val context: Context,
private val callback: ((Float) -> Unit)? = null

View File

@ -11,9 +11,23 @@ import java.util.TimeZone
@Entity()
data class Water(
@PrimaryKey(autoGenerate = true) var id: Long = 0,
/**
* the quantity of water in ML drank by the user
*/
var value: Int = 0,
/**
* when the water was drank precise to the day
*/
@ColumnInfo(index = true)
var timestamp: Long = 0,
/**
* the source for the Entry
*
* note: Unused currently but kept for future usage
*/
var source: String = "OpenHealth"
) {
init {

View File

@ -14,9 +14,19 @@ data class Weight(
* Store the weight in kilograms
*/
var weight: Float = 0f,
/**
* when the weight was taken precise to the millisecond
*/
@ColumnInfo(index = true)
var timestamp: Long = System.currentTimeMillis(),
var source: String = ""
/**
* the source for the Entry
*
* note: Unused currently but kept for future usage
*/
var source: String = "OpenHealth"
) {
fun formatTimestamp(): String = getDateInstance().format(Date(timestamp));
}