Show history.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-01-06 19:44:02 +01:00
parent 1e428e854e
commit 74be455d48
27 changed files with 358 additions and 150 deletions

View File

@@ -6,10 +6,10 @@ import java.util.*
@Entity
data class Game(
val active: Boolean,
var nameA: String,
var nameB: String,
val created: Date,
var modified: Date,
@PrimaryKey(autoGenerate = true) val uid: Long? = null
)
override var active: Boolean,
override var nameA: String,
override var nameB: String,
override val created: Date,
override var modified: Date,
@PrimaryKey(autoGenerate = true) override val uid: Long? = null
) : IGame, IEntity

View File

@@ -0,0 +1,17 @@
package me.zobrist.tichucounter.data
import androidx.room.Entity
import java.util.*
@Entity
data class GameAndScore(
override var active: Boolean,
override var nameA: String,
override var nameB: String,
override val created: Date,
override var modified: Date,
override var gameId: Long,
override var scoreA: Int?,
override var scoreB: Int?,
) : IGame, IRound {
}

View File

@@ -7,6 +7,14 @@ import kotlinx.coroutines.flow.Flow
@Dao
interface GameDao : DaoBase<Game> {
@Query("SELECT * FROM game")
fun getAll(): Flow<List<Game>>
@Query("SELECT *, SUM(round.scoreA) as scoreA, SUM(round.scoreB) as scoreB, SUM(round.scoreB) as scoreB " +
"FROM game " +
"LEFT JOIN round ON round.gameId = game.uid GROUP BY gameId ORDER BY modified DESC")
fun getAllWithPoints(): Flow<List<GameAndScore>>
@Query("SELECT * FROM game WHERE uid is :gameId")
fun getGameById(gameId: Long): Flow<Game>

View File

@@ -0,0 +1,5 @@
package me.zobrist.tichucounter.data
interface IEntity {
val uid: Long?
}

View File

@@ -0,0 +1,11 @@
package me.zobrist.tichucounter.data
import java.util.*
interface IGame {
var active: Boolean
var nameA: String
var nameB: String
val created: Date
var modified: Date
}

View File

@@ -0,0 +1,7 @@
package me.zobrist.tichucounter.data
interface IRound {
var gameId: Long
var scoreA: Int?
var scoreB: Int?
}

View File

@@ -5,8 +5,8 @@ import androidx.room.PrimaryKey
@Entity
data class Round(
var gameId: Long,
var scoreA: Int?,
var scoreB: Int?,
@PrimaryKey(autoGenerate = true) val uid: Long? = null
)
override var gameId: Long,
override var scoreA: Int?,
override var scoreB: Int?,
@PrimaryKey(autoGenerate = true) override val uid: Long? = null
) : IRound, IEntity

View File

