Skip to content

Commit

Permalink
[FEAT/#49] calculate accuracy
Browse files Browse the repository at this point in the history
  • Loading branch information
chattymin committed Aug 29, 2024
1 parent 24a6013 commit 3ef9bd4
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,9 @@ class RhythmFragment : BaseFragment<FragmentRhythmBinding>(R.layout.fragment_rhy
event.dataItem.also { item ->
if (item.uri.path?.compareTo(PATH_RECORD) == 0) {
DataMapItem.fromDataItem(item).dataMap.apply {
val record = getInt(KEY_RECORD)
val record = getDouble(KEY_RECORD)
Timber.tag("okhttp").d("LISTENER : DATA RECEIVED : $record")
// TODO 여기서 기록 받아서 서버통신으로 기록
viewModel.posRhythmRecordToSaveWatch(record)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ constructor(
}
}

fun posRhythmRecordToSaveWatch(
accuracy: Double,
) {
viewModelScope.launch {
rhythmRepository.postRhythmRecord(
RecordRequestModel(
accuracy,
0,
stepCount.value
)
).onSuccess {
resetStepInfo()
_isRecordSaved.emit(true)
}.onFailure {
_isRecordSaved.emit(false)
}
}
}

private fun resetStepInfo() {
_stepCount.value = 0
_speed.value = 0.0
Expand Down
33 changes: 20 additions & 13 deletions stempo/src/main/java/com/kkkk/stempo/presentation/WatchActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ package com.kkkk.stempo.presentation
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.google.android.gms.wearable.DataClient
import com.google.android.gms.wearable.DataEvent
Expand All @@ -17,12 +19,15 @@ import com.google.android.gms.wearable.DataMapItem
import com.google.android.gms.wearable.Wearable
import com.kkkk.stempo.presentation.home.HomeScreen
import com.kkkk.stempo.presentation.manager.WearableDataManager
import com.kkkk.stempo.presentation.manager.WearableDataManager.Companion.KEY_RECORD
import com.kkkk.stempo.presentation.manager.WearableDataManager.Companion.PATH_RECORD
import com.kkkk.stempo.presentation.theme.StempoandroidTheme
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber

val LocalWearableDataManager =
staticCompositionLocalOf<WearableDataManager> {
error("No DataClient provided")
}

@AndroidEntryPoint
class WatchActivity : ComponentActivity(), DataClient.OnDataChangedListener {
override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -33,17 +38,18 @@ class WatchActivity : ComponentActivity(), DataClient.OnDataChangedListener {
setTheme(android.R.style.Theme_DeviceDefault)

setContent {
StempoandroidTheme {
HomeScreen()
CompositionLocalProvider(
LocalWearableDataManager provides WearableDataManager(
Wearable.getDataClient(
this
)
)
) {
StempoandroidTheme {
HomeScreen()
}
}
}

// TODO 이 함수로 정지 시 결과값 전송
WearableDataManager(Wearable.getDataClient(this)).sendIntToPhone(
PATH_RECORD,
KEY_RECORD,
50
)
}

override fun onResume() {
Expand All @@ -67,7 +73,7 @@ class WatchActivity : ComponentActivity(), DataClient.OnDataChangedListener {
DataMapItem.fromDataItem(item).dataMap.apply {
val bpm = getInt(KEY_BPM)
Timber.tag("okhttp").d("LISTENER : DATA RECEIVED : $bpm")
// TODO 여기서 bpm 받아서 초기값으로 설정
VIBRATION_INTERVAL = (bpm/60.0).toLong()
}
}
}
Expand All @@ -77,7 +83,8 @@ class WatchActivity : ComponentActivity(), DataClient.OnDataChangedListener {

companion object {
const val KEY_BPM = "KEY_BPM"

const val PATH_BPM = "/bpm"

var VIBRATION_INTERVAL = 500L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import android.os.Build
import android.os.PowerManager
import android.os.VibrationEffect
import android.os.Vibrator
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
Expand All @@ -21,9 +20,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
Expand All @@ -41,12 +37,16 @@ import androidx.lifecycle.flowWithLifecycle
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Text
import com.kkkk.stempo.R
import com.kkkk.stempo.presentation.LocalWearableDataManager
import com.kkkk.stempo.presentation.home.HomeViewModel.Companion.VIBRATION_DURATION
import com.kkkk.stempo.presentation.manager.WearableDataManager.Companion.KEY_RECORD
import com.kkkk.stempo.presentation.manager.WearableDataManager.Companion.PATH_RECORD

@Composable
fun HomeScreen(
viewModel: HomeViewModel = hiltViewModel(),
) {
val wearableDataManager = LocalWearableDataManager.current
lateinit var sensorManager: SensorManager
lateinit var sensorEventListener: SensorEventListener

Expand All @@ -61,9 +61,9 @@ fun HomeScreen(

sensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
Log.e("TAG", "onSensorChanged: ")
if (event.sensor.type == Sensor.TYPE_STEP_DETECTOR) {
if (!state.isPlayingMusic) return

viewModel.addStep()
}
}
Expand All @@ -72,14 +72,17 @@ fun HomeScreen(
// 정확도 변경 처리 (필요한 경우)
}
}
sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val stepDetectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)

sensorManager.registerListener(
sensorEventListener,
stepDetectorSensor,
SensorManager.SENSOR_DELAY_NORMAL
)
LaunchedEffect(key1 = Unit) {
sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val stepDetectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)

sensorManager.registerListener(
sensorEventListener,
stepDetectorSensor,
SensorManager.SENSOR_DELAY_NORMAL
)
}


LaunchedEffect(Unit) { // 화면 꺼짐 방지
Expand Down Expand Up @@ -114,6 +117,16 @@ fun HomeScreen(
)
)
}

is HomeSideEffect.EndCount -> {
wearableDataManager.sendDoubleToPhone(
PATH_RECORD,
KEY_RECORD,
sideEffect.accuracy
)

viewModel.resetStepInfo()
}
}
}
}
Expand All @@ -127,10 +140,12 @@ fun HomeScreen(
viewModel.controlMusic()
}

Text(
text = state.stepCount.toString(),
modifier = Modifier.align(Alignment.TopCenter)
)
if (state.isPlayingMusic) {
Text(
text = state.stepCount.toString(),
modifier = Modifier.align(Alignment.TopCenter)
)
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ package com.kkkk.stempo.presentation.home

sealed class HomeSideEffect {
data object Vibrate : HomeSideEffect()
data class EndCount(val accuracy: Double) : HomeSideEffect()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.kkkk.stempo.presentation.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.kkkk.domain.repository.UserRepository
import com.kkkk.stempo.presentation.WatchActivity.Companion.VIBRATION_INTERVAL
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
Expand All @@ -14,14 +15,12 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.math.max

@HiltViewModel
class HomeViewModel
@Inject
constructor(
class HomeViewModel @Inject constructor(
private val userRepository: UserRepository,
) : ViewModel() {

private val _state: MutableStateFlow<HomeState> = MutableStateFlow(HomeState())
val state: StateFlow<HomeState>
get() = _state.asStateFlow()
Expand All @@ -32,6 +31,9 @@ constructor(

private var vibrationJob: Job? = null

private val _speed = MutableStateFlow(0.0)

private val _firstStepTime = MutableStateFlow(0L)

fun controlMusic() {
_state.value = _state.value.copy(isPlayingMusic = !_state.value.isPlayingMusic)
Expand All @@ -45,19 +47,39 @@ constructor(

private fun startVibration() {
if (vibrationJob?.isActive == true) return
_state.value = _state.value.copy(stepCount = 0)

vibrationJob = viewModelScope.launch {
while (true) {
_sideEffect.emit(HomeSideEffect.Vibrate)
delay(VIBRATION_INTERVAL)
}
}
_firstStepTime.value = System.currentTimeMillis()
}

fun resetStepInfo() {
_speed.value = 0.0
}

private fun stopVibration() {
vibrationJob?.cancel()
vibrationJob = null

var accuracy =
(_state.value.stepCount.toDouble() / (VIBRATION_INTERVAL / 60 * ((System.currentTimeMillis() - _firstStepTime.value) / 10000)))
if (accuracy > 1) {
accuracy = max(2 - accuracy, 0.0)
}

viewModelScope.launch {
_sideEffect.emit(
HomeSideEffect.EndCount(
accuracy
)
)
}

_state.value = _state.value.copy(stepCount = 0)
}

Expand All @@ -66,7 +88,6 @@ constructor(
}

companion object {
const val VIBRATION_INTERVAL = 500L // TODO: Server에서 받아올 예정
const val VIBRATION_DURATION = 100L
const val VIBRATION_DURATION = 50L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import timber.log.Timber

class WearableDataManager(private val dataClient: DataClient) {

fun sendIntToPhone(path: String, key: String, value: Int): Task<DataItem> {
fun sendDoubleToPhone(path: String, key: String, value: Double): Task<DataItem> {

Timber.tag("okhttp").d("START SENDING DATA TO PHONE")

val putDataReq: PutDataRequest = PutDataMapRequest.create(path).run {
dataMap.putInt(key, value)
dataMap.putDouble(key, value)
asPutDataRequest().setUrgent()
}

Expand Down

0 comments on commit 3ef9bd4

Please sign in to comment.