Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.ruleup.challenge.domain.entity.MemberRole
import com.ruleup.challenge.domain.entity.OwnerType
import com.ruleup.challenge.domain.entity.RoomSummary
import com.ruleup.challenge.domain.entity.RoomTopRanker
import com.ruleup.challenge.domain.entity.RoutineProgress
import com.ruleup.challenge.domain.entity.TodayVerificationStatus
import com.ruleup.domain.entity.user.User
import com.ruleup.domain.entity.user.UserRelationship
Expand Down Expand Up @@ -89,6 +90,8 @@ data class RoomResponse(
val topRanking: List<RoomTopRankerResponse>? = null,
@SerialName("myTodayStatus")
val myTodayStatus: String? = null,
@SerialName("routineProgress")
val routineProgress: RoomRoutineProgressResponse? = null,
)

internal fun RoomResponse.toDomain(): ChallengeRoom =
Expand All @@ -108,4 +111,23 @@ internal fun RoomResponse.toDomain(): ChallengeRoom =
topRanking = topRanking.orEmpty().mapNotNull { it.toDomain() },
// 미지 값은 null
myTodayStatus = TodayVerificationStatus.fromValue(myTodayStatus),
routineProgress = routineProgress?.toDomain(),
)

/** 루틴 진행률. 비율은 %(0~100) 로 온다. roomAverageProgressRate 는 summary.roomSuccessRate 와 같은 값이라 읽지 않는다. */
@Serializable
data class RoomRoutineProgressResponse(
@SerialName("myProgressRate")
val myProgressRate: Double? = null,
@SerialName("mySuccessDays")
val mySuccessDays: Int? = null,
@SerialName("myTargetDays")
val myTargetDays: Int? = null,
)

internal fun RoomRoutineProgressResponse.toDomain(): RoutineProgress =
RoutineProgress(
myProgressRate = (myProgressRate ?: 0.0) / 100,
mySuccessDays = mySuccessDays ?: 0,
myTargetDays = myTargetDays ?: 0,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.ruleup.challenge.data.dto
import com.ruleup.challenge.domain.entity.MemberRole
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNull
import kotlin.test.assertTrue

Expand Down Expand Up @@ -47,4 +48,28 @@ class RoomMappingTest {

assertTrue(room.topRanking.isEmpty())
}

@Test
fun `루틴 진행률은 퍼센트를 0에서 1 사이 비율로 옮긴다`() {
val progress =
RoomResponse(routineProgress = RoomRoutineProgressResponse(myProgressRate = 72.5, mySuccessDays = 18, myTargetDays = 25))
.toDomain()
.routineProgress!!

assertEquals(0.725, progress.myProgressRate, 1e-9)
assertEquals(18, progress.mySuccessDays)
assertEquals(25, progress.myTargetDays)
}

@Test
fun `목표일이 아직 계산 전이면 분모가 없는 것으로 본다`() {
val progress = RoomResponse(routineProgress = RoomRoutineProgressResponse(myTargetDays = 0)).toDomain().routineProgress!!

assertFalse(progress.hasTargetDays)
}

@Test
fun `루틴 진행률이 없으면 비워 둔다`() {
assertNull(RoomResponse().toDomain().routineProgress)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,17 @@ data class ChallengeRoom(
// 상위 3.
val topRanking: List<RoomTopRanker>,
val myTodayStatus: TodayVerificationStatus?,
// 응답에 없으면 null
val routineProgress: RoutineProgress? = null,
)

/** 챌린지 전체 기간 기준 내 루틴 진행률. 방 평균은 [RoomSummary.roomSuccessRate] 와 같은 값이라 따로 두지 않는다. */
data class RoutineProgress(
// 0~1
val myProgressRate: Double,
val mySuccessDays: Int,
// 첫 인증 전에는 아직 계산 전이라 0 이다
val myTargetDays: Int,
) {
val hasTargetDays: Boolean get() = myTargetDays > 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -464,11 +464,26 @@ internal fun ProgressInfoCard(
owner?.let { append(" · $it") }
},
)
InfoLine(
label = "방 성공률",
// 판정 이력이 없으면 null 이다.
value = room.summary.roomSuccessRate?.let { "${it.toPercentText()}%" } ?: "아직 집계 전",
)
room.routineProgress?.let { progress ->
InfoLine(
label = "내 진행률",
value =
buildString {
append("${progress.myProgressRate.toPercentText()}% · ${progress.mySuccessDays}")
// 목표일이 아직 계산 전(0)이면 분모를 숨긴다
if (progress.hasTargetDays) append("/${progress.myTargetDays}")
append("일")
},
)
}
// 솔로는 방 평균이 곧 내 값이라 내 진행률만 둔다
if (detail.mode.isGroup) {
InfoLine(
label = "방 성공률",
// 판정 이력이 없으면 null 이다.
value = room.summary.roomSuccessRate?.let { "${it.toPercentText()}%" } ?: "아직 집계 전",
)
}
}
}

Expand Down
Loading