@@ -9,6 +9,14 @@ interface RoundDao : DaoBase<Round> {
@Query("SELECT * FROM round WHERE gameId is :gameId")
fun getAllForGame(gameId: Long?): List<Round>
@Query(
"SELECT gameId, SUM(scoreA) as scoreA, SUM(scoreB) as scoreB " +
"FROM round " +
"LEFT JOIN game ON game.uid = round.gameId " +
"WHERE game.active == 1"
)
fun getRoundSumForActiveGame() : Flow<Round>
@Query(
"SELECT gameId, scoreA, scoreB, round.uid " +
"FROM round " +

View File

@@ -6,16 +6,16 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import dagger.hilt.android.AndroidEntryPoint
import me.zobrist.tichucounter.databinding.FragmentHistoryListBinding
import me.zobrist.tichucounter.databinding.FragmentRoundListBinding
import me.zobrist.tichucounter.ui.FragmentBase
@AndroidEntryPoint
class HistoryList : FragmentBase<FragmentHistoryListBinding>() {
class RoundList : FragmentBase<FragmentRoundListBinding>() {
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentHistoryListBinding
get() = FragmentHistoryListBinding::inflate
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentRoundListBinding
get() = FragmentRoundListBinding::inflate
private val viewModel: HistoryListViewModel by activityViewModels()
private val viewModel: RoundListViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@@ -12,7 +12,7 @@ import me.zobrist.tichucounter.framework.SingleLiveEvent
import javax.inject.Inject
@HiltViewModel
class HistoryListViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel() {
class RoundListViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel() {
private val _historyA: MutableLiveData<String> = MutableLiveData<String>()
private val _historyB: MutableLiveData<String> = MutableLiveData<String>()

View File

@@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import me.zobrist.tichucounter.data.Round
import me.zobrist.tichucounter.data.RoundDao
@@ -18,26 +19,14 @@ class TeamScoresViewModel @Inject constructor(private val roundDao: RoundDao) :
init {
viewModelScope.launch {
roundDao.getForActiveGame().collect { scores ->
update(scores)
roundDao.getRoundSumForActiveGame().collect { score ->
_scoreA.value = if(score?.scoreA != null) score.scoreA else 0
_scoreB.value = if(score?.scoreB != null) score.scoreB else 0
}
}
}
private fun update(scores: List<Round>) {
var scoreA = 0
var scoreB = 0
scores.forEach {
it.scoreA?.let { a -> scoreA += a }
it.scoreB?.let { b -> scoreB += b }
}
_scoreA.value = scoreA
_scoreB.value = scoreB
}
val scoreA: LiveData<Int>
get() {
return _scoreA

View File

@@ -0,0 +1,68 @@
package me.zobrist.tichucounter.ui.history
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import dagger.hilt.android.AndroidEntryPoint
import me.zobrist.tichucounter.R
/**
* A fragment representing a list of Items.
*/
@AndroidEntryPoint
class HistoryFragment : Fragment() {
private val viewModel: HistoryFragmentViewModel by activityViewModels()
private var columnCount = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
columnCount = it.getInt(ARG_COLUMN_COUNT)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_history_list, container, false)
// Set the adapter
if (view is RecyclerView) {
with(view) {
layoutManager = when {
columnCount <= 1 -> LinearLayoutManager(context)
else -> GridLayoutManager(context, columnCount)
}
viewModel.gameAndHistory.observe(viewLifecycleOwner) {
adapter = MyGameRecyclerViewAdapter(it)
}
}
}
return view
}
companion object {
const val ARG_COLUMN_COUNT = "1"
@JvmStatic
fun newInstance(columnCount: Int) =
HistoryFragment().apply {
arguments = Bundle().apply {
putInt(ARG_COLUMN_COUNT, columnCount)
}
}
}
}

View File

@@ -0,0 +1,32 @@
package me.zobrist.tichucounter.ui.history
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.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.zobrist.tichucounter.data.GameAndScore
import me.zobrist.tichucounter.data.GameDao
import me.zobrist.tichucounter.data.RoundDao
import javax.inject.Inject
@HiltViewModel
class HistoryFragmentViewModel @Inject constructor(private val gameDao: GameDao, private val roundDao: RoundDao) : ViewModel() {
private val _gameAndHistory: MutableLiveData<List<GameAndScore>> = MutableLiveData()
val gameAndHistory: LiveData<List<GameAndScore>>
get() { return _gameAndHistory}
init {
viewModelScope.launch {
gameDao.getAllWithPoints().collect { games ->
_gameAndHistory.value = games
}
}
}
}

View File

@@ -0,0 +1,49 @@
package me.zobrist.tichucounter.ui.history
import android.provider.Settings.Global.getString
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.res.TypedArrayUtils
import me.zobrist.tichucounter.R
import me.zobrist.tichucounter.data.GameAndScore
import me.zobrist.tichucounter.databinding.FragmentHistoryBinding
import java.text.DateFormat
/**
* [RecyclerView.Adapter] that can display a [GameAndScore].
* TODO: Replace the implementation with code for your data type.
*/
class MyGameRecyclerViewAdapter(
private val values: List<GameAndScore>
) : RecyclerView.Adapter<MyGameRecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
FragmentHistoryBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = values[position]
holder.title.text = "${item.nameA} - ${item.nameB}"
holder.secondary.text = item.scoreA.toString() + ":" + item.scoreB
holder.support.text = DateFormat.getDateInstance().format(item.modified)
}
override fun getItemCount(): Int = values.size
inner class ViewHolder(binding: FragmentHistoryBinding) :
RecyclerView.ViewHolder(binding.root) {
val title: TextView = binding.cardTitle
val secondary: TextView = binding.cardSecondary
val support: TextView = binding.cardSupporting
}
}

View File

@@ -1,36 +0,0 @@
package me.zobrist.tichucounter.ui.slideshow
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import me.zobrist.tichucounter.databinding.FragmentSlideshowBinding
class SlideshowFragment : Fragment() {
private var _binding: FragmentSlideshowBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val slideshowViewModel =
ViewModelProvider(this)[SlideshowViewModel::class.java]
_binding = FragmentSlideshowBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@@ -1,13 +0,0 @@
package me.zobrist.tichucounter.ui.slideshow
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class SlideshowViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is slideshow Fragment"
}
val text: LiveData<String> = _text
}

View File

@@ -39,12 +39,12 @@
<androidx.fragment.app.FragmentContainerView
android:id="@+id/scrollHistory"
android:name="me.zobrist.tichucounter.ui.counter.HistoryList"
android:name="me.zobrist.tichucounter.ui.counter.RoundList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="16dp"
android:clickable="false"
tools:layout="@layout/fragment_history_list" />
tools:layout="@layout/fragment_round_list" />
</LinearLayout>
<LinearLayout

View File

@@ -41,7 +41,7 @@
<androidx.fragment.app.FragmentContainerView
android:id="@+id/scrollHistory"
android:name="me.zobrist.tichucounter.ui.counter.HistoryList"
android:name="me.zobrist.tichucounter.ui.counter.RoundList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
@@ -49,7 +49,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dividerTop"
tools:layout="@layout/fragment_history_list" />
tools:layout="@layout/fragment_round_list" />
<View
android:id="@+id/dividerBottom"

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Title, secondary and supporting text -->
<TextView
android:id="@+id/card_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceHeadline6"
/>
<TextView
android:id="@+id/card_secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
/>
<TextView
android:id="@+id/card_supporting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary"
/>
</LinearLayout>
</LinearLayout>

View File

@@ -1,45 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list"
android:name="me.zobrist.tichucounter.ui.slideshow.HistoryFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.counter.HistoryList">
<ScrollView
android:id="@+id/scrollViewHistory"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/historyA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:gravity="center"
tools:text="@tools:sample/cities" />
<TextView
android:id="@+id/historyB"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:gravity="center"
tools:text="@tools:sample/date/hhmmss" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context=".ui.history.HistoryFragment"
tools:listitem="@layout/fragment_history" />

View File

@@ -47,14 +47,13 @@
<LinearLayout
android:id="@+id/ButtonRow1"
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -63,7 +62,7 @@
<Button
android:id="@+id/button2"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -72,7 +71,7 @@
<Button
android:id="@+id/button3"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -81,7 +80,7 @@
<Button
android:id="@+id/buttonAdd100"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -91,14 +90,13 @@
<LinearLayout
android:id="@+id/ButtonRow2"
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button4"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -107,7 +105,7 @@
<Button
android:id="@+id/button5"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -116,7 +114,7 @@
<Button
android:id="@+id/button6"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -125,7 +123,7 @@
<Button
android:id="@+id/buttonSub100"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -135,14 +133,13 @@
<LinearLayout
android:id="@+id/ButtonRow3"
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button7"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -151,7 +148,7 @@
<Button
android:id="@+id/button8"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -160,7 +157,7 @@
<Button
android:id="@+id/button9"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -169,7 +166,7 @@
<ImageButton
android:id="@+id/buttonBack"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -184,7 +181,6 @@
<LinearLayout
android:id="@+id/ButtonRow4"
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@@ -194,7 +190,7 @@
<Button
android:id="@+id/buttonInv"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
@@ -202,24 +198,28 @@
<Button
android:id="@+id/button0"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="0" />
<Space
style='?android:attr/buttonBarButtonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
<ImageButton
android:id="@+id/submit"
style='style="?android:attr/buttonBarButtonStyle'
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.0"
android:contentDescription="TODO"
android:layout_weight="1"
android:contentDescription="@string/submit"
android:cropToPadding="false"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:scaleType="fitCenter"
app:srcCompat="@drawable/checkmark" />
</LinearLayout>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".ui.counter.RoundList">
<ScrollView
android:id="@+id/scrollViewHistory"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/historyA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:gravity="center"
tools:text="@tools:sample/cities" />
<TextView
android:id="@+id/historyB"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:gravity="center"
tools:text="@tools:sample/date/hhmmss" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>

View File

@@ -13,7 +13,7 @@
<fragment
android:id="@+id/nav_history"
android:name="me.zobrist.tichucounter.ui.settings.SettingsFragment"
android:name="me.zobrist.tichucounter.ui.history.HistoryFragment"
android:label="@string/menu_history"
tools:layout="@layout/fragment_slideshow" />

View File

@@ -16,4 +16,6 @@
<string name="dark">Dunkel</string>
<string name="settings">Einstellungen</string>
<string name="display">Anzeige</string>
<string name="activate">Aktivieren</string>
<string name="delete">Löschen</string>
</resources>

View File

@@ -5,4 +5,5 @@
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<dimen name="nav_header_height">176dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="text_margin">16dp</dimen>
</resources>

View File

@@ -32,4 +32,7 @@
<string name="menu_counter">Counter</string>
<string name="menu_history">History</string>
<string name="menu_settings">Settings</string>
<string name="activate">Activate</string>
<string name="delete">Delete</string>
<string name="submit">Submit</string>
</resources>