实现了热量值计算
This commit is contained in:
@@ -30,8 +30,13 @@ import com.sw.dualscreen.activity.MainActivity
|
||||
import com.sw.dualscreen.databinding.ItemUserNutritionBinding
|
||||
import com.sw.dualscreen.databinding.PresentationSecondaryScreenBinding
|
||||
import com.sw.dualscreen.ext.dp
|
||||
import com.sw.dualscreen.ext.format2String
|
||||
import com.sw.dualscreen.ext.maskName
|
||||
import com.sw.dualscreen.model.response.DinnerTypeInfo
|
||||
import com.sw.dualscreen.model.response.FoodInfo
|
||||
import com.sw.dualscreen.model.response.UserNutritionData
|
||||
import com.sw.dualscreen.sdk.SensorScaleUtils
|
||||
import com.sw.dualscreen.utils.Debouncer
|
||||
import com.sw.dualscreen.utils.GlideUtils
|
||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
@@ -70,6 +75,8 @@ class SecondaryScreenPresentation(
|
||||
|
||||
// 当前食物信息
|
||||
private var currentFood: FoodInfo? = null
|
||||
private var userNutritionData: UserNutritionData? = null
|
||||
private var dinnerType: DinnerTypeInfo? = null
|
||||
private lateinit var itemUserNutritionBinding: ItemUserNutritionBinding
|
||||
private lateinit var stepChangeCallback: (Int) -> Unit
|
||||
|
||||
@@ -92,14 +99,16 @@ class SecondaryScreenPresentation(
|
||||
viewModel.nutritionData.collect {
|
||||
Timber.d("registerDataChange nutritionData = $it")
|
||||
if (it == null) return@collect
|
||||
userNutritionData = it
|
||||
step3()
|
||||
itemUserNutritionBinding.tvUserName.text = it.userName.maskName()
|
||||
itemUserNutritionBinding.tvRecommendHeat.text =
|
||||
"推荐热量:${it.recommendMin}-${it.recommendMax}"
|
||||
|
||||
itemUserNutritionBinding.customKcalColumn.setCustomHeight(280, true)
|
||||
itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent(1f, true)
|
||||
itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent(0.5f, true)
|
||||
itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent(0f, true)
|
||||
}
|
||||
}
|
||||
activity.lifecycleScope.launch {
|
||||
viewModel.dinnerTypeInfo.collect {
|
||||
dinnerType = it
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,6 +172,8 @@ class SecondaryScreenPresentation(
|
||||
|
||||
binding.tvBottomTip.visibility = View.VISIBLE
|
||||
itemUserNutritionBinding.clNutritionData.visibility = View.GONE
|
||||
stopSensorScale()
|
||||
viewModel.getDinnerType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,6 +222,7 @@ class SecondaryScreenPresentation(
|
||||
}
|
||||
binding.tvFoodInfo.text = currentFood!!.foodName
|
||||
|
||||
startSensorScale()
|
||||
|
||||
GlideUtils.loadRoundCornerImage(
|
||||
context,
|
||||
@@ -229,11 +241,82 @@ class SecondaryScreenPresentation(
|
||||
itemUserNutritionBinding.clNutritionData.visibility = View.VISIBLE
|
||||
|
||||
viewModel.getUserNutritionData(
|
||||
userId = "187c96f7bf294c08bc1d1e57b90a7210",
|
||||
userId = userNutritionData!!.userId!!,
|
||||
foodId = currentFood!!.id!!
|
||||
)
|
||||
}
|
||||
|
||||
private fun startSensorScale() {
|
||||
var lastWeight = 0.0
|
||||
val debouncer = Debouncer(1000)
|
||||
SensorScaleUtils.startScale { weight ->
|
||||
if (weight == lastWeight) return@startScale
|
||||
Timber.d("registerDataChange weight = $weight")
|
||||
lastWeight = weight
|
||||
if (currentFood == null) return@startScale
|
||||
if (userNutritionData == null) return@startScale
|
||||
if (dinnerType == null) return@startScale
|
||||
debouncer.debounce {
|
||||
val calcResultInfo = UserNutritionUtils.calculateNutrition(
|
||||
currentFood!!,
|
||||
userNutritionData!!,
|
||||
weight,
|
||||
dinnerType = dinnerType!!.dinnerType!!.dinnerType!!
|
||||
)
|
||||
Timber.d("calcResultInfo = $calcResultInfo")
|
||||
activity.runOnUiThread {
|
||||
val totalKcal = calcResultInfo.totalKcal
|
||||
val grain = calcResultInfo.grain
|
||||
val fruits = calcResultInfo.fruits
|
||||
val meat = calcResultInfo.meat
|
||||
itemUserNutritionBinding.customKcalColumn.setImageDrawable(
|
||||
true,
|
||||
totalKcal.first < totalKcal.second
|
||||
)
|
||||
itemUserNutritionBinding.totalKcalTv.text = totalKcal.second.format2String()
|
||||
itemUserNutritionBinding.customKcalColumn.setCustomHeightPercent(
|
||||
(totalKcal.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
|
||||
itemUserNutritionBinding.customFoodColumn.setImageDrawable(
|
||||
false,
|
||||
grain.first < grain.second
|
||||
)
|
||||
itemUserNutritionBinding.totalFoodTv.text = grain.second.format2String()
|
||||
itemUserNutritionBinding.customFoodColumn.setCustomHeightPercent(
|
||||
(grain.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
|
||||
itemUserNutritionBinding.customVegetableColumn.setImageDrawable(
|
||||
false,
|
||||
fruits.first < fruits.second
|
||||
)
|
||||
itemUserNutritionBinding.totalVegetableTv.text = fruits.second.format2String()
|
||||
itemUserNutritionBinding.customVegetableColumn.setCustomHeightPercent(
|
||||
(fruits.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
|
||||
itemUserNutritionBinding.customMeatColumn.setImageDrawable(
|
||||
false,
|
||||
meat.first < meat.second
|
||||
)
|
||||
itemUserNutritionBinding.totalMeatTv.text = meat.second.format2String()
|
||||
itemUserNutritionBinding.customMeatColumn.setCustomHeightPercent(
|
||||
(meat.second / 100).toFloat(),
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopSensorScale() {
|
||||
SensorScaleUtils.closeScale()
|
||||
}
|
||||
|
||||
private fun openCamera(cameraId: String) {
|
||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) !=
|
||||
PackageManager.PERMISSION_GRANTED
|
||||
@@ -328,7 +411,8 @@ class SecondaryScreenPresentation(
|
||||
|
||||
recognizeViewModel.recognizeUserId.observe(activity, Observer { userId: String? ->
|
||||
Timber.i("recognizeUserId observe userId = $userId")
|
||||
// viewModel.getUserInfoById(memberId = userId?.toInt() ?: 0)
|
||||
if (userId == null) return@Observer
|
||||
viewModel.getUserNutritionData(userId = userId, foodId = currentFood!!.id!!)
|
||||
})
|
||||
|
||||
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
|
||||
@@ -534,7 +618,7 @@ class SecondaryScreenPresentation(
|
||||
rgbCameraHelper!!.release()
|
||||
rgbCameraHelper = null
|
||||
}
|
||||
|
||||
SensorScaleUtils.closeScale()
|
||||
recognizeViewModel.destroy()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.sw.dualscreen.presentation
|
||||
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.sw.dualscreen.model.response.FoodInfo
|
||||
import com.sw.dualscreen.model.response.UserNutritionData
|
||||
|
||||
object UserNutritionUtils {
|
||||
|
||||
/**
|
||||
* 计算热量信息
|
||||
*/
|
||||
fun calculateNutrition(
|
||||
foodInfo: FoodInfo,
|
||||
userModel: UserNutritionData,
|
||||
weight: Double,
|
||||
dinnerType: String
|
||||
): CalcResultInfo {
|
||||
// 1. 初始化变量
|
||||
var foodKcal = 0.0
|
||||
var totalKcal = 0.0
|
||||
var (vegetable, meat, fruits, grain) = List(4) { 0.0 }
|
||||
|
||||
// 2. 处理食物信息
|
||||
foodKcal = calculateValue(foodInfo.stFoodInfoMaterial?.energyKcal, weight)
|
||||
|
||||
grain = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.grainValue(), weight)
|
||||
fruits = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.fruitsValue(), weight)
|
||||
vegetable = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.vegetableValue(), weight)
|
||||
meat = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.meatValue(), weight)
|
||||
|
||||
// 3. 合并用户数据
|
||||
grain += userModel.stFoodInfoPagoda?.grainValue() ?: 0.0
|
||||
fruits += userModel.stFoodInfoPagoda?.fruitsValue() ?: 0.0
|
||||
vegetable = vegetable.plus(userModel.stFoodInfoPagoda?.vegetableValue() ?: 0.0)
|
||||
meat += userModel.stFoodInfoPagoda?.meatValue() ?: 0.0
|
||||
|
||||
totalKcal = foodKcal + userModel.energyValue()
|
||||
val fruitsAndVeg = fruits + vegetable
|
||||
|
||||
// 4. 判断当餐最大热量
|
||||
val maxKcal =
|
||||
userModel.totalEnergyCalculateScoreValue() * calculateDinnerTypeRatio(dinnerType) / 10
|
||||
|
||||
val pagoda = userModel.stFoodInfoPagoda
|
||||
val calcResult = CalcResultInfo(
|
||||
totalKcal = maxKcal to totalKcal,
|
||||
grain = parseMax(pagoda?.grainRecommend) to grain,
|
||||
fruits = parseMax(pagoda?.fruitsRecommend) + parseMax(pagoda?.vegetableRecommend) to fruitsAndVeg,
|
||||
meat = parseMax(pagoda?.meatRecommend) to meat
|
||||
)
|
||||
return calcResult
|
||||
}
|
||||
|
||||
fun parseMax(recommend: String?): Double {
|
||||
if (TextUtils.isEmpty(recommend) || !recommend!!.contains("-")) return 0.0
|
||||
val (min, max) = recommend.split("-")
|
||||
return max.toDouble()
|
||||
}
|
||||
|
||||
private fun calculateDinnerTypeRatio(dinnerType: String): Int {
|
||||
return when (dinnerType) {
|
||||
"早餐", "晚餐" -> 3
|
||||
"午餐" -> 4
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateValue(nutrient: Double?, weight: Double): Double {
|
||||
return weight * (nutrient ?: 1.0)
|
||||
}
|
||||
|
||||
data class CalcResultInfo(
|
||||
var totalKcal: Pair<Double, Double>,
|
||||
var grain: Pair<Double, Double>,
|
||||
var fruits: Pair<Double, Double>,
|
||||
var meat: Pair<Double, Double>,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user