Skip to content

Commit e6228d2

Browse files
bngshyonghanJu
andcommitted
✨ RunningWorker 기능 구현 마무리 및 location listener로 전환
Co-authored-by: yonghanJu <[email protected]>
1 parent e67b922 commit e6228d2

File tree

3 files changed

+191
-97
lines changed

3 files changed

+191
-97
lines changed

presentation/src/main/java/com/whyranoid/presentation/running/RunningActivity.kt

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package com.whyranoid.presentation.running
22

33
import android.os.Bundle
44
import androidx.activity.viewModels
5-
import com.naver.maps.geometry.LatLng
6-
import com.naver.maps.map.CameraUpdate
75
import com.naver.maps.map.MapView
86
import com.naver.maps.map.NaverMap
97
import com.naver.maps.map.OnMapReadyCallback
8+
import com.naver.maps.map.overlay.OverlayImage
9+
import com.naver.maps.map.overlay.PathOverlay
1010
import com.whyranoid.presentation.R
1111
import com.whyranoid.presentation.base.BaseActivity
1212
import com.whyranoid.presentation.databinding.ActivityRunningBinding
@@ -23,38 +23,38 @@ internal class RunningActivity :
2323

2424
private lateinit var mapView: MapView
2525
private lateinit var naverMap: NaverMap
26+
private lateinit var paths: MutableList<PathOverlay>
2627

2728
override fun onCreate(savedInstanceState: Bundle?) {
2829
super.onCreate(savedInstanceState)
29-
mapView = binding.mapView
30-
31-
mapView.onCreate(savedInstanceState)
32-
mapView.getMapAsync(this)
3330

34-
binding.vm = viewModel
35-
36-
repeatWhenUiStarted {
37-
viewModel.runningState.collect { runningState ->
38-
with(runningState.runningData) {
39-
binding.tvStartTime.text = Date(startTime).dateToString("hh:mm")
40-
binding.tvRunningTime.text =
41-
String.format("%d:%02d", runningTime / 60, runningTime % 60)
42-
binding.tvTotalDistance.text = String.format("%.4f m", totalDistance)
43-
binding.tvPace.text = String.format("%.4f km/h", pace * 3.6)
44-
}
45-
}
46-
}
31+
initViews(savedInstanceState)
32+
observeState()
4733
}
4834

4935
override fun onMapReady(naverMap: NaverMap) {
5036
this.naverMap = naverMap
5137

52-
naverMap.maxZoom = 18.0
53-
naverMap.minZoom = 10.0
38+
with(naverMap) {
39+
maxZoom = MAP_MAX_ZOOM
40+
minZoom = MAP_MIN_ZOOM
41+
uiSettings.isLocationButtonEnabled = false
42+
uiSettings.isZoomControlEnabled = false
43+
locationOverlay.isVisible = true
44+
locationOverlay.icon = OverlayImage.fromResource(R.drawable.kong)
45+
locationOverlay.iconWidth = MAP_ICON_SIZE
46+
locationOverlay.iconHeight = MAP_ICON_SIZE
47+
}
48+
49+
paths = mutableListOf()
5450

55-
naverMap.moveCamera(CameraUpdate.scrollAndZoomTo(LatLng(37.498095, 127.027610), 15.0))
56-
naverMap.uiSettings.isLocationButtonEnabled = false
57-
naverMap.uiSettings.isZoomControlEnabled = false
51+
repeatWhenUiStarted {
52+
viewModel.runningState.collect { runningState ->
53+
makeNewPath(runningState)
54+
updateRunnerPosition(runningState)
55+
updatePathsOverlay(runningState)
56+
}
57+
}
5858
}
5959

6060
override fun onStart() {
@@ -91,4 +91,60 @@ internal class RunningActivity :
9191
super.onLowMemory()
9292
mapView.onLowMemory()
9393
}
94+
95+
private fun initViews(savedInstanceState: Bundle?) {
96+
mapView = binding.mapView
97+
98+
mapView.onCreate(savedInstanceState)
99+
mapView.getMapAsync(this)
100+
101+
binding.vm = viewModel
102+
}
103+
104+
private fun observeState() {
105+
repeatWhenUiStarted {
106+
viewModel.runningState.collect { runningState ->
107+
with(runningState.runningData) {
108+
binding.tvStartTime.text = Date(startTime).dateToString("hh:mm")
109+
binding.tvRunningTime.text =
110+
String.format("%d:%02d", runningTime / 60, runningTime % 60)
111+
binding.tvTotalDistance.text = String.format("%.4f m", totalDistance)
112+
binding.tvPace.text = String.format("%.4f km/h", pace * 3.6)
113+
}
114+
}
115+
}
116+
}
117+
118+
private fun provideMogakrunPath(): PathOverlay {
119+
return PathOverlay().apply {
120+
color = getColor(R.color.mogakrun_secondary_light)
121+
width = 20
122+
}
123+
}
124+
125+
private fun makeNewPath(runningState: RunningState) {
126+
while (paths.size < runningState.runningData.runningPositionList.size) {
127+
paths.add(provideMogakrunPath())
128+
}
129+
}
130+
131+
private fun updateRunnerPosition(runningState: RunningState) {
132+
runningState.runningData.runningPositionList.last().lastOrNull()?.let {
133+
naverMap.locationOverlay.position = it.toLatLng()
134+
}
135+
}
136+
137+
private fun updatePathsOverlay(runningState: RunningState) {
138+
if (runningState.runningData.runningPositionList.last().size >= 2) {
139+
paths.last().coords =
140+
runningState.runningData.runningPositionList.last().map { it.toLatLng() }
141+
paths.last().map = naverMap
142+
}
143+
}
144+
145+
companion object {
146+
const val MAP_MAX_ZOOM = 18.0
147+
const val MAP_MIN_ZOOM = 10.0
148+
const val MAP_ICON_SIZE = 80
149+
}
94150
}

