diff --git a/app/src/test/java/dev/lucasnlm/antimine/mocks/FixedDimensionRepository.kt b/app/src/test/java/dev/lucasnlm/antimine/mocks/FixedDimensionRepository.kt index 2d564b17..be6eb11d 100644 --- a/app/src/test/java/dev/lucasnlm/antimine/mocks/FixedDimensionRepository.kt +++ b/app/src/test/java/dev/lucasnlm/antimine/mocks/FixedDimensionRepository.kt @@ -15,4 +15,6 @@ class FixedDimensionRepository : IDimensionRepository { override fun displaySize(): Size = Size(50 * 15, 50 * 30) override fun actionBarSize(): Int = 50 + + override fun navigationBarHeight(): Int = 0 } diff --git a/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/DimensionRepository.kt b/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/DimensionRepository.kt index 4fb7a873..88c874e4 100644 --- a/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/DimensionRepository.kt +++ b/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/DimensionRepository.kt @@ -12,6 +12,7 @@ interface IDimensionRepository { fun areaSeparator(): Float fun displaySize(): Size fun actionBarSize(): Int + fun navigationBarHeight(): Int } data class Size( @@ -51,4 +52,17 @@ class DimensionRepository( styledAttributes.recycle() return actionBarSize } + + override fun navigationBarHeight(): Int { + // TODO use official mode if available + val resources = context.resources + val resourceId: Int = resources.getIdentifier(NAVIGATION_BAR_HEIGHT, DEF_TYPE_DIMEN, DEF_PACKAGE) + return if (resourceId > 0) { resources.getDimensionPixelSize(resourceId) } else 0 + } + + companion object { + private const val NAVIGATION_BAR_HEIGHT = "navigation_bar_height" + private const val DEF_TYPE_DIMEN = "dimen" + private const val DEF_PACKAGE = "android" + } } diff --git a/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/MinefieldRepository.kt b/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/MinefieldRepository.kt index 73e2939c..188a183a 100644 --- a/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/MinefieldRepository.kt +++ b/common/src/main/java/dev/lucasnlm/antimine/common/level/repository/MinefieldRepository.kt @@ -35,10 +35,12 @@ class MinefieldRepository : IMinefieldRepository { dimensionRepository: IDimensionRepository ): Minefield { val fieldSize = dimensionRepository.areaSize() + val verticalGap = if (dimensionRepository.navigationBarHeight() > 0) + VERTICAL_STANDARD_GAP else VERTICAL_STANDARD_GAP_WITHOUT_BOTTOM val display = dimensionRepository.displaySize() val calculatedWidth = ((display.width / fieldSize).toInt() - HORIZONTAL_STANDARD_GAP) - val calculatedHeight = ((display.height / fieldSize).toInt() - VERTICAL_STANDARD_GAP) + val calculatedHeight = ((display.height / fieldSize).toInt() - verticalGap) val finalWidth = calculatedWidth.coerceAtLeast(MIN_STANDARD_WIDTH) val finalHeight = calculatedHeight.coerceAtLeast(MIN_STANDARD_HEIGHT) val finalMines = (finalWidth * finalHeight * CUSTOM_LEVEL_RATIO).toInt() @@ -55,6 +57,7 @@ class MinefieldRepository : IMinefieldRepository { private const val CUSTOM_LEVEL_RATIO = 0.2 private const val HORIZONTAL_STANDARD_GAP = 1 + private const val VERTICAL_STANDARD_GAP_WITHOUT_BOTTOM = 4 private const val VERTICAL_STANDARD_GAP = 3 private const val MIN_STANDARD_WIDTH = 6 private const val MIN_STANDARD_HEIGHT = 9 diff --git a/common/src/main/java/dev/lucasnlm/antimine/common/level/view/CommonLevelFragment.kt b/common/src/main/java/dev/lucasnlm/antimine/common/level/view/CommonLevelFragment.kt index 0a366f5f..67712634 100644 --- a/common/src/main/java/dev/lucasnlm/antimine/common/level/view/CommonLevelFragment.kt +++ b/common/src/main/java/dev/lucasnlm/antimine/common/level/view/CommonLevelFragment.kt @@ -3,7 +3,6 @@ package dev.lucasnlm.antimine.common.level.view import android.content.Context import android.os.Bundle import android.util.DisplayMetrics -import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -54,19 +53,9 @@ abstract class CommonLevelFragment : Fragment() { val displayMetrics = DisplayMetrics() windowManager.defaultDisplay.getMetrics(displayMetrics) - val typedValue = TypedValue() - val actionBarHeight = if (context.theme.resolveAttribute(android.R.attr.actionBarSize, typedValue, true)) { - TypedValue.complexToDimensionPixelSize(typedValue.data, resources.displayMetrics) - } else { - 0 - } - - val resourceId: Int = resources.getIdentifier("navigation_bar_height", "dimen", "android") - val bottom = if (resourceId > 0) { resources.getDimensionPixelSize(resourceId) } else 0 - - val height = displayMetrics.heightPixels - actionBarHeight - bottom + val height = recyclerGrid.measuredHeight val recyclerViewHeight = (dimensionRepository.areaSize() * boardHeight) - val separatorsHeight = (dimensionRepository.areaSeparator() * (boardHeight - 1)) + val separatorsHeight = (2 * dimensionRepository.areaSeparator() * (boardHeight - 1)) return ((height - recyclerViewHeight - separatorsHeight) / 2).coerceAtLeast(0.0f).toInt() } diff --git a/common/src/test/java/dev/lucasnlm/antimine/common/level/mocks/FixedDimensionRepository.kt b/common/src/test/java/dev/lucasnlm/antimine/common/level/mocks/FixedDimensionRepository.kt index a0e90e72..a1334da8 100644 --- a/common/src/test/java/dev/lucasnlm/antimine/common/level/mocks/FixedDimensionRepository.kt +++ b/common/src/test/java/dev/lucasnlm/antimine/common/level/mocks/FixedDimensionRepository.kt @@ -15,4 +15,6 @@ class FixedDimensionRepository : IDimensionRepository { override fun displaySize(): Size = Size(50 * 15, 50 * 30) override fun actionBarSize(): Int = 50 + + override fun navigationBarHeight(): Int = 0 } diff --git a/common/src/test/java/dev/lucasnlm/antimine/common/level/repository/MinefieldRepositoryTest.kt b/common/src/test/java/dev/lucasnlm/antimine/common/level/repository/MinefieldRepositoryTest.kt new file mode 100644 index 00000000..10b114da --- /dev/null +++ b/common/src/test/java/dev/lucasnlm/antimine/common/level/repository/MinefieldRepositoryTest.kt @@ -0,0 +1,99 @@ +package dev.lucasnlm.antimine.common.level.repository + +import dev.lucasnlm.antimine.common.level.models.Difficulty +import dev.lucasnlm.antimine.common.level.models.Minefield +import dev.lucasnlm.antimine.core.preferences.IPreferencesRepository +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.assertEquals +import org.junit.Test + +class MinefieldRepositoryTest { + private val beginnerMinefield = Minefield(9, 9, 10) + private val intermediateMinefield = Minefield(16, 16, 40) + private val expertMinefield = Minefield(24, 24, 99) + + @Test + fun testStandardSizeCalcWithoutNavigationBar() { + val minefieldRepository = MinefieldRepository() + val preferencesRepository = mockk(relaxed = true) + val dimensionRepository = mockk(relaxed = true) { + every { areaSize() } returns 10.0f + every { navigationBarHeight() } returns 0 + every { displaySize() } returns Size(1000, 1000) + } + + val minefield = minefieldRepository.fromDifficulty( + Difficulty.Standard, dimensionRepository, preferencesRepository + ) + + assertEquals(Minefield(99, 96, 1900), minefield) + } + + @Test + fun testStandardSizeCalcWithNavigationBar() { + val minefieldRepository = MinefieldRepository() + val preferencesRepository = mockk(relaxed = true) + val dimensionRepository = mockk(relaxed = true) { + every { areaSize() } returns 10.0f + every { navigationBarHeight() } returns 100 + every { displaySize() } returns Size(1000, 1000) + } + + val minefield = minefieldRepository.fromDifficulty( + Difficulty.Standard, dimensionRepository, preferencesRepository + ) + + assertEquals(Minefield(99, 97, 1920), minefield) + } + + @Test + fun testBeginnerMinefield() { + val minefieldRepository = MinefieldRepository() + val preferencesRepository = mockk(relaxed = true) + val dimensionRepository = mockk(relaxed = true) + + val minefield = minefieldRepository.fromDifficulty( + Difficulty.Beginner, dimensionRepository, preferencesRepository + ) + assertEquals(beginnerMinefield, minefield) + } + + @Test + fun testIntermediateMinefield() { + val minefieldRepository = MinefieldRepository() + val preferencesRepository = mockk(relaxed = true) + val dimensionRepository = mockk(relaxed = true) + + val minefield = minefieldRepository.fromDifficulty( + Difficulty.Intermediate, dimensionRepository, preferencesRepository + ) + assertEquals(intermediateMinefield, minefield) + } + + @Test + fun testExpertMinefieldMinefield() { + val minefieldRepository = MinefieldRepository() + val preferencesRepository = mockk(relaxed = true) + val dimensionRepository = mockk(relaxed = true) + + val minefield = minefieldRepository.fromDifficulty( + Difficulty.Expert, dimensionRepository, preferencesRepository + ) + assertEquals(expertMinefield, minefield) + } + + @Test + fun testCustomMinefieldMinefield() { + val minefieldRepository = MinefieldRepository() + val preferencesRepository = mockk(relaxed = true) { + every { customGameMode() } returns Minefield(25, 20, 12) + } + val dimensionRepository = mockk(relaxed = true) + + val minefield = minefieldRepository.fromDifficulty( + Difficulty.Custom, dimensionRepository, preferencesRepository + ) + assertEquals(Minefield(25, 20, 12), minefield) + } +}