From 7655d1d7a300506896caec3ddde330d93f571f37 Mon Sep 17 00:00:00 2001 From: Fabian Zobrist Date: Tue, 27 Dec 2022 17:19:55 +0100 Subject: [PATCH] Add database. Write score to database and update. --- app/build.gradle | 7 ++- .../me/zobrist/tichucounter/MainActivity.kt | 33 +++++++----- .../zobrist/tichucounter/data/AppDatabase.kt | 12 +++++ .../tichucounter/data/DatabaseModule.kt | 34 ++++++++++++ .../tichucounter/data/DateConverter.kt | 14 +++++ .../java/me/zobrist/tichucounter/data/Game.kt | 13 +++++ .../me/zobrist/tichucounter/data/GameDao.kt | 31 +++++++++++ .../me/zobrist/tichucounter/data/Round.kt | 12 +++++ .../me/zobrist/tichucounter/data/RoundDao.kt | 22 ++++++++ .../me/zobrist/tichucounter/domain/Round.kt | 6 --- .../me/zobrist/tichucounter/domain/Tichu.kt | 1 + .../fragments/HistoryListViewModel.kt | 53 ++++++++----------- .../fragments/KeyboardViewModel.kt | 17 +++++- .../tichucounter/repository/GameRepository.kt | 53 +++++++++++++++++++ 14 files changed, 256 insertions(+), 52 deletions(-) create mode 100644 app/src/main/java/me/zobrist/tichucounter/data/AppDatabase.kt create mode 100644 app/src/main/java/me/zobrist/tichucounter/data/DatabaseModule.kt create mode 100644 app/src/main/java/me/zobrist/tichucounter/data/DateConverter.kt create mode 100644 app/src/main/java/me/zobrist/tichucounter/data/Game.kt create mode 100644 app/src/main/java/me/zobrist/tichucounter/data/GameDao.kt create mode 100644 app/src/main/java/me/zobrist/tichucounter/data/Round.kt create mode 100644 app/src/main/java/me/zobrist/tichucounter/data/RoundDao.kt delete mode 100644 app/src/main/java/me/zobrist/tichucounter/domain/Round.kt create mode 100644 app/src/main/java/me/zobrist/tichucounter/repository/GameRepository.kt diff --git a/app/build.gradle b/app/build.gradle index 015d5f3..ec8d04f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,8 +31,8 @@ android { versionCode versionProperties["versionCode"].toInteger() versionName "1.1.0Beta1" resConfigs("de", "en") - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + multiDexEnabled true } signingConfigs { create("release") { @@ -85,6 +85,11 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' implementation "com.google.dagger:hilt-android:2.44" kapt "com.google.dagger:hilt-compiler:2.44" + implementation("androidx.room:room-runtime:2.4.3") + annotationProcessor("androidx.room:room-compiler:2.4.3") + kapt("androidx.room:room-compiler:2.4.3") + implementation("androidx.room:room-ktx:2.4.3") + implementation("androidx.multidex:multidex:2.0.1") } // Allow references to generated code diff --git a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt index 97e471d..debc04e 100644 --- a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt +++ b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt @@ -11,29 +11,31 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.core.os.LocaleListCompat import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import me.zobrist.tichucounter.databinding.ActivityMainBinding -import me.zobrist.tichucounter.domain.Round +import me.zobrist.tichucounter.data.Round import me.zobrist.tichucounter.domain.Tichu import me.zobrist.tichucounter.domain.getAbsoluteDifference import me.zobrist.tichucounter.fragments.HistoryListViewModel import me.zobrist.tichucounter.fragments.KeyboardViewModel +import me.zobrist.tichucounter.repository.GameRepository import java.util.* import javax.inject.Inject @AndroidEntryPoint class MainActivity : AppCompatActivity() { - private var currentRound: Round = Round(null, null) + private var currentRound: Round = Round(0, 0, null, null) private val keyboardViewModel: KeyboardViewModel by viewModels() private val historyListViewModel: HistoryListViewModel by viewModels() @Inject lateinit var tichu: Tichu - + @Inject lateinit var gameRepository: GameRepository private var ignoreNextUpdate: Boolean = false - private var systemLocale = Locale.getDefault() - private lateinit var binding: ActivityMainBinding @@ -46,14 +48,23 @@ class MainActivity : AppCompatActivity() { setSupportActionBar(binding.toolbar) + GlobalScope.launch(Dispatchers.IO) { + val game = gameRepository.getActiveGame() + + if(game == null) + { + val game = gameRepository.newGame() + } + } + + historyListViewModel.updateAll() + updateTheme(this.getSharedPreferences("Settings", MODE_PRIVATE).getInt("Theme", 2)) keepScreenOn( this.getSharedPreferences("Settings", MODE_PRIVATE).getBoolean("Screen_On", false) ) - val json = this.getSharedPreferences("Settings", MODE_PRIVATE) - .getString("history", "{\"scores\":[]}") binding.contentMain.nameTeamA.setText( this.getSharedPreferences("Settings", MODE_PRIVATE).getString("nameTeamA", "TeamA") ) @@ -98,9 +109,7 @@ class MainActivity : AppCompatActivity() { } keyboardViewModel.submitButtonClicked.observe(this) { - historyListViewModel.logRound(currentRound) - keyboardViewModel.setScoreA(null) - keyboardViewModel.setScoreB(null) + historyListViewModel.updateAll() } historyListViewModel.totalScoreA.observe(this) { value -> @@ -148,7 +157,7 @@ class MainActivity : AppCompatActivity() { true } R.id.action_undo -> { - historyListViewModel.revertLastRound() + //historyListViewModel.revertLastRound() true } R.id.action_theme -> { @@ -169,7 +178,7 @@ class MainActivity : AppCompatActivity() { } private fun clearAll() { - historyListViewModel.clearAll() + //historyListViewModel.clearAll() } diff --git a/app/src/main/java/me/zobrist/tichucounter/data/AppDatabase.kt b/app/src/main/java/me/zobrist/tichucounter/data/AppDatabase.kt new file mode 100644 index 0000000..a7b540b --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/data/AppDatabase.kt @@ -0,0 +1,12 @@ +package me.zobrist.tichucounter.data + +import DateConverter +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.TypeConverter + +@Database(entities = [Round::class, Game::class], version = 1) +abstract class AppDatabase : RoomDatabase() { + abstract fun roundDao(): RoundDao + abstract fun gameDao(): GameDao +} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/data/DatabaseModule.kt b/app/src/main/java/me/zobrist/tichucounter/data/DatabaseModule.kt new file mode 100644 index 0000000..4ac90d2 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/data/DatabaseModule.kt @@ -0,0 +1,34 @@ +package me.zobrist.tichucounter.data + +import android.content.Context +import androidx.room.Room +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +class DatabaseModule { + @Provides + fun provideRoundDao(appDatabase: AppDatabase): RoundDao { + return appDatabase.roundDao() + } + + @Provides + fun provideGameDao(appDatabase: AppDatabase): GameDao { + return appDatabase.gameDao() + } + + @Provides + @Singleton + fun provideAppDatabase(@ApplicationContext appContext: Context): AppDatabase { + return Room.databaseBuilder( + appContext, + AppDatabase::class.java, + "TichuCounterDb" + ).build() + } +} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/data/DateConverter.kt b/app/src/main/java/me/zobrist/tichucounter/data/DateConverter.kt new file mode 100644 index 0000000..4afbe99 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/data/DateConverter.kt @@ -0,0 +1,14 @@ +import androidx.room.TypeConverter +import java.util.* + +object DateConverter { + @TypeConverter + fun toDate(dateLong: Long?): Date? { + return dateLong?.let { Date(it) } + } + + @TypeConverter + fun fromDate(date: Date?): Long? { + return date?.time + } +} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/data/Game.kt b/app/src/main/java/me/zobrist/tichucounter/data/Game.kt new file mode 100644 index 0000000..948b454 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/data/Game.kt @@ -0,0 +1,13 @@ +package me.zobrist.tichucounter.data + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import java.util.Date + +@Entity +data class Game( + val active: Boolean, + var nameA: String, + var nameB: String, + @PrimaryKey(autoGenerate = true) val uid: Int? = null) \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/data/GameDao.kt b/app/src/main/java/me/zobrist/tichucounter/data/GameDao.kt new file mode 100644 index 0000000..a2a5b69 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/data/GameDao.kt @@ -0,0 +1,31 @@ +package me.zobrist.tichucounter.data + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface GameDao { + + @Query("SELECT * FROM game") + fun getAll(): List + + @Query("SELECT * FROM game WHERE uid is :gameId") + fun getGameById(gameId: Int): Game + + @Query("SELECT * FROM game WHERE active is 1") + fun getActive(): Game + + @Query("UPDATE game SET active = 1 WHERE uid is :gameId;") + fun setActive(gameId: Int) + + @Query("UPDATE game SET active = 0 WHERE uid is not :gameId;") + fun setOthersInactive(gameId: Int) + + @Insert + fun insertAll(vararg users: Game) + + @Delete + fun delete(round: Game) +} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/data/Round.kt b/app/src/main/java/me/zobrist/tichucounter/data/Round.kt new file mode 100644 index 0000000..6d6aab9 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/data/Round.kt @@ -0,0 +1,12 @@ +package me.zobrist.tichucounter.data + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity +data class Round( + var gameId: Int, + var scoreA: Int?, + var scoreB: Int?, + @PrimaryKey(autoGenerate = true) val uid: Int? = null) \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/data/RoundDao.kt b/app/src/main/java/me/zobrist/tichucounter/data/RoundDao.kt new file mode 100644 index 0000000..3d0a7ee --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/data/RoundDao.kt @@ -0,0 +1,22 @@ +package me.zobrist.tichucounter.data + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface RoundDao { + + @Query("SELECT * FROM round") + fun getAll(): List + + @Query("SELECT * FROM round WHERE gameId is :gameId") + fun getAllForGame(gameId: Int?): List + + @Insert + fun insertAll(vararg rounds: Round) + + @Delete + fun delete(round: Round) +} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/domain/Round.kt b/app/src/main/java/me/zobrist/tichucounter/domain/Round.kt deleted file mode 100644 index ca59968..0000000 --- a/app/src/main/java/me/zobrist/tichucounter/domain/Round.kt +++ /dev/null @@ -1,6 +0,0 @@ -package me.zobrist.tichucounter.domain - -import java.io.Serializable - -data class Round(var scoreA: Int?, var scoreB: Int?) : Serializable { -} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/domain/Tichu.kt b/app/src/main/java/me/zobrist/tichucounter/domain/Tichu.kt index 76c6f95..d3240fe 100644 --- a/app/src/main/java/me/zobrist/tichucounter/domain/Tichu.kt +++ b/app/src/main/java/me/zobrist/tichucounter/domain/Tichu.kt @@ -1,5 +1,6 @@ package me.zobrist.tichucounter.domain +import me.zobrist.tichucounter.data.Round import javax.inject.Inject class Tichu @Inject constructor() { diff --git a/app/src/main/java/me/zobrist/tichucounter/fragments/HistoryListViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/fragments/HistoryListViewModel.kt index 9721bfa..b03667f 100644 --- a/app/src/main/java/me/zobrist/tichucounter/fragments/HistoryListViewModel.kt +++ b/app/src/main/java/me/zobrist/tichucounter/fragments/HistoryListViewModel.kt @@ -4,12 +4,15 @@ import SingleLiveEvent import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import me.zobrist.tichucounter.domain.Round - -class HistoryListViewModel : ViewModel() { - // TODO: Implement the ViewModel - private var scores = ArrayList() +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import me.zobrist.tichucounter.data.Round +import me.zobrist.tichucounter.repository.GameRepository +import javax.inject.Inject +@HiltViewModel +class HistoryListViewModel @Inject constructor(val gameRepository: GameRepository) : ViewModel() { private val _totalScoreA: MutableLiveData = MutableLiveData() private val _totalScoreB: MutableLiveData = MutableLiveData() private val _historyA: MutableLiveData = MutableLiveData() @@ -43,7 +46,7 @@ class HistoryListViewModel : ViewModel() { return _scrollDown } - private fun getScoreA() { + private fun getScoreA(scores: List) { var tempScore = 0 scores.forEach { it.scoreA?.let { it -> tempScore += it } @@ -51,7 +54,7 @@ class HistoryListViewModel : ViewModel() { _totalScoreA.value = tempScore } - private fun getScoreB() { + private fun getScoreB(scores: List) { var tempScore = 0 scores.forEach { it.scoreB?.let { it -> tempScore += it } @@ -59,7 +62,7 @@ class HistoryListViewModel : ViewModel() { _totalScoreB.value = tempScore } - private fun getHistoryA() { + private fun getHistoryA(scores: List) { var tempHistory = String() scores.forEach { tempHistory += it.scoreA.toString() + "\n" @@ -67,7 +70,7 @@ class HistoryListViewModel : ViewModel() { _historyA.value = tempHistory } - private fun getHistoryB() { + private fun getHistoryB(scores: List) { var tempHistory = String() scores.forEach { tempHistory += it.scoreB.toString() + "\n" @@ -75,33 +78,21 @@ class HistoryListViewModel : ViewModel() { _historyB.value = tempHistory } - private fun updateAll() { - getHistoryA() - getHistoryB() - getScoreA() - getScoreB() - scrollDown() - } - - fun logRound(round: Round) { - scores.add(round.copy()) - updateAll() - } - - fun revertLastRound() { - if (scores.isNotEmpty()) { - scores.removeAt(scores.size - 1) + fun updateAll() { + viewModelScope.launch { + val scores = gameRepository.getActiveRoundHistory() + getHistoryA(scores) + getHistoryB(scores) + getScoreA(scores) + getScoreB(scores) + scrollDown() } - updateAll() + + } private fun scrollDown() { _scrollDown.value = true } - - fun clearAll() { - scores.clear() - updateAll() - } } diff --git a/app/src/main/java/me/zobrist/tichucounter/fragments/KeyboardViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/fragments/KeyboardViewModel.kt index e5331d9..4bfd298 100644 --- a/app/src/main/java/me/zobrist/tichucounter/fragments/KeyboardViewModel.kt +++ b/app/src/main/java/me/zobrist/tichucounter/fragments/KeyboardViewModel.kt @@ -4,13 +4,20 @@ import SingleLiveEvent import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import me.zobrist.tichucounter.repository.GameRepository +import javax.inject.Inject -class KeyboardViewModel : ViewModel() { +@HiltViewModel +class KeyboardViewModel @Inject constructor(val gameRepository: GameRepository) : ViewModel() { private val _scoreA: MutableLiveData = MutableLiveData() private val _scoreB: MutableLiveData = MutableLiveData() private val _enableSubmitButton: MutableLiveData = MutableLiveData() private val _submitButtonClicked: SingleLiveEvent = SingleLiveEvent() + val scoreA: LiveData get() { return _scoreA @@ -44,6 +51,12 @@ class KeyboardViewModel : ViewModel() { } fun submitButtonClicked() { - _submitButtonClicked.value = true + viewModelScope.launch { + gameRepository.addRoundToActiveGame(scoreA.value!!, scoreB.value!!) + _scoreA.value = null + _scoreB.value = null + setSubmitButtonEnable(false) + _submitButtonClicked.value = true + } } } \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/repository/GameRepository.kt b/app/src/main/java/me/zobrist/tichucounter/repository/GameRepository.kt new file mode 100644 index 0000000..1ef4c0d --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/repository/GameRepository.kt @@ -0,0 +1,53 @@ +package me.zobrist.tichucounter.repository + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import me.zobrist.tichucounter.data.Game +import me.zobrist.tichucounter.data.GameDao +import me.zobrist.tichucounter.data.Round +import me.zobrist.tichucounter.data.RoundDao +import javax.inject.Inject + +class GameRepository @Inject constructor(private val gameDao: GameDao, private val roundDao: RoundDao) { + + suspend fun newGame(): Game { + return withContext(Dispatchers.IO) { + val game = Game(true, "TeamA", "TeamB") + gameDao.insertAll(game) + setActive(game) + return@withContext gameDao.getActive() + } + + } + + suspend fun getActiveGame(): Game { + return withContext(Dispatchers.IO) { + return@withContext gameDao.getActive() + } + } + + suspend fun setActive(game: Game) + { + withContext(Dispatchers.IO) { + game.uid?.let { gameDao.setActive(it) } + game.uid?.let { gameDao.setOthersInactive(it) } + } + } + + suspend fun getActiveRoundHistory(): List + { + return withContext(Dispatchers.IO) { + val active = getActiveGame() + return@withContext roundDao.getAllForGame(active.uid) + } + } + + suspend fun addRoundToActiveGame(scoreA: Int, scoreB: Int) + { + withContext(Dispatchers.IO) { + val active = getActiveGame() + val round = Round(active.uid!!, scoreA, scoreB) + roundDao.insertAll(round) + } + } +} \ No newline at end of file