commit
85e398536d
37 changed files with 564 additions and 48 deletions
|
@ -139,11 +139,27 @@
|
|||
|
||||
<activity
|
||||
android:name="dev.lucasnlm.antimine.about.TextActivity"
|
||||
android:theme="@style/AppTheme" />
|
||||
android:theme="@style/AppTheme">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="dev.lucasnlm.antimine.about.AboutActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="dev.lucasnlm.antimine.about.AboutActivity"
|
||||
android:theme="@style/AppTheme" />
|
||||
android:theme="@style/AppTheme">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="dev.lucasnlm.antimine.GameActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="dev.lucasnlm.antimine.stats.StatsActivity"
|
||||
android:theme="@style/AppTheme">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="dev.lucasnlm.antimine.GameActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="dev.lucasnlm.antimine.history.HistoryActivity"
|
||||
|
|
|
@ -37,6 +37,7 @@ import dev.lucasnlm.antimine.level.view.EndGameDialogFragment
|
|||
import dev.lucasnlm.antimine.level.view.LevelFragment
|
||||
import dev.lucasnlm.antimine.preferences.PreferencesActivity
|
||||
import dev.lucasnlm.antimine.share.viewmodel.ShareViewModel
|
||||
import dev.lucasnlm.antimine.stats.StatsActivity
|
||||
import kotlinx.android.synthetic.main.activity_game.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
|
@ -250,6 +251,7 @@ class GameActivity : DaggerAppCompatActivity() {
|
|||
R.id.rate -> openRateUsLink("Drawer")
|
||||
R.id.share_now -> shareCurrentGame()
|
||||
R.id.previous_games -> openSaveHistory()
|
||||
R.id.stats -> openStats()
|
||||
R.id.install_new -> installFromInstantApp()
|
||||
else -> handled = false
|
||||
}
|
||||
|
@ -373,6 +375,13 @@ class GameActivity : DaggerAppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun openStats() {
|
||||
analyticsManager.sentEvent(Analytics.OpenStats())
|
||||
Intent(this, StatsActivity::class.java).apply {
|
||||
startActivity(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSettings() {
|
||||
analyticsManager.sentEvent(Analytics.OpenSettings())
|
||||
Intent(this, PreferencesActivity::class.java).apply {
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.content.Intent
|
|||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.view.MenuItem
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.lifecycle.Observer
|
||||
|
@ -22,7 +21,7 @@ class AboutActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_empty)
|
||||
bindToolbar()
|
||||
setTitle(R.string.about)
|
||||
|
||||
aboutViewModel = ViewModelProviders.of(this).get(AboutViewModel::class.java)
|
||||
|
||||
|
@ -60,23 +59,6 @@ class AboutActivity : AppCompatActivity() {
|
|||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(SOURCE_CODE)))
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
onBackPressed()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun bindToolbar() {
|
||||
supportActionBar?.apply {
|
||||
setTitle(R.string.about)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeButtonEnabled(true)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SOURCE_CODE = "https://github.com/lucasnlm/antimine-android"
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package dev.lucasnlm.antimine.about
|
|||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import dev.lucasnlm.antimine.R
|
||||
|
||||
|
@ -16,8 +15,8 @@ class TextActivity : AppCompatActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
title = intent.getStringExtra(Constants.TEXT_TITLE)
|
||||
setContentView(R.layout.activity_text)
|
||||
bindToolbar()
|
||||
|
||||
GlobalScope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
|
@ -41,23 +40,4 @@ class TextActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
var handled = false
|
||||
|
||||
if (item.itemId == android.R.id.home) {
|
||||
onBackPressed()
|
||||
handled = true
|
||||
}
|
||||
|
||||
return handled || super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun bindToolbar() {
|
||||
supportActionBar?.apply {
|
||||
title = intent.getStringExtra(Constants.TEXT_TITLE)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeButtonEnabled(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import dagger.android.ContributesAndroidInjector
|
|||
import dev.lucasnlm.antimine.TvGameActivity
|
||||
import dev.lucasnlm.antimine.core.scope.ActivityScope
|
||||
import dev.lucasnlm.antimine.history.views.HistoryFragment
|
||||
import dev.lucasnlm.antimine.stats.StatsActivity
|
||||
|
||||
@Module
|
||||
interface ActivityModule {
|
||||
|
@ -17,6 +18,10 @@ interface ActivityModule {
|
|||
@ContributesAndroidInjector
|
||||
fun contributeHistoryFragmentInjector(): HistoryFragment
|
||||
|
||||
@ActivityScope
|
||||
@ContributesAndroidInjector
|
||||
fun contributeStatsActivityInjector(): StatsActivity
|
||||
|
||||
@ActivityScope
|
||||
@ContributesAndroidInjector
|
||||
fun contributeTvGameActivityInjector(): TvGameActivity
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package dev.lucasnlm.antimine.stats
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import dev.lucasnlm.antimine.R
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.stats.viewmodel.StatsViewModel
|
||||
import kotlinx.android.synthetic.main.activity_stats.*
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class StatsActivity : DaggerAppCompatActivity() {
|
||||
@Inject
|
||||
lateinit var statsRepository: IStatsRepository
|
||||
|
||||
private lateinit var viewModel: StatsViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_stats)
|
||||
setTitle(R.string.events)
|
||||
|
||||
viewModel = ViewModelProviders.of(this).get(StatsViewModel::class.java)
|
||||
viewModel.statsObserver.observe(this, Observer {
|
||||
minesCount.text = it.mines.toString()
|
||||
totalTime.text = formatTime(it.duration)
|
||||
averageTime.text = formatTime(it.averageDuration)
|
||||
totalGames.text = it.totalGames.toString()
|
||||
performance.text = formatPercentage(100.0 * it.victory / it.totalGames)
|
||||
openAreas.text = it.openArea.toString()
|
||||
})
|
||||
|
||||
GlobalScope.launch {
|
||||
viewModel.loadStats(statsRepository)
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatPercentage(value: Double) =
|
||||
String.format("%.2f%%", value)
|
||||
|
||||
private fun formatTime(durationSecs: Long) =
|
||||
String.format("%02d:%02d:%02d", durationSecs / 3600, durationSecs % 3600 / 60, durationSecs % 60)
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package dev.lucasnlm.antimine.stats.model
|
||||
|
||||
data class StatsModel(
|
||||
val totalGames: Int,
|
||||
val duration: Long,
|
||||
val averageDuration: Long,
|
||||
val mines: Int,
|
||||
val victory: Int,
|
||||
val openArea: Int
|
||||
)
|
|
@ -0,0 +1,41 @@
|
|||
package dev.lucasnlm.antimine.stats.viewmodel
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.stats.model.StatsModel
|
||||
|
||||
class StatsViewModel : ViewModel() {
|
||||
val statsObserver = MutableLiveData<StatsModel>()
|
||||
|
||||
suspend fun getStatsModel(statsRepository: IStatsRepository): StatsModel? {
|
||||
val stats = statsRepository.getAllStats()
|
||||
val statsCount = stats.count()
|
||||
|
||||
return if (statsCount > 0) {
|
||||
val result = stats.fold(
|
||||
StatsModel(statsCount, 0L, 0L, 0, 0, 0)
|
||||
) { acc, value ->
|
||||
StatsModel(
|
||||
acc.totalGames,
|
||||
acc.duration + value.duration,
|
||||
0,
|
||||
acc.mines + value.mines,
|
||||
acc.victory + value.victory,
|
||||
acc.openArea + value.openArea
|
||||
)
|
||||
}
|
||||
result.copy(averageDuration = result.duration / result.totalGames)
|
||||
} else {
|
||||
StatsModel(0, 0, 0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadStats(statsRepository: IStatsRepository) {
|
||||
getStatsModel(statsRepository)?.let {
|
||||
if (it.totalGames > 0) {
|
||||
statsObserver.postValue(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
app/src/main/res/layout/activity_stats.xml
Normal file
96
app/src/main/res/layout/activity_stats.xml
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:stretchColumns="1"
|
||||
android:fitsSystemWindows="true"
|
||||
android:divider="?android:listDivider"
|
||||
android:showDividers="middle"
|
||||
tools:context=".stats.StatsActivity">
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:padding="16dp"
|
||||
android:text="@string/games"
|
||||
android:textColor="@color/text_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/totalGames"
|
||||
android:gravity="end"
|
||||
android:padding="16dp"
|
||||
android:text="0"
|
||||
tools:ignore="HardcodedText" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:padding="16dp"
|
||||
android:text="@string/mines"
|
||||
android:textColor="@color/text_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/minesCount"
|
||||
android:gravity="end"
|
||||
android:padding="16dp"
|
||||
android:text="-"
|
||||
tools:ignore="HardcodedText" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:padding="16dp"
|
||||
android:text="@string/total_time"
|
||||
android:textColor="@color/text_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/totalTime"
|
||||
android:gravity="end"
|
||||
android:padding="16dp"
|
||||
android:text="-"
|
||||
tools:ignore="HardcodedText" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:padding="16dp"
|
||||
android:text="@string/average_time"
|
||||
android:textColor="@color/text_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/averageTime"
|
||||
android:gravity="end"
|
||||
android:padding="16dp"
|
||||
android:text="-"
|
||||
tools:ignore="HardcodedText" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView
|
||||
android:padding="16dp"
|
||||
android:text="@string/open_areas"
|
||||
android:textColor="@color/text_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/openAreas"
|
||||
android:gravity="end"
|
||||
android:padding="16dp"
|
||||
android:text="-"
|
||||
tools:ignore="HardcodedText" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<TextView
|
||||
android:padding="16dp"
|
||||
android:text="@string/performance"
|
||||
android:textColor="@color/text_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/performance"
|
||||
android:gravity="end"
|
||||
android:padding="16dp"
|
||||
android:text="-"
|
||||
tools:ignore="HardcodedText" />
|
||||
</TableRow>
|
||||
</TableLayout>
|
|
@ -8,6 +8,34 @@
|
|||
android:fitsSystemWindows="false"
|
||||
tools:context="dev.lucasnlm.antimine.history.views.HistoryFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/stats"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/events" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/stats"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/saveHistory"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -16,7 +44,6 @@
|
|||
android:overScrollMode="never"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
android:checkable="false"
|
||||
android:title="@string/previous_games" />
|
||||
|
||||
<item
|
||||
android:id="@+id/stats"
|
||||
android:checkable="false"
|
||||
android:title="@string/events" />
|
||||
|
||||
</group>
|
||||
|
||||
<group
|
||||
|
|
|
@ -10,6 +10,7 @@ import dev.lucasnlm.antimine.common.level.models.Event
|
|||
import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
import dev.lucasnlm.antimine.common.level.utils.IHapticFeedbackInteractor
|
||||
import dev.lucasnlm.antimine.common.level.viewmodel.GameViewModelFactory
|
||||
|
@ -19,6 +20,7 @@ import dev.lucasnlm.antimine.mocks.MockDimensionRepository
|
|||
import dev.lucasnlm.antimine.mocks.MockHapticFeedbackInteractor
|
||||
import dev.lucasnlm.antimine.mocks.MockMinefieldRepository
|
||||
import dev.lucasnlm.antimine.mocks.MockSavesRepository
|
||||
import dev.lucasnlm.antimine.mocks.MockStatsRepository
|
||||
|
||||
@Module
|
||||
class TestLevelModule(
|
||||
|
@ -35,6 +37,7 @@ class TestLevelModule(
|
|||
application: Application,
|
||||
eventObserver: MutableLiveData<Event>,
|
||||
savesRepository: ISavesRepository,
|
||||
statsRepository: IStatsRepository,
|
||||
dimensionRepository: IDimensionRepository,
|
||||
preferencesRepository: IPreferencesRepository,
|
||||
hapticFeedbackInteractor: IHapticFeedbackInteractor,
|
||||
|
@ -45,6 +48,7 @@ class TestLevelModule(
|
|||
application,
|
||||
eventObserver,
|
||||
savesRepository,
|
||||
statsRepository,
|
||||
dimensionRepository,
|
||||
preferencesRepository,
|
||||
hapticFeedbackInteractor,
|
||||
|
@ -62,6 +66,9 @@ class TestLevelModule(
|
|||
@Provides
|
||||
override fun provideSavesRepository(): ISavesRepository = MockSavesRepository()
|
||||
|
||||
@Provides
|
||||
override fun provideStatsRepository(): IStatsRepository = MockStatsRepository(listOf())
|
||||
|
||||
@Provides
|
||||
override fun provideMinefieldRepository(): IMinefieldRepository = MockMinefieldRepository()
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package dev.lucasnlm.antimine.mocks
|
||||
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
|
||||
class MockStatsRepository(
|
||||
private val list: List<Stats>
|
||||
) : IStatsRepository {
|
||||
override suspend fun getAllStats(): List<Stats> = list
|
||||
|
||||
override suspend fun addStats(stats: Stats): Long? {
|
||||
return null
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package dev.lucasnlm.antimine.stats.viewmodel
|
||||
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
import dev.lucasnlm.antimine.mocks.MockStatsRepository
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class StatsViewModelTest {
|
||||
private val listOfStats = listOf(
|
||||
Stats(0, 1000, 10, 1, 10, 10, 90),
|
||||
Stats(1, 1200, 24, 0, 10, 10, 20)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testStatsTotalGames() = runBlockingTest {
|
||||
val viewModel = StatsViewModel()
|
||||
val statsModel = viewModel.getStatsModel(MockStatsRepository(listOfStats))
|
||||
assertEquals(2, statsModel?.totalGames)
|
||||
|
||||
val emptyStatsModel = viewModel.getStatsModel(MockStatsRepository(listOf()))
|
||||
assertEquals(0, emptyStatsModel?.totalGames)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStatsDuration() = runBlockingTest {
|
||||
val viewModel = StatsViewModel()
|
||||
val statsModel = viewModel.getStatsModel(MockStatsRepository(listOfStats))
|
||||
assertEquals(2200L, statsModel?.duration)
|
||||
|
||||
val emptyStatsModel = viewModel.getStatsModel(MockStatsRepository(listOf()))
|
||||
assertEquals(0L, emptyStatsModel?.duration)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStatsAverageDuration() = runBlockingTest {
|
||||
val viewModel = StatsViewModel()
|
||||
val statsModel = viewModel.getStatsModel(MockStatsRepository(listOfStats))
|
||||
assertEquals(1100L, statsModel?.averageDuration)
|
||||
|
||||
val emptyStatsModel = viewModel.getStatsModel(MockStatsRepository(listOf()))
|
||||
assertEquals(0L, emptyStatsModel?.averageDuration)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStatsMines() = runBlockingTest {
|
||||
val viewModel = StatsViewModel()
|
||||
val statsModel = viewModel.getStatsModel(MockStatsRepository(listOfStats))
|
||||
assertEquals(34, statsModel?.mines)
|
||||
|
||||
val emptyStatsModel = viewModel.getStatsModel(MockStatsRepository(listOf()))
|
||||
assertEquals(0, emptyStatsModel?.mines)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testVictory() = runBlockingTest {
|
||||
val viewModel = StatsViewModel()
|
||||
val statsModel = viewModel.getStatsModel(MockStatsRepository(listOfStats))
|
||||
assertEquals(1, statsModel?.victory)
|
||||
|
||||
val emptyStatsModel = viewModel.getStatsModel(MockStatsRepository(listOf()))
|
||||
assertEquals(0, emptyStatsModel?.victory)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOpenArea() = runBlockingTest {
|
||||
val viewModel = StatsViewModel()
|
||||
val statsModel = viewModel.getStatsModel(MockStatsRepository(listOfStats))
|
||||
assertEquals(110, statsModel?.openArea)
|
||||
|
||||
val emptyStatsModel = viewModel.getStatsModel(MockStatsRepository(listOf()))
|
||||
assertEquals(0, emptyStatsModel?.openArea)
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package dev.lucasnlm.antimine.common.level
|
|||
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Save
|
||||
import dev.lucasnlm.antimine.common.level.database.models.SaveStatus
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
import dev.lucasnlm.antimine.common.level.models.Area
|
||||
import dev.lucasnlm.antimine.common.level.models.Difficulty
|
||||
import dev.lucasnlm.antimine.common.level.models.Mark
|
||||
|
@ -354,6 +355,27 @@ class LevelFacade {
|
|||
)
|
||||
}
|
||||
|
||||
fun getStats(duration: Long): Stats? {
|
||||
val gameStatus: SaveStatus = when {
|
||||
checkVictory() -> SaveStatus.VICTORY
|
||||
hasAnyMineExploded() -> SaveStatus.DEFEAT
|
||||
else -> SaveStatus.ON_GOING
|
||||
}
|
||||
return if (gameStatus == SaveStatus.ON_GOING) {
|
||||
null
|
||||
} else {
|
||||
Stats(
|
||||
0,
|
||||
duration,
|
||||
mines.count(),
|
||||
if (gameStatus == SaveStatus.VICTORY) 1 else 0,
|
||||
minefield.width,
|
||||
minefield.height,
|
||||
mines.count { !it.isCovered }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentSaveId(id: Int) {
|
||||
this.saveId = id.coerceAtLeast(0)
|
||||
}
|
||||
|
|
|
@ -8,12 +8,15 @@ import dev.lucasnlm.antimine.common.level.database.converters.FieldConverter
|
|||
import dev.lucasnlm.antimine.common.level.database.converters.MinefieldConverter
|
||||
import dev.lucasnlm.antimine.common.level.database.converters.SaveStatusConverter
|
||||
import dev.lucasnlm.antimine.common.level.database.dao.SaveDao
|
||||
import dev.lucasnlm.antimine.common.level.database.dao.StatsDao
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Save
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
Save::class
|
||||
], version = 2, exportSchema = false
|
||||
Save::class,
|
||||
Stats::class
|
||||
], version = 3, exportSchema = false
|
||||
)
|
||||
@TypeConverters(
|
||||
FieldConverter::class,
|
||||
|
@ -23,4 +26,5 @@ import dev.lucasnlm.antimine.common.level.database.models.Save
|
|||
)
|
||||
abstract class AppDataBase : RoomDatabase() {
|
||||
abstract fun saveDao(): SaveDao
|
||||
abstract fun statsDao(): StatsDao
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package dev.lucasnlm.antimine.common.level.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
|
||||
@Dao
|
||||
interface StatsDao {
|
||||
@Query("SELECT * FROM stats")
|
||||
suspend fun getAll(): List<Stats>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAll(vararg stats: Stats): Array<Long>
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package dev.lucasnlm.antimine.common.level.database.models
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity
|
||||
data class Stats(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val uid: Int,
|
||||
|
||||
@ColumnInfo(name = "duration")
|
||||
val duration: Long,
|
||||
|
||||
@ColumnInfo(name = "mines")
|
||||
val mines: Int,
|
||||
|
||||
@ColumnInfo(name = "victory")
|
||||
val victory: Int,
|
||||
|
||||
@ColumnInfo(name = "width")
|
||||
val width: Int,
|
||||
|
||||
@ColumnInfo(name = "height")
|
||||
val height: Int,
|
||||
|
||||
@ColumnInfo(name = "openArea")
|
||||
val openArea: Int
|
||||
)
|
|
@ -12,8 +12,10 @@ import dev.lucasnlm.antimine.common.level.repository.DimensionRepository
|
|||
import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.MinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.SavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.StatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
import dev.lucasnlm.antimine.common.level.utils.HapticFeedbackInteractor
|
||||
import dev.lucasnlm.antimine.common.level.utils.IHapticFeedbackInteractor
|
||||
|
@ -35,10 +37,18 @@ open class LevelModule(
|
|||
appDataBase.saveDao()
|
||||
}
|
||||
|
||||
private val statsDao by lazy {
|
||||
appDataBase.statsDao()
|
||||
}
|
||||
|
||||
private val savesRepository by lazy {
|
||||
SavesRepository(savesDao)
|
||||
}
|
||||
|
||||
private val statsRepository by lazy {
|
||||
StatsRepository(statsDao)
|
||||
}
|
||||
|
||||
@Provides
|
||||
open fun provideGameEventObserver(): MutableLiveData<Event> = MutableLiveData()
|
||||
|
||||
|
@ -50,6 +60,7 @@ open class LevelModule(
|
|||
application: Application,
|
||||
eventObserver: MutableLiveData<Event>,
|
||||
savesRepository: ISavesRepository,
|
||||
statsRepository: IStatsRepository,
|
||||
dimensionRepository: IDimensionRepository,
|
||||
preferencesRepository: IPreferencesRepository,
|
||||
hapticFeedbackInteractor: IHapticFeedbackInteractor,
|
||||
|
@ -60,6 +71,7 @@ open class LevelModule(
|
|||
application,
|
||||
eventObserver,
|
||||
savesRepository,
|
||||
statsRepository,
|
||||
dimensionRepository,
|
||||
preferencesRepository,
|
||||
hapticFeedbackInteractor,
|
||||
|
@ -78,6 +90,9 @@ open class LevelModule(
|
|||
@Provides
|
||||
open fun provideSavesRepository(): ISavesRepository = savesRepository
|
||||
|
||||
@Provides
|
||||
open fun provideStatsRepository(): IStatsRepository = statsRepository
|
||||
|
||||
@Provides
|
||||
open fun provideMinefieldRepository(): IMinefieldRepository = MinefieldRepository()
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package dev.lucasnlm.antimine.common.level.repository
|
||||
|
||||
import dev.lucasnlm.antimine.common.level.database.dao.StatsDao
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
|
||||
interface IStatsRepository {
|
||||
suspend fun getAllStats(): List<Stats>
|
||||
suspend fun addStats(stats: Stats): Long?
|
||||
}
|
||||
|
||||
class StatsRepository(
|
||||
private val statsDao: StatsDao
|
||||
) : IStatsRepository {
|
||||
override suspend fun getAllStats(): List<Stats> {
|
||||
return statsDao.getAll()
|
||||
}
|
||||
|
||||
override suspend fun addStats(stats: Stats): Long? {
|
||||
return statsDao.insertAll(stats).firstOrNull()
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import dev.lucasnlm.antimine.common.level.database.models.Save
|
|||
import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
import dev.lucasnlm.antimine.common.level.utils.IHapticFeedbackInteractor
|
||||
import dev.lucasnlm.antimine.core.analytics.AnalyticsManager
|
||||
|
@ -28,6 +29,7 @@ class GameViewModel(
|
|||
val application: Application,
|
||||
val eventObserver: MutableLiveData<Event>,
|
||||
private val savesRepository: ISavesRepository,
|
||||
private val statsRepository: IStatsRepository,
|
||||
private val dimensionRepository: IDimensionRepository,
|
||||
private val preferencesRepository: IPreferencesRepository,
|
||||
private val hapticFeedbackInteractor: IHapticFeedbackInteractor,
|
||||
|
@ -146,6 +148,14 @@ class GameViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun saveStats() {
|
||||
if (initialized && levelFacade.hasMines) {
|
||||
levelFacade.getStats(elapsedTimeSeconds.value ?: 0L)?.let {
|
||||
statsRepository.addStats(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun resumeGame() {
|
||||
if (initialized && levelFacade.hasMines && !levelFacade.isGameOver()) {
|
||||
eventObserver.postValue(Event.Resume)
|
||||
|
@ -303,6 +313,7 @@ class GameViewModel(
|
|||
}
|
||||
|
||||
GlobalScope.launch {
|
||||
saveStats()
|
||||
saveGame()
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +332,7 @@ class GameViewModel(
|
|||
}
|
||||
|
||||
GlobalScope.launch {
|
||||
saveStats()
|
||||
saveGame()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import dev.lucasnlm.antimine.common.level.models.Event
|
|||
import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
import dev.lucasnlm.antimine.common.level.utils.IHapticFeedbackInteractor
|
||||
import dev.lucasnlm.antimine.core.analytics.AnalyticsManager
|
||||
|
@ -18,6 +19,7 @@ class GameViewModelFactory @Inject constructor(
|
|||
private val application: Application,
|
||||
private val eventObserver: MutableLiveData<Event>,
|
||||
private val savesRepository: ISavesRepository,
|
||||
private val statsRepository: IStatsRepository,
|
||||
private val dimensionRepository: IDimensionRepository,
|
||||
private val preferencesRepository: IPreferencesRepository,
|
||||
private val hapticFeedbackInteractor: IHapticFeedbackInteractor,
|
||||
|
@ -33,6 +35,7 @@ class GameViewModelFactory @Inject constructor(
|
|||
application,
|
||||
eventObserver,
|
||||
savesRepository,
|
||||
statsRepository,
|
||||
dimensionRepository,
|
||||
preferencesRepository,
|
||||
hapticFeedbackInteractor,
|
||||
|
|
|
@ -65,6 +65,8 @@ sealed class Analytics(
|
|||
|
||||
class OpenAbout : Analytics("Open About")
|
||||
|
||||
class OpenStats : Analytics("Open Stats")
|
||||
|
||||
class OpenSettings : Analytics("Open Settings")
|
||||
|
||||
class OpenSaveHistory : Analytics("Open Save History")
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Anti-Mine</string>
|
||||
<string name="app_description">Musíte vyčistit obdélníkovou desku obsahující skryté miny, aniž by kterákoliv z nich vybuchla.</string>
|
||||
<string name="remaining_mines">Zbývající miny</string>
|
||||
<string name="games">Hry</string>
|
||||
<string name="previous_games">Předchozí hry</string>
|
||||
<string name="install">Instalovat</string>
|
||||
<string name="minefield">Obtížnost</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Pokud se vám tato hra líbí, dejte nám prosím zpětnou vazbu. Hodně nám to pomůže.</string>
|
||||
<string name="rating_button">Ano ❤️️️</string>
|
||||
<string name="rating_button_no">Ne</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Anti-Mine</string>
|
||||
<string name="app_description">Du musst eine rechteckige Tafel mit versteckten minen räumen, ohne dass eine davon explodiert.</string>
|
||||
<string name="remaining_mines">Verbleibende Minen</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Vorherige Spiele</string>
|
||||
<string name="install">Installieren</string>
|
||||
<string name="minefield">Schwierigkeitsgrad</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Wenn dir dieses Spiel gefällt, gib uns bitte eine Rückmeldung. Es wird uns sehr helfen.</string>
|
||||
<string name="rating_button">Ja ❤️️️</string>
|
||||
<string name="rating_button_no">Nein</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Antimine</string>
|
||||
<string name="app_description">Πρέπει να καθαρίσετε μια ορθογώνια πλακέτα που περιέχει κρυμμένες \"νάρκες\" χωρίς να πυροδοτήσετε καμία από αυτές.</string>
|
||||
<string name="remaining_mines">Υπόλοιπες νάρκες</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Προηγούμενα Παιχνίδια</string>
|
||||
<string name="install">Εγκατάσταση</string>
|
||||
<string name="minefield">Δυσκολία</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Αν σας αρέσει αυτό το παιχνίδι, παρακαλούμε δώστε μας τα σχόλιά σας. Θα μας βοηθήσει πολύ.</string>
|
||||
<string name="rating_button">Ναι ❤️️️</string>
|
||||
<string name="rating_button_no">Όχι</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Anti-Mina</string>
|
||||
<string name="app_description">Usted tiene que limpiar un tablero cuadrado que contiene minas escondidas sin detornarlas.</string>
|
||||
<string name="remaining_mines">Minas restantes</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Juegos anteriores</string>
|
||||
<string name="install">Instalar</string>
|
||||
<string name="minefield">Dificultad</string>
|
||||
|
@ -78,7 +79,7 @@
|
|||
<string name="auto_flag">Asistente de Juego</string>
|
||||
<string name="desc_convered_area">Área cubierta</string>
|
||||
<string name="desc_marked_area">Área marcada</string>
|
||||
<string name="desc_question_area">Area dudosa</string>
|
||||
<string name="desc_question_area">Área dudosa</string>
|
||||
<string name="desc_wrongly_marked_area">Área marcada incorrectamente</string>
|
||||
<string name="settings_general">General</string>
|
||||
<string name="settings_vibration_desc">Vibrar al activar la explosión o la bandera</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Si te gusta este juego, por favor danos un comentario. Nos ayudará mucho.</string>
|
||||
<string name="rating_button">Sí ❤️️️</string>
|
||||
<string name="rating_button_no">No</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Anti-Mine</string>
|
||||
<string name="app_description">Vous devez vider un tableau rectangulaire contenant des mines cachées sans en détonner.</string>
|
||||
<string name="remaining_mines">Mines restantes</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Parties précédentes</string>
|
||||
<string name="install">Installer</string>
|
||||
<string name="minefield">Difficulté</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Si vous aimez ce jeu, n\'hésitez pas à jour donner un retour. Ça nous serait très utile.</string>
|
||||
<string name="rating_button">Oui ❤️</string>
|
||||
<string name="rating_button_no">Non</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Antimine</string>
|
||||
<string name="app_description">L\'obbiettivo del gioco è ripulire un campo rettangolare che contiene mine nascoste senza detonarne nessuna.</string>
|
||||
<string name="remaining_mines">Mine rimanenti</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Previous Games</string>
|
||||
<string name="install">Installare</string>
|
||||
<string name="minefield">Difficoltà</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Se ti piace questo gioco, per favore inviaci suggerimenti. Puoi aiutare a migliorarlo.</string>
|
||||
<string name="rating_button">Sì ❤️️️</string>
|
||||
<string name="rating_button_no">No</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Anti-Mine</string>
|
||||
<string name="app_description">Encontre todas as minas escondidas no campo minado.</string>
|
||||
<string name="remaining_mines">Minas Restantes</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Jogos Anteriores</string>
|
||||
<string name="install">Instalar</string>
|
||||
<string name="minefield">Dificuldade</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Se você está gostando do jogo, por favor deixe um comentário! Isso nos ajuda muito.</string>
|
||||
<string name="rating_button">Sim ❤️️️</string>
|
||||
<string name="rating_button_no">Não</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Anti-Mine</string>
|
||||
<string name="app_description">Вам необходимо расчистить прямоугольную площадь со спрятанными минами, не взорвав ни одну из них.</string>
|
||||
<string name="remaining_mines">Мин осталось</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Предыдущая партия</string>
|
||||
<string name="install">Установить</string>
|
||||
<string name="minefield">Сложность</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Нравится игра? Оставьте отзыв, пожалуйста. Это нам очень поможет.</string>
|
||||
<string name="rating_button">Да ❤️️️</string>
|
||||
<string name="rating_button_no">Нет</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Anti-Mine</string>
|
||||
<string name="app_description">Hiçbirini patlatmadan gizli mayın içeren dikdörtgen bir tahtayı temizlemelisiniz.</string>
|
||||
<string name="remaining_mines">Kalan mayınlar</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Önceki Oyun</string>
|
||||
<string name="install">Yükle</string>
|
||||
<string name="minefield">Zorluk</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Bu oyunu beğendiyseniz, lütfen bize bir geri bildirim verin. Bize çok yardımcı olacak.</string>
|
||||
<string name="rating_button">Evet ❤️️️</string>
|
||||
<string name="rating_button_no">Hayır</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">Сапер</string>
|
||||
<string name="app_description">Вам потрібно очистити поле від схованих мін, не детонуючи їх.</string>
|
||||
<string name="remaining_mines">Залишилося мін</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Попередня гра</string>
|
||||
<string name="install">Встановити</string>
|
||||
<string name="minefield">Складність</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">Якщо вам подобається ця гра, то залиште нам свій відгук. Це нам дуже допоможе.</string>
|
||||
<string name="rating_button">Так ❤️️️</string>
|
||||
<string name="rating_button_no">Ні</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
<string name="app_name">Dò mìn</string>
|
||||
<string name="app_description">Bạn phải mở tất cả các ô trên một bãi mìn mà không làm nổ cục mìn nào.</string>
|
||||
<string name="remaining_mines">Số mìn còn lại</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Previous Games</string>
|
||||
<string name="install">Cài đặt</string>
|
||||
<string name="minefield">Độ khó</string>
|
||||
<string name="standard">Tiêu chuẩn</string>
|
||||
<string name="beginner">Dễ</string>
|
||||
<string name="intermediate">Trung bình</string>
|
||||
<string name="expert">Khó</string>
|
||||
<string name="open">Mở</string>
|
||||
<string name="open_menu">Mở menu</string>
|
||||
<string name="close_menu">Đóng menu</string>
|
||||
<string name="settings">Cài đặt</string>
|
||||
|
@ -92,4 +95,8 @@
|
|||
<string name="rating_message">Nếu bạn thích trò chơi này, hãy gửi phản hồi cho chúng tôi. Nhận xét của bạn sẽ giúp chúng tôi rất nhiều.</string>
|
||||
<string name="rating_button">Có ❤️️️</string>
|
||||
<string name="rating_button_no">Không</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<string name="app_name">反雷 - 扫雷</string>
|
||||
<string name="app_description">你需要清除一个隐藏着地雷的矩形面板,不能使任何地雷爆炸。</string>
|
||||
<string name="remaining_mines">剩余地雷</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">前一盘棋</string>
|
||||
<string name="install">安装</string>
|
||||
<string name="minefield">难度</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">如果你喜欢这个游戏,请给我们反馈。这将对我们有很多帮助。</string>
|
||||
<string name="rating_button">是 ❤️️️</string>
|
||||
<string name="rating_button_no">取消</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="en">
|
||||
<string name="app_name">Antimine</string>
|
||||
<string name="app_description">You have to clear a rectangular board containing hidden \"mines\" without detonating any of them.</string>
|
||||
<string name="app_description">You have to clear a rectangular board containing hidden mines without detonating any of them.</string>
|
||||
<string name="remaining_mines">Remaining mines</string>
|
||||
<string name="games">Games</string>
|
||||
<string name="previous_games">Previous Games</string>
|
||||
<string name="install">Install</string>
|
||||
<string name="minefield">Difficulty</string>
|
||||
|
@ -94,4 +95,8 @@
|
|||
<string name="rating_message">If you like this game, please give us a feedback. It will help us a lot.</string>
|
||||
<string name="rating_button">Yes ❤️️️</string>
|
||||
<string name="rating_button_no">No</string>
|
||||
<string name="open_areas">Open Areas</string>
|
||||
<string name="total_time">Total Time</string>
|
||||
<string name="average_time">Average Time</string>
|
||||
<string name="performance">Performance</string>
|
||||
</resources>
|
||||
|
|
|
@ -6,12 +6,14 @@ import androidx.lifecycle.MutableLiveData
|
|||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Save
|
||||
import dev.lucasnlm.antimine.common.level.database.models.Stats
|
||||
import dev.lucasnlm.antimine.common.level.models.Difficulty
|
||||
import dev.lucasnlm.antimine.common.level.models.Event
|
||||
import dev.lucasnlm.antimine.common.level.models.Minefield
|
||||
import dev.lucasnlm.antimine.common.level.repository.IDimensionRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IMinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.ISavesRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.IStatsRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.MinefieldRepository
|
||||
import dev.lucasnlm.antimine.common.level.repository.Size
|
||||
import dev.lucasnlm.antimine.common.level.utils.Clock
|
||||
|
@ -35,6 +37,7 @@ class TestLevelModule(
|
|||
application: Application,
|
||||
eventObserver: MutableLiveData<Event>,
|
||||
savesRepository: ISavesRepository,
|
||||
statsRepository: IStatsRepository,
|
||||
dimensionRepository: IDimensionRepository,
|
||||
preferencesRepository: IPreferencesRepository,
|
||||
hapticFeedbackInteractor: IHapticFeedbackInteractor,
|
||||
|
@ -45,6 +48,7 @@ class TestLevelModule(
|
|||
application,
|
||||
eventObserver,
|
||||
savesRepository,
|
||||
statsRepository,
|
||||
dimensionRepository,
|
||||
preferencesRepository,
|
||||
hapticFeedbackInteractor,
|
||||
|
@ -91,6 +95,13 @@ class TestLevelModule(
|
|||
override fun randomSeed(): Long = 200
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideStatsRepository(): IStatsRepository = object : IStatsRepository {
|
||||
override suspend fun getAllStats(): List<Stats> = listOf()
|
||||
|
||||
override suspend fun addStats(stats: Stats): Long? = null
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideHapticFeedbackInteractor(
|
||||
application: Application,
|
||||
|
|
Loading…
Reference in a new issue