Skip to content
Merged
15 changes: 14 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.gradle.kotlin.dsl.testRuntimeOnly

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
Expand Down Expand Up @@ -51,6 +53,13 @@ android {
buildFeatures {
viewBinding = true
}

testOptions {
unitTests.all {
it.useJUnitPlatform()
}
}

}

dependencies {
Expand Down Expand Up @@ -81,7 +90,11 @@ dependencies {
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.assertj:assertj-core:3.27.6")
androidTestImplementation(libs.androidx.junit)
androidTestImplementation("org.assertj:assertj-core:3.27.6")
androidTestImplementation(libs.androidx.espresso.core)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,52 @@
package com.example.egobook_frontent.ui.home

import android.os.Bundle

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.example.egobook_frontent.R
import com.example.egobook_frontent.databinding.FragmentHomeBinding
import kotlinx.coroutines.launch

class HomeFragment : Fragment(R.layout.fragment_home) {
class HomeFragment : Fragment() {
private lateinit var binding: FragmentHomeBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentHomeBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val viewModel: HomeViewModel by viewModels()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { userState ->
binding.tvLevel.text = "Lv ${userState.level.number}"
binding.ivLevelType.setImageResource(userState.level.type.getResId())
binding.tvInk.text = "${userState.ink.value}"
}
}
}
}
private fun LevelType.getResId(): Int {
return when(this) {
LevelType.ONE -> R.drawable.level_type_1
LevelType.TWO -> R.drawable.level_type_2
LevelType.THREE -> R.drawable.level_type_3
LevelType.FOUR -> R.drawable.level_type_4
LevelType.FIVE -> R.drawable.level_type_5
LevelType.SIX -> R.drawable.level_type_6
LevelType.SEVEN -> R.drawable.level_type_7
LevelType.EIGHT -> R.drawable.level_type_8
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.egobook_frontent.ui.home

import android.R.attr.level
import androidx.lifecycle.ViewModel
import com.example.egobook_frontent.R
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

class HomeViewModel: ViewModel() {
private val _uiState = MutableStateFlow(UserState(Level(1), Ink(9999)))
val uiState: StateFlow<UserState> = _uiState.asStateFlow()
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/example/egobook_frontent/ui/home/Ink.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.egobook_frontent.ui.home

data class Ink(val value: Int) {
init {
check(value >= MINIMUM_INK) { "잉크는 음수가 될 수 없습니다." }
}

companion object {
const val MINIMUM_INK = 0
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/example/egobook_frontent/ui/home/Level.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.egobook_frontent.ui.home

data class Level(val number: Int) {
val type: LevelType = LevelType.of(number)
init {
check(number in MINIMUM_LEVEL..MAXIMUM_LEVEL) { "올바른 레벨 범위가 아닙니다." }
}
companion object {
const val MAXIMUM_LEVEL = 1500
const val MINIMUM_LEVEL = 0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.egobook_frontent.ui.home

enum class LevelType(val range: IntRange) {
ONE(0..99),
TWO(100..299),
THREE(300..499),
FOUR(500..699),
FIVE(700..999),
SIX(1000..1299),
SEVEN(1300..1499),
EIGHT(1500..1500);

companion object {
fun of(number: Int): LevelType = checkNotNull(entries.find { number in it.range }) {
"잘못된 레벨 값입니다."
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.example.egobook_frontent.ui.home

data class UserState(val level: Level, val ink: Ink)
Binary file added app/src/main/res/drawable/level_type_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/level_type_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/level_type_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/level_type_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/level_type_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/level_type_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/level_type_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/src/main/res/layout/fragment_home.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
android:src="@drawable/ink_icon" />

<TextView
android:id="@+id/tv_ink"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
Expand Down
17 changes: 0 additions & 17 deletions app/src/test/java/com/example/egobook_frontent/ExampleUnitTest.kt

This file was deleted.

57 changes: 57 additions & 0 deletions app/src/test/java/com/example/egobook_frontent/UserStateTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.example.egobook_frontent

import com.example.egobook_frontent.ui.home.Level
import com.example.egobook_frontent.ui.home.Ink
import com.example.egobook_frontent.ui.home.LevelType
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import org.junit.jupiter.params.provider.ValueSource

class UserStateTest {
@ParameterizedTest
@MethodSource("levelInformation")
fun `레벨 값에 맞는 레벨 타입을 결정한다`(level: Level, expectedLevelType: LevelType) {
assertThat(level.type)
.isEqualTo(expectedLevelType)
}

@ParameterizedTest
@ValueSource(ints = [-1, 1501])
fun `올바르지 않은 레벨 값은 예외를 반환한다`(invalidLevelNumber: Int) {
assertThatThrownBy { Level(invalidLevelNumber) }
.isInstanceOf(IllegalStateException::class.java)
}

@Test
fun `잉크 값이 음수라면 예외를 반환한다`() {
assertThatThrownBy { Ink(-1) }
.isInstanceOf(java.lang.IllegalStateException::class.java)
}

companion object {
@JvmStatic
fun levelInformation(): List<Arguments> {
return listOf(
Arguments.of(Level(1), LevelType.ONE),
Arguments.of(Level(99), LevelType.ONE),
Arguments.of(Level(100), LevelType.TWO),
Arguments.of(Level(299), LevelType.TWO),
Arguments.of(Level(300), LevelType.THREE),
Arguments.of(Level(499), LevelType.THREE),
Arguments.of(Level(500), LevelType.FOUR),
Arguments.of(Level(699), LevelType.FOUR),
Arguments.of(Level(700), LevelType.FIVE),
Arguments.of(Level(999), LevelType.FIVE),
Arguments.of(Level(1000), LevelType.SIX),
Arguments.of(Level(1299), LevelType.SIX),
Arguments.of(Level(1300), LevelType.SEVEN),
Arguments.of(Level(1499), LevelType.SEVEN),
Arguments.of(Level(1500), LevelType.EIGHT),
)
}
}
}
Loading