presentation/src/main/java/com/whyranoid/presentation/running/RunningRepository.kt

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,27 @@ class RunningRepository @Inject constructor() {
1515
)
1616
val runningState get() = _runningState.asStateFlow()
1717

18-
fun startRunning(startPosition: RunningPosition) {
18+
fun startRunning() {
1919
if (runningState.value is RunningState.NotRunning) {
2020
_runningState.value = RunningState.Running(
2121
RunningData(
2222
startTime = System.currentTimeMillis(),
2323
runningTime = 0,
2424
totalDistance = 0.0,
2525
pace = 0.0,
26-
runningPositionList = listOf(startPosition)
26+
runningPositionList = listOf(emptyList())
2727
)
2828
)
2929
}
3030
}
3131

3232
fun pauseRunning() = runCatching {
3333
if (runningState.value is RunningState.Running) {
34-
_runningState.value = RunningState.Paused(
35-
runningState.value.runningData
34+
val newRunningData = runningState.value.runningData.copy(
35+
runningPositionList = runningState.value.runningData.runningPositionList.toMutableList()
36+
.also { it.add(emptyList()) }
3637
)
38+
_runningState.value = RunningState.Paused(newRunningData)
3739
} else {
3840
throw Exception("상태가 잘못되었습니다.")
3941
}
@@ -68,18 +70,23 @@ class RunningRepository @Inject constructor() {
6870
fun setRunningState(runningPosition: RunningPosition) {
6971
if (_runningState.value is RunningState.Running) {
7072
val prevRunningData = _runningState.value.runningData
71-
val newRunningTime = prevRunningData.runningTime + 1
73+
val newRunningTime = prevRunningData.runningTime
7274
val distance = FloatArray(1)
75+
7376
Location.distanceBetween(
74-
prevRunningData.runningPositionList.last().latitude,
75-
prevRunningData.runningPositionList.last().longitude,
77+
prevRunningData.runningPositionList.last().lastOrNull()?.latitude
78+
?: runningPosition.latitude,
79+
prevRunningData.runningPositionList.last().lastOrNull()?.longitude
80+
?: runningPosition.longitude,
7681
runningPosition.latitude,
7782
runningPosition.longitude,
7883
distance
7984
)
8085
val newTotalDistance = prevRunningData.totalDistance + distance.first()
8186
val newPace = newTotalDistance / newRunningTime
82-
val newRunningPositionList = prevRunningData.runningPositionList.plus(runningPosition)
87+
val newRunningPositionList =
88+
prevRunningData.runningPositionList.toList().map { it.toMutableList() }
89+
.also { it[it.lastIndex].add(runningPosition) }
8390

8491
_runningState.value = RunningState.Running(
8592
RunningData(
@@ -92,6 +99,12 @@ class RunningRepository @Inject constructor() {
9299
)
93100
}
94101
}
102+
103+
fun tick() {
104+
_runningState.value = _runningState.value.let {
105+
it.runningData.copy(runningTime = it.runningData.runningTime + 1)
106+
}.let { RunningState.Running(it) }
107+
}
95108
}
96109

97110
// TODO : 모델 파일 분리
@@ -100,12 +113,12 @@ data class RunningData(
100113
val runningTime: Int = 0,
101114
val totalDistance: Double = 0.0,
102115
val pace: Double = 0.0,
103-
val runningPositionList: List<RunningPosition> = emptyList()
116+
val runningPositionList: List<List<RunningPosition>> = listOf(emptyList())
104117
)
105118

106119
data class RunningFinishData(
107120
val runningHistory: RunningHistory,
108-
val runningPositionList: List<RunningPosition>
121+
val runningPositionList: List<List<RunningPosition>>
109122
)
110123

111124
sealed interface RunningState {

0 commit comments

Comments
 (0)