Add database. Write score to database and update.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2022-12-27 17:19:55 +01:00
parent 6edbe12fd1
commit 7655d1d7a3
14 changed files with 256 additions and 52 deletions

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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
}

View File

@@ -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()
}
}

View File

@@ -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
}
}

View File

@@ -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)

View File

@@ -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<Game>
@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)
}

View File

@@ -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)

View File

@@ -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<Round>
@Query("SELECT * FROM round WHERE gameId is :gameId")
fun getAllForGame(gameId: Int?): List<Round>
@Insert
fun insertAll(vararg rounds: Round)
@Delete
fun delete(round: Round)
}

View File

@@ -1,6 +0,0 @@
package me.zobrist.tichucounter.domain
import java.io.Serializable
data class Round(var scoreA: Int?, var scoreB: Int?) : Serializable {
}

View File

@@ -1,5 +1,6 @@
package me.zobrist.tichucounter.domain
import me.zobrist.tichucounter.data.Round
import javax.inject.Inject
class Tichu @Inject constructor() {

View File

@@ -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<Round>()
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<Int> = MutableLiveData<Int>()
private val _totalScoreB: MutableLiveData<Int> = MutableLiveData<Int>()
private val _historyA: MutableLiveData<String> = MutableLiveData<String>()
@@ -43,7 +46,7 @@ class HistoryListViewModel : ViewModel() {
return _scrollDown
}
private fun getScoreA() {
private fun getScoreA(scores: List<Round>) {
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<Round>) {
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<Round>) {
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<Round>) {
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()
}
}

View File

@@ -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<Int?> = MutableLiveData()
private val _scoreB: MutableLiveData<Int?> = MutableLiveData()
private val _enableSubmitButton: MutableLiveData<Boolean> = MutableLiveData()
private val _submitButtonClicked: SingleLiveEvent<Boolean> = SingleLiveEvent()
val scoreA: LiveData<Int?>
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
}
}
}

View File

@@ -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<Round>
{
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)
}
}
}