feat(home): 크리에이터 랭킹 응답 매핑을 추가한다
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package kr.co.vividnext.sodalive.v2.main.home.data
|
||||
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
|
||||
interface HomeCreatorRankingApi {
|
||||
@GET("/api/v2/home/rankings/creators")
|
||||
fun getCreatorRankings(
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<HomeCreatorRankingResponse>>
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package kr.co.vividnext.sodalive.v2.main.home.data
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@Keep
|
||||
data class HomeCreatorRankingResponse(
|
||||
@SerializedName("showRankChange") val showRankChange: Boolean,
|
||||
@SerializedName("items") val items: List<HomeCreatorRankingItemResponse>
|
||||
)
|
||||
|
||||
@Keep
|
||||
data class HomeCreatorRankingItemResponse(
|
||||
@SerializedName("rank") val rank: Int,
|
||||
@SerializedName("rankChange") val rankChange: Int?,
|
||||
@SerializedName("isNew") val isNew: Boolean,
|
||||
@SerializedName("creatorId") val creatorId: Long,
|
||||
@SerializedName("nickname") val nickname: String,
|
||||
@SerializedName("profileImageUrl") val profileImageUrl: String
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
package kr.co.vividnext.sodalive.v2.main.home.data
|
||||
|
||||
class HomeCreatorRankingRepository(private val api: HomeCreatorRankingApi) {
|
||||
fun getCreatorRankings(token: String) = api.getCreatorRankings(authHeader = token)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package kr.co.vividnext.sodalive.v2.main.home.model
|
||||
|
||||
import kr.co.vividnext.sodalive.v2.main.home.data.HomeCreatorRankingItemResponse
|
||||
import kr.co.vividnext.sodalive.v2.main.home.data.HomeCreatorRankingResponse
|
||||
import kr.co.vividnext.sodalive.v2.widget.creatorranking.CreatorRankingItem
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.Decrease
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.Increase
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.New
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.Stay
|
||||
import kotlin.math.abs
|
||||
|
||||
fun HomeCreatorRankingResponse.toCreatorRankingItems(): List<CreatorRankingItem> = items
|
||||
.filter { it.rank >= 1 }
|
||||
.sortedBy { it.rank }
|
||||
.map { it.toCreatorRankingItem(showRankChange) }
|
||||
|
||||
private fun HomeCreatorRankingItemResponse.toCreatorRankingItem(showRankChange: Boolean): CreatorRankingItem {
|
||||
val changeType = toRankingChangeType()
|
||||
return CreatorRankingItem(
|
||||
creatorId = creatorId,
|
||||
rank = rank,
|
||||
rankChangeType = changeType,
|
||||
rankChangeAmount = if (changeType == New) 0 else abs(rankChange ?: 0),
|
||||
creatorName = nickname,
|
||||
imageUrl = profileImageUrl,
|
||||
isBlocked = creatorId == 0L,
|
||||
showRankChange = showRankChange
|
||||
)
|
||||
}
|
||||
|
||||
private fun HomeCreatorRankingItemResponse.toRankingChangeType(): RankingChangeType = when {
|
||||
isNew -> New
|
||||
rankChange == null || rankChange == 0 -> Stay
|
||||
rankChange > 0 -> Increase
|
||||
else -> Decrease
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package kr.co.vividnext.sodalive.v2.main.home
|
||||
|
||||
import kr.co.vividnext.sodalive.v2.main.home.data.HomeCreatorRankingItemResponse
|
||||
import kr.co.vividnext.sodalive.v2.main.home.data.HomeCreatorRankingResponse
|
||||
import kr.co.vividnext.sodalive.v2.main.home.model.toCreatorRankingItems
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.Decrease
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.Increase
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.New
|
||||
import kr.co.vividnext.sodalive.v2.widget.ranking.RankingChangeType.Stay
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class HomeCreatorRankingMapperTest {
|
||||
|
||||
@Test
|
||||
fun `응답 아이템은 rank 오름차순으로 정렬하고 유효하지 않은 rank는 제외한다`() {
|
||||
val response = HomeCreatorRankingResponse(
|
||||
showRankChange = true,
|
||||
items = listOf(
|
||||
item(rank = 3, creatorId = 3L),
|
||||
item(rank = 0, creatorId = 0L),
|
||||
item(rank = 1, creatorId = 1L),
|
||||
item(rank = 2, creatorId = 2L)
|
||||
)
|
||||
)
|
||||
|
||||
val items = response.toCreatorRankingItems()
|
||||
|
||||
assertEquals(listOf(1, 2, 3), items.map { it.rank })
|
||||
assertEquals(listOf(1L, 2L, 3L), items.map { it.creatorId })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `신규 여부는 순위 변동보다 우선한다`() {
|
||||
val item = HomeCreatorRankingResponse(
|
||||
showRankChange = true,
|
||||
items = listOf(item(isNew = true, rankChange = -3))
|
||||
).toCreatorRankingItems().single()
|
||||
|
||||
assertEquals(New, item.rankChangeType)
|
||||
assertEquals(0, item.rankChangeAmount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rankChange가 null이거나 0이면 유지로 매핑한다`() {
|
||||
val items = HomeCreatorRankingResponse(
|
||||
showRankChange = true,
|
||||
items = listOf(
|
||||
item(rank = 1, rankChange = null),
|
||||
item(rank = 2, rankChange = 0)
|
||||
)
|
||||
).toCreatorRankingItems()
|
||||
|
||||
assertEquals(listOf(Stay, Stay), items.map { it.rankChangeType })
|
||||
assertEquals(listOf(0, 0), items.map { it.rankChangeAmount })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `양수와 음수 rankChange는 절대값과 함께 상승과 하락으로 매핑한다`() {
|
||||
val items = HomeCreatorRankingResponse(
|
||||
showRankChange = true,
|
||||
items = listOf(
|
||||
item(rank = 1, rankChange = 5),
|
||||
item(rank = 2, rankChange = -3)
|
||||
)
|
||||
).toCreatorRankingItems()
|
||||
|
||||
assertEquals(listOf(Increase, Decrease), items.map { it.rankChangeType })
|
||||
assertEquals(listOf(5, 3), items.map { it.rankChangeAmount })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `순위 변동 숨김 값은 모든 크리에이터 랭킹 아이템에 전달된다`() {
|
||||
val items = HomeCreatorRankingResponse(
|
||||
showRankChange = false,
|
||||
items = listOf(item(rank = 1), item(rank = 2))
|
||||
).toCreatorRankingItems()
|
||||
|
||||
assertTrue(items.isNotEmpty())
|
||||
assertTrue(items.all { !it.showRankChange })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `creatorId가 0이면 차단되고 터치할 수 없는 아이템으로 매핑한다`() {
|
||||
val item = HomeCreatorRankingResponse(
|
||||
showRankChange = true,
|
||||
items = listOf(item(creatorId = 0L))
|
||||
).toCreatorRankingItems().single()
|
||||
|
||||
assertTrue(item.isBlocked)
|
||||
assertTrue(item.isInaccessible)
|
||||
assertFalse(item.isTouchable)
|
||||
}
|
||||
|
||||
private fun item(
|
||||
rank: Int = 1,
|
||||
rankChange: Int? = 1,
|
||||
isNew: Boolean = false,
|
||||
creatorId: Long = 1L,
|
||||
nickname: String = "크리에이터 이름",
|
||||
profileImageUrl: String = "https://example.com/image.png"
|
||||
) = HomeCreatorRankingItemResponse(
|
||||
rank = rank,
|
||||
rankChange = rankChange,
|
||||
isNew = isNew,
|
||||
creatorId = creatorId,
|
||||
nickname = nickname,
|
||||
profileImageUrl = profileImageUrl
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user