Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement home api #14

Merged
merged 12 commits into from
Apr 1, 2024
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.GrowTree"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".feature.login.LoginActivity"
Expand Down
15 changes: 9 additions & 6 deletions app/src/main/java/univ/earthbreaker/namu/data/ApiFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import univ.earthbreaker.namu.BuildConfig
import univ.earthbreaker.namu.data.interceptor.TokenInterceptor
import univ.earthbreaker.namu.data.service.HomeService
import univ.earthbreaker.namu.data.service.OpenAIApiService

object ApiFactory {
Expand All @@ -26,7 +28,8 @@ object ApiFactory {
}

val retrofitForGrowTreeServer: Retrofit by lazy {
Retrofit.Builder().baseUrl(BuildConfig.GROW_TREE_BASE_URL).client(client)
Retrofit.Builder().baseUrl(BuildConfig.GROW_TREE_BASE_URL)
.client(client.newBuilder().addInterceptor(TokenInterceptor()).build())
.addConverterFactory(
json.asConverterFactory("application/json".toMediaType()),
).build()
Expand All @@ -37,11 +40,10 @@ object ApiFactory {
.addConverterFactory(json.asConverterFactory("application/json".toMediaType())).build()
}

inline fun <reified T> create(forWhichServer: Server): T =
when (forWhichServer) {
Server.GrowTreeServer -> retrofitForGrowTreeServer.create(T::class.java)
Server.OpenAI -> retrofitForOpenAiService.create(T::class.java)
}
inline fun <reified T> create(forWhichServer: Server): T = when (forWhichServer) {
Server.GrowTreeServer -> retrofitForGrowTreeServer.create(T::class.java)
Server.OpenAI -> retrofitForOpenAiService.create(T::class.java)
}
}

enum class Server {
Expand All @@ -51,4 +53,5 @@ enum class Server {

object ServicePool {
val openAIApiService: OpenAIApiService = ApiFactory.create(forWhichServer = Server.OpenAI)
val homeService: HomeService = ApiFactory.create(forWhichServer = Server.GrowTreeServer)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package univ.earthbreaker.namu.data.interceptor

import okhttp3.Interceptor
import okhttp3.Response
import univ.earthbreaker.namu.BuildConfig

class TokenInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val tokenAddedRequest = originalRequest.newBuilder().header(
"Authorization",
"Bearer ${BuildConfig.ACCESS_TOKEN}",
).build()
return chain.proceed(tokenAddedRequest)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package univ.earthbreaker.namu.data.model

import kotlinx.serialization.Serializable

@Serializable
data class FailureResponseDto(
val message: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package univ.earthbreaker.namu.data.model.home

import kotlinx.serialization.Serializable

@Serializable
data class GetCharacterInfoResponse(
val imageUrl: String,
val requiredExp: Int,
val currentExp: Int,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package univ.earthbreaker.namu.data.model.home

import kotlinx.serialization.Serializable

@Serializable
data class GetUserEnergyResponse(
val point: Int,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package univ.earthbreaker.namu.data.model.home

import kotlinx.serialization.Serializable

@Serializable
data class GetUserInfoResponse(
val currentExp: Float,
val level: Int,
val memberNo: Int,
val requiredExp: Float,
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package univ.earthbreaker.namu.data.model.home
package univ.earthbreaker.namu.data.model.mission

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package univ.earthbreaker.namu.data.model.home
package univ.earthbreaker.namu.data.model.mission

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
package univ.earthbreaker.namu.data.repository.home

import univ.earthbreaker.namu.domain.entity.mission.HomeInfo
import univ.earthbreaker.namu.data.ServicePool
import univ.earthbreaker.namu.data.service.HomeService
import univ.earthbreaker.namu.domain.entity.home.HomeInfo
import univ.earthbreaker.namu.domain.repository.HomeRepository
import univ.earthbreaker.namu.feature.home.type.CharacterLevel

class HomeRepositoryImpl : HomeRepository {
class HomeRepositoryImpl(private val homeService: HomeService = ServicePool.homeService) : HomeRepository {
override suspend fun getHomeInfo(): HomeInfo {
return HomeInfo()
val characterInfo = homeService.getCharacterInfo()
val userEnergy = homeService.getUserEnergy()
val userInfo = homeService.getUserInfo()
return HomeInfo(
userLevel = userInfo.level,
userExp = userInfo.currentExp / userInfo.requiredExp,
characterLevel = CharacterLevel.entries[characterInfo.currentExp],
energy = userEnergy.point,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package univ.earthbreaker.namu.data.repository.mission

import univ.earthbreaker.namu.data.ServicePool
import univ.earthbreaker.namu.data.model.home.CertifyMissionRequest
import univ.earthbreaker.namu.data.model.home.CertifyMissionRequest.Message
import univ.earthbreaker.namu.data.model.home.CertifyMissionRequest.Message.ImageContent
import univ.earthbreaker.namu.data.model.home.CertifyMissionRequest.Message.ImageContent.ImageUrl
import univ.earthbreaker.namu.data.model.mission.CertifyMissionRequest
import univ.earthbreaker.namu.data.model.mission.CertifyMissionRequest.Message
import univ.earthbreaker.namu.data.model.mission.CertifyMissionRequest.Message.ImageContent
import univ.earthbreaker.namu.data.model.mission.CertifyMissionRequest.Message.ImageContent.ImageUrl
import univ.earthbreaker.namu.domain.entity.mission.MissionCertificationInfo
import univ.earthbreaker.namu.domain.repository.MissionRepository

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package univ.earthbreaker.namu.data.service

import retrofit2.http.GET
import univ.earthbreaker.namu.data.model.home.GetCharacterInfoResponse
import univ.earthbreaker.namu.data.model.home.GetUserEnergyResponse
import univ.earthbreaker.namu.data.model.home.GetUserInfoResponse

interface HomeService {
@GET("characters/home")
suspend fun getCharacterInfo(): GetCharacterInfoResponse

@GET("points/home")
suspend fun getUserEnergy(): GetUserEnergyResponse

@GET("members/home")
suspend fun getUserInfo(): GetUserInfoResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import retrofit2.http.Body
import retrofit2.http.Header
import retrofit2.http.POST
import univ.earthbreaker.namu.BuildConfig
import univ.earthbreaker.namu.data.model.home.CertifyMissionRequest
import univ.earthbreaker.namu.data.model.home.CertifyMissionResponse
import univ.earthbreaker.namu.data.model.mission.CertifyMissionRequest
import univ.earthbreaker.namu.data.model.mission.CertifyMissionResponse

interface OpenAIApiService {
@POST("chat/completions")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package univ.earthbreaker.namu.domain.entity.mission
package univ.earthbreaker.namu.domain.entity.home

import univ.earthbreaker.namu.feature.home.type.CharacterLevel

data class HomeInfo(
val userLevel: Int = 0,
val userExp: Float = 0f,
val characterLevel: CharacterLevel = CharacterLevel.LEVEL_INITIAL,
val characterLevel: CharacterLevel = CharacterLevel.LEVEL_BEGIN,
val energy: Int = 0,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package univ.earthbreaker.namu.domain.repository

import univ.earthbreaker.namu.domain.entity.mission.HomeInfo
import univ.earthbreaker.namu.domain.entity.home.HomeInfo

interface HomeRepository {
suspend fun getHomeInfo(): HomeInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import univ.earthbreaker.namu.data.repository.home.HomeRepositoryImpl
import univ.earthbreaker.namu.domain.entity.mission.HomeInfo
import univ.earthbreaker.namu.domain.entity.home.HomeInfo
import univ.earthbreaker.namu.domain.repository.HomeRepository

class GetHomeInfoUseCase(
private val homeRepository: HomeRepository = HomeRepositoryImpl(),
) {
operator fun invoke(): Flow<HomeInfo> = flow<HomeInfo> {
operator fun invoke(): Flow<HomeInfo> = flow {
emit(homeRepository.getHomeInfo())
}.flowOn(Dispatchers.IO)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import univ.earthbreaker.namu.R
import univ.earthbreaker.namu.domain.entity.mission.HomeInfo
import univ.earthbreaker.namu.domain.entity.home.HomeInfo
import univ.earthbreaker.namu.feature.book.BookDialog
import univ.earthbreaker.namu.feature.home.component.OpenDialogCard
import univ.earthbreaker.namu.feature.home.component.TreeEnergyCard
Expand Down Expand Up @@ -69,17 +69,17 @@ fun HomeScreen(
)
Image(
painter = when (state.homeInfo.characterLevel) {
CharacterLevel.LEVEL_INITIAL -> painterResource(id = R.drawable.img_mock_character1)
CharacterLevel.LEVEL_MID -> painterResource(id = R.drawable.img_mock_character2)
CharacterLevel.LEVEL_FINAL -> painterResource(id = R.drawable.img_mock_character3)
CharacterLevel.LEVEL_BEGIN -> painterResource(id = R.drawable.img_mock_character1)
CharacterLevel.LEVEL_MIDDLE -> painterResource(id = R.drawable.img_mock_character2)
CharacterLevel.LEVEL_END -> painterResource(id = R.drawable.img_mock_character3)
},
contentDescription = null,
)
HomeBottomCard(
energy = state.homeInfo.energy,
characterLevel = state.homeInfo.characterLevel,
onClickCharacterLevelUp = {
if (state.homeInfo.characterLevel == CharacterLevel.LEVEL_FINAL) {
if (state.homeInfo.characterLevel == CharacterLevel.LEVEL_END) {
} else {
actions.levelUpCharacter
}
Expand Down Expand Up @@ -269,7 +269,7 @@ fun HomeTopCardPreview() {
fun HomeBottomCardPreview() {
HomeBottomCard(
energy = 1,
characterLevel = CharacterLevel.LEVEL_MID,
characterLevel = CharacterLevel.LEVEL_MIDDLE,
onClickCharacterLevelUp = {},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import univ.earthbreaker.namu.domain.entity.mission.HomeInfo
import univ.earthbreaker.namu.domain.entity.home.HomeInfo
import univ.earthbreaker.namu.domain.usecase.home.GetHomeInfoUseCase
import univ.earthbreaker.namu.domain.usecase.mission.CertifyMissionUseCase
import univ.earthbreaker.namu.feature.home.model.HomeDialogState
Expand Down Expand Up @@ -72,7 +72,7 @@ class HomeViewModel(
homeInfo.value = it
_homeUiStateFlow.emit(
HomeUiState.Success(
it,
homeInfo = homeInfo.value,
missionDescription = missionDescription.value,
missionImageUri = missionImageUri.value,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import univ.earthbreaker.namu.feature.home.type.CharacterLevel
@Composable
fun TreeEnergyCard(characterLevel: CharacterLevel) {
Row {
repeat(CharacterLevel.LEVEL_FINAL.level) { index ->
repeat(CharacterLevel.LEVEL_END.level) { index ->
Image(
painter = painterResource(
id = if (index < characterLevel.level) {
Expand All @@ -27,7 +27,7 @@ fun TreeEnergyCard(characterLevel: CharacterLevel) {
),
contentDescription = null,
)
if (index < CharacterLevel.LEVEL_FINAL.level - 1) {
if (index < CharacterLevel.LEVEL_END.level - 1) {
Spacer(Modifier.width(17.dp))
}
}
Expand All @@ -38,8 +38,8 @@ fun TreeEnergyCard(characterLevel: CharacterLevel) {
@Composable
fun TreeEnergyCardPreview() {
Column {
TreeEnergyCard(characterLevel = CharacterLevel.LEVEL_INITIAL)
TreeEnergyCard(characterLevel = CharacterLevel.LEVEL_MID)
TreeEnergyCard(characterLevel = CharacterLevel.LEVEL_FINAL)
TreeEnergyCard(characterLevel = CharacterLevel.LEVEL_BEGIN)
TreeEnergyCard(characterLevel = CharacterLevel.LEVEL_MIDDLE)
TreeEnergyCard(characterLevel = CharacterLevel.LEVEL_END)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package univ.earthbreaker.namu.feature.home.model

import android.net.Uri
import univ.earthbreaker.namu.domain.entity.mission.HomeInfo
import univ.earthbreaker.namu.domain.entity.home.HomeInfo

sealed interface HomeUiState {
data object Loading : HomeUiState
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package univ.earthbreaker.namu.feature.home.type

enum class CharacterLevel(val level: Int) {
LEVEL_INITIAL(1),
LEVEL_MID(2),
LEVEL_FINAL(3),
LEVEL_BEGIN(1),
LEVEL_MIDDLE(2),
LEVEL_END(3),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package univ.earthbreaker.namu.util

import android.util.Log
import kotlinx.serialization.json.Json
import retrofit2.HttpException
import univ.earthbreaker.namu.data.model.FailureResponseDto

fun Throwable.getErrorMessage(): String {
when (this) {
is HttpException -> {
val data = Json.decodeFromString<FailureResponseDto>(
this.response()?.errorBody()?.string() ?: return "예기치 못한 에러 발생",
)
return data.message
}

else -> {
Log.e("errorMessage", this.message.toString())
return "예기치 못한 에러 발생"
}
}
}