Use compose for keyboard.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -5,7 +5,7 @@ import javax.inject.Inject
|
||||
|
||||
class Tichu @Inject constructor() {
|
||||
|
||||
fun calculateOtherScore(score: Int?): Int? {
|
||||
fun calculateOtherScore(score: Int): Int? {
|
||||
if (score == null) {
|
||||
return null
|
||||
}
|
||||
@@ -21,10 +21,10 @@ class Tichu @Inject constructor() {
|
||||
return 100 - (score % 100)
|
||||
}
|
||||
|
||||
fun isValidRound(round: Round): Boolean {
|
||||
if (round.scoreA == null || round.scoreB == null) {
|
||||
fun isValidRound(scoreA: Int?, scoreB: Int?): Boolean {
|
||||
if (scoreA == null || scoreB == null) {
|
||||
return false
|
||||
}
|
||||
return (round.scoreA!!.isMultipleOf5()) && round.scoreB!!.isMultipleOf5() && (round.scoreA!! + round.scoreB!!).isMultipleOf100()
|
||||
return (scoreA!!.isMultipleOf5()) && scoreB!!.isMultipleOf5() && (scoreA!! + scoreB!!).isMultipleOf100()
|
||||
}
|
||||
}
|
||||
@@ -42,43 +42,6 @@ class CounterFragment : FragmentBase<FragmentCounterBinding>(), MenuProvider {
|
||||
this, viewLifecycleOwner, Lifecycle.State.RESUMED
|
||||
)
|
||||
|
||||
keyboardViewModel.scoreA.observe(viewLifecycleOwner) { value ->
|
||||
val tichu = Tichu()
|
||||
|
||||
val oldValue = currentRound.scoreA
|
||||
currentRound.scoreA = value
|
||||
|
||||
if (ignoreNextUpdate) {
|
||||
ignoreNextUpdate = false
|
||||
} else {
|
||||
if (currentRound.scoreA?.let { oldValue?.getAbsoluteDifference(it) } != 100) {
|
||||
ignoreNextUpdate = true
|
||||
currentRound.scoreB = tichu.calculateOtherScore(value)
|
||||
keyboardViewModel.setScoreB(currentRound.scoreB)
|
||||
}
|
||||
|
||||
keyboardViewModel.setSubmitButtonEnable(tichu.isValidRound(currentRound))
|
||||
}
|
||||
}
|
||||
|
||||
keyboardViewModel.scoreB.observe(viewLifecycleOwner) { value ->
|
||||
val tichu = Tichu()
|
||||
|
||||
val oldValue = currentRound.scoreB
|
||||
currentRound.scoreB = value
|
||||
|
||||
if (ignoreNextUpdate) {
|
||||
ignoreNextUpdate = false
|
||||
} else {
|
||||
if (currentRound.scoreB?.let { oldValue?.getAbsoluteDifference(it) } != 100) {
|
||||
ignoreNextUpdate = true
|
||||
currentRound.scoreA = tichu.calculateOtherScore(value)
|
||||
keyboardViewModel.setScoreA(currentRound.scoreA)
|
||||
}
|
||||
|
||||
keyboardViewModel.setSubmitButtonEnable(tichu.isValidRound(currentRound))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||
|
||||
@@ -1,17 +1,33 @@
|
||||
package me.zobrist.tichucounter.ui.counter
|
||||
|
||||
import android.content.Context
|
||||
import android.icu.number.FormattedNumber
|
||||
import android.os.Bundle
|
||||
import android.text.InputType
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.*
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import me.zobrist.tichucounter.databinding.FragmentKeyboardBinding
|
||||
import me.zobrist.tichucounter.domain.Tichu
|
||||
import me.zobrist.tichucounter.ui.FragmentBase
|
||||
import me.zobrist.tichucounter.ui.history.IHistoryFragmentViewModel
|
||||
|
||||
@AndroidEntryPoint
|
||||
class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
||||
@@ -19,226 +35,280 @@ class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentKeyboardBinding
|
||||
get() = FragmentKeyboardBinding::inflate
|
||||
|
||||
private var unhandledNegation: Boolean = false
|
||||
|
||||
private val viewModel: KeyboardViewModel by activityViewModels()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
private val requester = FocusRequester()
|
||||
private var isAFocused: Boolean = false
|
||||
private var isBFocused: Boolean = false
|
||||
|
||||
binding.inputTeamA.setRawInputType(InputType.TYPE_NULL)
|
||||
binding.inputTeamB.setRawInputType(InputType.TYPE_NULL)
|
||||
binding.inputTeamA.requestFocus()
|
||||
var enableSubmit = mutableStateOf(false)
|
||||
|
||||
disableSubmitButton()
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
||||
viewModel.enableSubmitButton.observe(viewLifecycleOwner) { enabled ->
|
||||
if (enabled) enableSubmitButton() else disableSubmitButton()
|
||||
}
|
||||
|
||||
viewModel.scoreA.observe(viewLifecycleOwner) { value ->
|
||||
updateScore(binding.inputTeamA, value)
|
||||
}
|
||||
|
||||
viewModel.scoreB.observe(viewLifecycleOwner) { value ->
|
||||
updateScore(binding.inputTeamB, value)
|
||||
}
|
||||
|
||||
setListeners()
|
||||
|
||||
}
|
||||
|
||||
private fun setListeners() {
|
||||
binding.inputTeamA.setOnFocusChangeListener { _, b ->
|
||||
if (b) {
|
||||
hideKeyboard()
|
||||
snapshotFlow { viewModel.scoreA.value }
|
||||
.onEach {
|
||||
enableSubmitOnValidRound(viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
binding.inputTeamB.setOnFocusChangeListener { _, b ->
|
||||
if (b) {
|
||||
hideKeyboard()
|
||||
snapshotFlow { viewModel.scoreB.value }
|
||||
.onEach {
|
||||
enableSubmitOnValidRound(viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
binding.buttonAdd100.setOnClickListener {
|
||||
var value = getActiveValue()
|
||||
|
||||
value = if (value != null) {
|
||||
value + 100
|
||||
} else {
|
||||
100
|
||||
}
|
||||
setActiveValue(value)
|
||||
}
|
||||
|
||||
binding.buttonSub100.setOnClickListener {
|
||||
var value = getActiveValue()
|
||||
|
||||
value = if (value != null) {
|
||||
value!! - 100
|
||||
} else {
|
||||
-100
|
||||
}
|
||||
setActiveValue(value)
|
||||
}
|
||||
|
||||
binding.button0.setOnClickListener {
|
||||
appendToFocusedScore(0)
|
||||
}
|
||||
|
||||
binding.button1.setOnClickListener {
|
||||
appendToFocusedScore(1)
|
||||
}
|
||||
|
||||
binding.button2.setOnClickListener {
|
||||
appendToFocusedScore(2)
|
||||
}
|
||||
|
||||
binding.button3.setOnClickListener {
|
||||
appendToFocusedScore(3)
|
||||
}
|
||||
|
||||
binding.button4.setOnClickListener {
|
||||
appendToFocusedScore(4)
|
||||
}
|
||||
|
||||
binding.button5.setOnClickListener {
|
||||
appendToFocusedScore(5)
|
||||
}
|
||||
|
||||
binding.button6.setOnClickListener {
|
||||
appendToFocusedScore(6)
|
||||
}
|
||||
|
||||
binding.button7.setOnClickListener {
|
||||
appendToFocusedScore(7)
|
||||
}
|
||||
|
||||
binding.button8.setOnClickListener {
|
||||
appendToFocusedScore(8)
|
||||
}
|
||||
|
||||
binding.button9.setOnClickListener {
|
||||
appendToFocusedScore(9)
|
||||
}
|
||||
|
||||
binding.buttonInv.setOnClickListener {
|
||||
var value = getActiveValue()
|
||||
|
||||
if (value == null) {
|
||||
unhandledNegation = if (getActiveText() == "-") {
|
||||
setActiveText("")
|
||||
false
|
||||
} else {
|
||||
setActiveText("-")
|
||||
true
|
||||
}
|
||||
} else {
|
||||
value = value?.times(-1)
|
||||
setActiveValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
binding.buttonBack.setOnClickListener {
|
||||
var value = getActiveValue()
|
||||
|
||||
if (value != null) {
|
||||
value = try {
|
||||
value.toString().dropLast(1).toInt()
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
return ComposeView(requireContext()).apply {
|
||||
// Dispose of the Composition when the view's LifecycleOwner
|
||||
// is destroyed
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
MaterialTheme {
|
||||
KeyboardView(viewModel)
|
||||
}
|
||||
}
|
||||
setActiveValue(value)
|
||||
}
|
||||
|
||||
binding.submit.setOnClickListener {
|
||||
viewModel.submitButtonClicked()
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideKeyboard() {
|
||||
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
|
||||
imm?.hideSoftInputFromWindow(view?.windowToken, 0)
|
||||
private fun enableSubmitOnValidRound(viewModel: IKeyboardViewModel) {
|
||||
enableSubmit.value = try {
|
||||
val tichu = Tichu()
|
||||
if(tichu.isValidRound(viewModel.scoreA.value.toInt(), viewModel.scoreB.value.toInt()))
|
||||
{
|
||||
true
|
||||
}
|
||||
false
|
||||
} catch(_:Exception)
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun giveFocusToAIfNone() {
|
||||
if (!binding.inputTeamA.isFocused && !binding.inputTeamB.isFocused) {
|
||||
binding.inputTeamA.requestFocus()
|
||||
if(!isAFocused && !isBFocused)
|
||||
{
|
||||
requester.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateScore(field: EditText, score: Int?) {
|
||||
if (score == null) {
|
||||
field.setText("")
|
||||
return
|
||||
}
|
||||
|
||||
val text = try {
|
||||
score.toString()
|
||||
} catch (e: Exception) {
|
||||
""
|
||||
}
|
||||
field.setText(text)
|
||||
private fun appendToFocusedScore(toAppend: String, viewModel: IKeyboardViewModel) {
|
||||
val value = getActiveValue(viewModel)
|
||||
value.value += toAppend
|
||||
updateOtherScore(viewModel)
|
||||
}
|
||||
|
||||
private fun appendToFocusedScore(toAppend: Int) {
|
||||
var value = getActiveValue()
|
||||
private fun updateOtherScore(viewModel: IKeyboardViewModel) {
|
||||
val value = getActiveValue(viewModel)
|
||||
|
||||
if (value != null) {
|
||||
value = value.times(10)
|
||||
value = value.plus(toAppend)
|
||||
try {
|
||||
val tichu = Tichu()
|
||||
val myScore = value.value.toInt()
|
||||
val hisScore = tichu.calculateOtherScore(myScore)
|
||||
if(tichu.isValidRound(myScore, hisScore))
|
||||
{
|
||||
updateInactiveValue(hisScore?.toString() ?: "", viewModel)
|
||||
} else
|
||||
{
|
||||
updateInactiveValue("", viewModel)
|
||||
}
|
||||
} catch(_: Exception) {
|
||||
updateInactiveValue("", viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
private fun negateActiveInput(viewModel: IKeyboardViewModel) {
|
||||
val value = getActiveValue(viewModel)
|
||||
|
||||
if(value.value.contains("-"))
|
||||
{
|
||||
value.value = value.value.replace("-", "")
|
||||
} else {
|
||||
value = toAppend
|
||||
if (unhandledNegation) {
|
||||
value = value.times(-1)
|
||||
unhandledNegation = false
|
||||
value.value = "-" + value.value
|
||||
}
|
||||
|
||||
updateOtherScore(viewModel)
|
||||
}
|
||||
|
||||
private fun addToActiveInput(toAdd: Int, viewModel: IKeyboardViewModel) {
|
||||
val value = getActiveValue(viewModel)
|
||||
|
||||
try {
|
||||
val temp = value.value.toInt() + toAdd
|
||||
value.value = temp.toString()
|
||||
} catch (e: Exception) {
|
||||
value.value = toAdd.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeFromActiveInput(viewModel: IKeyboardViewModel) {
|
||||
val value = getActiveValue(viewModel)
|
||||
if(value.value != "") {
|
||||
value.value = value.value.dropLast(1)
|
||||
}
|
||||
updateOtherScore(viewModel)
|
||||
}
|
||||
|
||||
private fun getActiveValue(viewModel: IKeyboardViewModel): MutableState<String> {
|
||||
giveFocusToAIfNone()
|
||||
if (isBFocused) {
|
||||
return viewModel.scoreB
|
||||
}
|
||||
return viewModel.scoreA
|
||||
}
|
||||
|
||||
private fun updateInactiveValue(value: String, viewModel: IKeyboardViewModel){
|
||||
giveFocusToAIfNone()
|
||||
if (isBFocused) {
|
||||
viewModel.scoreA.value = value
|
||||
} else
|
||||
{
|
||||
viewModel.scoreB.value = value
|
||||
}
|
||||
|
||||
try {
|
||||
val tichu = Tichu()
|
||||
enableSubmit.value = tichu.isValidRound(viewModel.scoreA.value.toInt(), viewModel.scoreB.value.toInt())
|
||||
} catch(_: java.lang.NumberFormatException) {
|
||||
enableSubmit.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun KeyboardView(viewModel: IKeyboardViewModel = DefaultViewModel()) {
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
||||
Column {
|
||||
Row {
|
||||
CompositionLocalProvider(
|
||||
LocalTextToolbar provides EmptyTextToolbar
|
||||
) {
|
||||
TextField(
|
||||
value = viewModel.scoreA.value,
|
||||
onValueChange = { },
|
||||
placeholder = { Text("0") },
|
||||
singleLine = true,
|
||||
modifier = Modifier
|
||||
.onFocusChanged {
|
||||
keyboardController?.hide()
|
||||
isAFocused = it.isFocused
|
||||
}
|
||||
.focusRequester(requester)
|
||||
.weight(1f),
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
cursorColor = Color.Transparent,
|
||||
errorCursorColor = Color.Transparent
|
||||
)
|
||||
)
|
||||
TextField(
|
||||
value = viewModel.scoreB.value,
|
||||
onValueChange = { },
|
||||
placeholder = { Text("0") },
|
||||
singleLine = true,
|
||||
modifier = Modifier
|
||||
.onFocusChanged {
|
||||
keyboardController?.hide()
|
||||
isBFocused = it.isFocused
|
||||
}
|
||||
.weight(1f),
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
cursorColor = Color.Transparent,
|
||||
errorCursorColor = Color.Transparent
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("1", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("1") }
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("2", viewModel ) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("2") }
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("3", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("3") }
|
||||
Button(onClick = { addToActiveInput(100, viewModel) }, modifier = Modifier.weight(1F)) { Text("+100") }
|
||||
|
||||
}
|
||||
Row {
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("4", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("4") }
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("5", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("5") }
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("6", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("6") }
|
||||
Button(onClick = { addToActiveInput(-100, viewModel) }, modifier = Modifier.weight(1F)) { Text("-100") }
|
||||
}
|
||||
Row {
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("7", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("7") }
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("8", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("8") }
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("9", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("9") }
|
||||
Button(onClick = { removeFromActiveInput(viewModel) }, modifier = Modifier.weight(1F)) { Text("DEL") }
|
||||
}
|
||||
Row {
|
||||
Button(onClick = { negateActiveInput(viewModel) }, modifier = Modifier.weight(1F)) { Text("+/-") }
|
||||
Button(
|
||||
onClick = { appendToFocusedScore("0", viewModel) },
|
||||
modifier = Modifier.weight(1F)
|
||||
) { Text("0") }
|
||||
Spacer(modifier = Modifier.weight(1F))
|
||||
Button(onClick = { submit(viewModel) }, modifier = Modifier.weight(1F), enabled = enableSubmit.value) { Text("ENTER") }
|
||||
}
|
||||
}
|
||||
setActiveValue(value)
|
||||
}
|
||||
|
||||
private fun getActiveValue(): Int? {
|
||||
giveFocusToAIfNone()
|
||||
if (binding.inputTeamA.isFocused) {
|
||||
return viewModel.scoreA.value
|
||||
}
|
||||
return viewModel.scoreB.value
|
||||
private fun submit(viewModel: IKeyboardViewModel) {
|
||||
viewModel.submitScore(viewModel.scoreA.value.toInt(), viewModel.scoreB.value.toInt())
|
||||
viewModel.scoreA.value = ""
|
||||
viewModel.scoreB.value = ""
|
||||
enableSubmit.value = false
|
||||
}
|
||||
|
||||
private fun setActiveValue(value: Int?) {
|
||||
giveFocusToAIfNone()
|
||||
if (binding.inputTeamA.isFocused) {
|
||||
viewModel.setScoreA(value)
|
||||
} else {
|
||||
viewModel.setScoreB(value)
|
||||
object EmptyTextToolbar : TextToolbar {
|
||||
override val status: TextToolbarStatus = TextToolbarStatus.Hidden
|
||||
|
||||
override fun hide() {}
|
||||
|
||||
override fun showMenu(
|
||||
rect: Rect,
|
||||
onCopyRequested: (() -> Unit)?,
|
||||
onPasteRequested: (() -> Unit)?,
|
||||
onCutRequested: (() -> Unit)?,
|
||||
onSelectAllRequested: (() -> Unit)?,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getActiveText(): String {
|
||||
giveFocusToAIfNone()
|
||||
if (binding.inputTeamA.isFocused) {
|
||||
return binding.inputTeamA.text.toString()
|
||||
}
|
||||
return binding.inputTeamB.text.toString()
|
||||
}
|
||||
internal class DefaultViewModel : IKeyboardViewModel {
|
||||
override var scoreA: MutableState<String> = mutableStateOf("")
|
||||
override var scoreB: MutableState<String> = mutableStateOf("")
|
||||
|
||||
private fun setActiveText(value: String) {
|
||||
giveFocusToAIfNone()
|
||||
if (binding.inputTeamA.isFocused) {
|
||||
binding.inputTeamA.setText(value)
|
||||
} else {
|
||||
binding.inputTeamB.setText(value)
|
||||
override fun submitScore(scoreA: Int, scoreB: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun enableSubmitButton() {
|
||||
binding.submit.imageAlpha = 255 // 0 being transparent and 255 being opaque
|
||||
binding.submit.isEnabled = true
|
||||
}
|
||||
|
||||
private fun disableSubmitButton() {
|
||||
binding.submit.imageAlpha = 60 // 0 being transparent and 255 being opaque
|
||||
binding.submit.isEnabled = false
|
||||
}
|
||||
}
|
||||
@@ -1,54 +1,37 @@
|
||||
package me.zobrist.tichucounter.ui.counter
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
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.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import me.zobrist.tichucounter.domain.Tichu
|
||||
import me.zobrist.tichucounter.repository.GameRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
interface IKeyboardViewModel {
|
||||
var scoreA: MutableState<String>
|
||||
var scoreB: MutableState<String>
|
||||
fun submitScore(scoreA: Int, scoreB: Int)
|
||||
}
|
||||
|
||||
@HiltViewModel
|
||||
class KeyboardViewModel @Inject constructor(private val gameRepository: GameRepository) :
|
||||
ViewModel() {
|
||||
private val _scoreA: MutableLiveData<Int?> = MutableLiveData()
|
||||
private val _scoreB: MutableLiveData<Int?> = MutableLiveData()
|
||||
private val _enableSubmitButton: MutableLiveData<Boolean> = MutableLiveData()
|
||||
ViewModel(), IKeyboardViewModel {
|
||||
override var scoreA = mutableStateOf( "")
|
||||
override var scoreB = mutableStateOf("")
|
||||
|
||||
val scoreA: LiveData<Int?>
|
||||
get() {
|
||||
return _scoreA
|
||||
}
|
||||
|
||||
val scoreB: LiveData<Int?>
|
||||
get() {
|
||||
return _scoreB
|
||||
}
|
||||
|
||||
val enableSubmitButton: LiveData<Boolean>
|
||||
get() {
|
||||
return _enableSubmitButton
|
||||
}
|
||||
|
||||
fun setScoreA(score: Int?) {
|
||||
_scoreA.value = score
|
||||
}
|
||||
|
||||
fun setScoreB(score: Int?) {
|
||||
_scoreB.value = score
|
||||
}
|
||||
|
||||
fun setSubmitButtonEnable(enabled: Boolean) {
|
||||
_enableSubmitButton.value = enabled
|
||||
}
|
||||
|
||||
fun submitButtonClicked() {
|
||||
override fun submitScore(scoreA: Int, scoreB: Int) {
|
||||
viewModelScope.launch {
|
||||
gameRepository.addRoundToActiveGame(scoreA.value!!, scoreB.value!!)
|
||||
_scoreA.value = null
|
||||
_scoreB.value = null
|
||||
setSubmitButtonEnable(false)
|
||||
gameRepository.addRoundToActiveGame(scoreA, scoreB)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,13 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardElevation
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -82,23 +84,28 @@ class HistoryFragment : Fragment() {
|
||||
Row() {
|
||||
Text(
|
||||
text = game.nameA,
|
||||
style = MaterialTheme.typography.headlineSmall)
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Text(
|
||||
text = game.scoreA.toString(),
|
||||
style = MaterialTheme.typography.headlineSmall)
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
}
|
||||
Row() {
|
||||
Text(
|
||||
text = game.nameB,
|
||||
style = MaterialTheme.typography.headlineSmall)
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Text(
|
||||
text = game.scoreB.toString(),
|
||||
style = MaterialTheme.typography.headlineSmall)
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
}
|
||||
Row() {
|
||||
Text(
|
||||
text = format.format(game.modified),
|
||||
style = MaterialTheme.typography.labelSmall)
|
||||
style = MaterialTheme.typography.labelSmall
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,8 +116,30 @@ class HistoryFragment : Fragment() {
|
||||
override val gameAndHistory: State<List<GameAndScore>>
|
||||
get() {
|
||||
val tempData = mutableListOf<GameAndScore>()
|
||||
tempData.add(GameAndScore(false, "TeamA1sdfdsf", "TeamB1", Date(), Date(), 1, 10, 50))
|
||||
tempData.add(GameAndScore(true, "TeamA2", "TeamB2sdfsdf", Date(), Date(), 2, 20, 60))
|
||||
tempData.add(
|
||||
GameAndScore(
|
||||
false,
|
||||
"TeamA1sdfdsf",
|
||||
"TeamB1",
|
||||
Date(),
|
||||
Date(),
|
||||
1,
|
||||
10,
|
||||
50
|
||||
)
|
||||
)
|
||||
tempData.add(
|
||||
GameAndScore(
|
||||
true,
|
||||
"TeamA2",
|
||||
"TeamB2sdfsdf",
|
||||
Date(),
|
||||
Date(),
|
||||
2,
|
||||
20,
|
||||
60
|
||||
)
|
||||
)
|
||||
tempData.add(GameAndScore(false, "TeamA3", "TeamB3", Date(), Date(), 3, 30, 70))
|
||||
tempData.add(GameAndScore(false, "TeamA4", "TeamB4", Date(), Date(), 4, 40, 80))
|
||||
tempData.add(GameAndScore(false, "TeamA5", "TeamB5", Date(), Date(), 5, 50, 90))
|
||||
|
||||
@@ -37,26 +37,26 @@ class TichuUnitTest {
|
||||
assertGeneratedRound(tichu, 400, 0)
|
||||
|
||||
//Good rounds trough Tichu
|
||||
assertValidRound(tichu, Round(1, 0, 0))
|
||||
assertValidRound(tichu, Round(1, -100, 0))
|
||||
assertValidRound(tichu, 0, 0)
|
||||
assertValidRound(tichu, -100, 0)
|
||||
|
||||
//Bad rounds
|
||||
assertInvalidRound(tichu, Round(1, 5, 12))
|
||||
assertInvalidRound(tichu, Round(1, 12, 5))
|
||||
assertInvalidRound(tichu, Round(1, 5, 55))
|
||||
assertInvalidRound(tichu, 5, 12)
|
||||
assertInvalidRound(tichu, 12, 5)
|
||||
assertInvalidRound(tichu, 5, 55)
|
||||
}
|
||||
|
||||
private fun assertGeneratedRound(tichu: Tichu, scoreA: Int, expectedScoreB: Int) {
|
||||
val round = Round(1, scoreA, tichu.calculateOtherScore(scoreA))
|
||||
assertEquals(expectedScoreB, round.scoreB)
|
||||
assertTrue(tichu.isValidRound(round))
|
||||
val scoreB = tichu.calculateOtherScore(scoreA)
|
||||
assertEquals(expectedScoreB, scoreB)
|
||||
assertTrue(tichu.isValidRound(scoreA, scoreB!!))
|
||||
}
|
||||
|
||||
private fun assertInvalidRound(tichu: Tichu, round: Round) {
|
||||
assertFalse(tichu.isValidRound(round))
|
||||
private fun assertInvalidRound(tichu: Tichu, scoreA: Int, scoreB: Int) {
|
||||
assertFalse(tichu.isValidRound(scoreA, scoreB))
|
||||
}
|
||||
|
||||
private fun assertValidRound(tichu: Tichu, round: Round) {
|
||||
assertTrue(tichu.isValidRound(round))
|
||||
private fun assertValidRound(tichu: Tichu, scoreA: Int, scoreB: Int) {
|
||||
assertTrue(tichu.isValidRound(scoreA, scoreB))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user