Move all functionality to viewmodel. Use simple button format.
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:
@@ -97,6 +97,7 @@ dependencies {
|
|||||||
implementation 'androidx.preference:preference-ktx:1.2.0'
|
implementation 'androidx.preference:preference-ktx:1.2.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
|
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
|
||||||
|
implementation 'androidx.compose.material:material-icons-extended:1.3.1'
|
||||||
implementation 'androidx.activity:activity-compose:1.3.1'
|
implementation 'androidx.activity:activity-compose:1.3.1'
|
||||||
implementation "androidx.compose.ui:ui:$compose_version"
|
implementation "androidx.compose.ui:ui:$compose_version"
|
||||||
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package me.zobrist.tichucounter.domain
|
package me.zobrist.tichucounter.domain
|
||||||
|
|
||||||
import me.zobrist.tichucounter.data.Round
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class Tichu @Inject constructor() {
|
class Tichu @Inject constructor() {
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import kotlinx.coroutines.launch
|
|||||||
import me.zobrist.tichucounter.R
|
import me.zobrist.tichucounter.R
|
||||||
import me.zobrist.tichucounter.data.Round
|
import me.zobrist.tichucounter.data.Round
|
||||||
import me.zobrist.tichucounter.databinding.FragmentCounterBinding
|
import me.zobrist.tichucounter.databinding.FragmentCounterBinding
|
||||||
import me.zobrist.tichucounter.domain.Tichu
|
|
||||||
import me.zobrist.tichucounter.domain.getAbsoluteDifference
|
|
||||||
import me.zobrist.tichucounter.repository.GameRepository
|
import me.zobrist.tichucounter.repository.GameRepository
|
||||||
import me.zobrist.tichucounter.ui.FragmentBase
|
import me.zobrist.tichucounter.ui.FragmentBase
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package me.zobrist.tichucounter.ui.counter
|
package me.zobrist.tichucounter.ui.counter
|
||||||
|
|
||||||
import android.icu.number.FormattedNumber
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -8,8 +7,14 @@ import android.view.ViewGroup
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Backspace
|
||||||
|
import androidx.compose.material.icons.outlined.Check
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
@@ -18,16 +23,13 @@ import androidx.compose.ui.focus.onFocusChanged
|
|||||||
import androidx.compose.ui.geometry.Rect
|
import androidx.compose.ui.geometry.Rect
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.*
|
import androidx.compose.ui.platform.*
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import me.zobrist.tichucounter.R
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import me.zobrist.tichucounter.databinding.FragmentKeyboardBinding
|
import me.zobrist.tichucounter.databinding.FragmentKeyboardBinding
|
||||||
import me.zobrist.tichucounter.domain.Tichu
|
|
||||||
import me.zobrist.tichucounter.ui.FragmentBase
|
import me.zobrist.tichucounter.ui.FragmentBase
|
||||||
import me.zobrist.tichucounter.ui.history.IHistoryFragmentViewModel
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
||||||
@@ -38,28 +40,12 @@ class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
|||||||
|
|
||||||
private val viewModel: KeyboardViewModel by activityViewModels()
|
private val viewModel: KeyboardViewModel by activityViewModels()
|
||||||
|
|
||||||
private val requester = FocusRequester()
|
|
||||||
private var isAFocused: Boolean = false
|
|
||||||
private var isBFocused: Boolean = false
|
|
||||||
|
|
||||||
var enableSubmit = mutableStateOf(false)
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
|
|
||||||
snapshotFlow { viewModel.scoreA.value }
|
|
||||||
.onEach {
|
|
||||||
enableSubmitOnValidRound(viewModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
snapshotFlow { viewModel.scoreB.value }
|
|
||||||
.onEach {
|
|
||||||
enableSubmitOnValidRound(viewModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ComposeView(requireContext()).apply {
|
return ComposeView(requireContext()).apply {
|
||||||
// Dispose of the Composition when the view's LifecycleOwner
|
// Dispose of the Composition when the view's LifecycleOwner
|
||||||
// is destroyed
|
// is destroyed
|
||||||
@@ -72,110 +58,6 @@ class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(!isAFocused && !isBFocused)
|
|
||||||
{
|
|
||||||
requester.requestFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun appendToFocusedScore(toAppend: String, viewModel: IKeyboardViewModel) {
|
|
||||||
val value = getActiveValue(viewModel)
|
|
||||||
value.value += toAppend
|
|
||||||
updateOtherScore(viewModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateOtherScore(viewModel: IKeyboardViewModel) {
|
|
||||||
val value = getActiveValue(viewModel)
|
|
||||||
|
|
||||||
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.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)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
@@ -195,9 +77,9 @@ class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
keyboardController?.hide()
|
keyboardController?.hide()
|
||||||
isAFocused = it.isFocused
|
viewModel.isAFocused.value = it.isFocused
|
||||||
}
|
}
|
||||||
.focusRequester(requester)
|
.focusRequester(viewModel.requestFocusA.value)
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
colors = TextFieldDefaults.textFieldColors(
|
colors = TextFieldDefaults.textFieldColors(
|
||||||
cursorColor = Color.Transparent,
|
cursorColor = Color.Transparent,
|
||||||
@@ -212,7 +94,7 @@ class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
keyboardController?.hide()
|
keyboardController?.hide()
|
||||||
isBFocused = it.isFocused
|
viewModel.isBFocused.value = it.isFocused
|
||||||
}
|
}
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
colors = TextFieldDefaults.textFieldColors(
|
colors = TextFieldDefaults.textFieldColors(
|
||||||
@@ -224,70 +106,79 @@ class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("1", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("1") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("1") }
|
) { Text("1") }
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("2", viewModel ) },
|
onClick = { viewModel.appendToFocusedScore("2") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("2") }
|
) { Text("2") }
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("3", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("3") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("3") }
|
) { Text("3") }
|
||||||
Button(onClick = { addToActiveInput(100, viewModel) }, modifier = Modifier.weight(1F)) { Text("+100") }
|
TextButton(
|
||||||
|
onClick = { viewModel.addToActiveInput(100) },
|
||||||
|
modifier = Modifier.weight(1F)
|
||||||
|
) { Text("+100") }
|
||||||
|
|
||||||
}
|
}
|
||||||
Row {
|
Row {
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("4", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("4") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("4") }
|
) { Text("4") }
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("5", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("5") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("5") }
|
) { Text("5") }
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("6", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("6") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("6") }
|
) { Text("6") }
|
||||||
Button(onClick = { addToActiveInput(-100, viewModel) }, modifier = Modifier.weight(1F)) { Text("-100") }
|
TextButton(
|
||||||
|
onClick = { viewModel.addToActiveInput(-100) },
|
||||||
|
modifier = Modifier.weight(1F)
|
||||||
|
) { Text("-100") }
|
||||||
}
|
}
|
||||||
Row {
|
Row {
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("7", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("7") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("7") }
|
) { Text("7") }
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("8", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("8") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("8") }
|
) { Text("8") }
|
||||||
Button(
|
TextButton(
|
||||||
onClick = { appendToFocusedScore("9", viewModel) },
|
onClick = { viewModel.appendToFocusedScore("9") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("9") }
|
) { Text("9") }
|
||||||
Button(onClick = { removeFromActiveInput(viewModel) }, modifier = Modifier.weight(1F)) { Text("DEL") }
|
IconButton(
|
||||||
|
onClick = { viewModel.removeLastCharFromActive() },
|
||||||
|
modifier = Modifier.weight(1F)
|
||||||
|
) { Icon(Icons.Outlined.Backspace, stringResource(R.string.submit)) }
|
||||||
}
|
}
|
||||||
Row {
|
Row {
|
||||||
Button(onClick = { negateActiveInput(viewModel) }, modifier = Modifier.weight(1F)) { Text("+/-") }
|
TextButton(
|
||||||
Button(
|
onClick = { viewModel.negateActiveInput() },
|
||||||
onClick = { appendToFocusedScore("0", viewModel) },
|
modifier = Modifier.weight(1F)
|
||||||
|
) { Text("+/-") }
|
||||||
|
TextButton(
|
||||||
|
onClick = { viewModel.appendToFocusedScore("0") },
|
||||||
modifier = Modifier.weight(1F)
|
modifier = Modifier.weight(1F)
|
||||||
) { Text("0") }
|
) { Text("0") }
|
||||||
Spacer(modifier = Modifier.weight(1F))
|
Spacer(modifier = Modifier.weight(1F))
|
||||||
Button(onClick = { submit(viewModel) }, modifier = Modifier.weight(1F), enabled = enableSubmit.value) { Text("ENTER") }
|
IconButton(
|
||||||
|
onClick = { viewModel.submitScore() },
|
||||||
|
modifier = Modifier.weight(1F),
|
||||||
|
enabled = viewModel.enableSubmit.value
|
||||||
|
) { Icon(Icons.Outlined.Check, stringResource(R.string.submit)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun submit(viewModel: IKeyboardViewModel) {
|
|
||||||
viewModel.submitScore(viewModel.scoreA.value.toInt(), viewModel.scoreB.value.toInt())
|
|
||||||
viewModel.scoreA.value = ""
|
|
||||||
viewModel.scoreB.value = ""
|
|
||||||
enableSubmit.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
object EmptyTextToolbar : TextToolbar {
|
object EmptyTextToolbar : TextToolbar {
|
||||||
override val status: TextToolbarStatus = TextToolbarStatus.Hidden
|
override val status: TextToolbarStatus = TextToolbarStatus.Hidden
|
||||||
|
|
||||||
@@ -306,8 +197,29 @@ class Keyboard : FragmentBase<FragmentKeyboardBinding>() {
|
|||||||
internal class DefaultViewModel : IKeyboardViewModel {
|
internal class DefaultViewModel : IKeyboardViewModel {
|
||||||
override var scoreA: MutableState<String> = mutableStateOf("")
|
override var scoreA: MutableState<String> = mutableStateOf("")
|
||||||
override var scoreB: MutableState<String> = mutableStateOf("")
|
override var scoreB: MutableState<String> = mutableStateOf("")
|
||||||
|
override var enableSubmit = mutableStateOf(false)
|
||||||
|
override var isAFocused = mutableStateOf(false)
|
||||||
|
override var isBFocused = mutableStateOf(false)
|
||||||
|
override var requestFocusA = mutableStateOf(FocusRequester())
|
||||||
|
|
||||||
override fun submitScore(scoreA: Int, scoreB: Int) {
|
override fun appendToFocusedScore(toAppend: String) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun negateActiveInput() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToActiveInput(toAdd: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeLastCharFromActive() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun submitScore() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
package me.zobrist.tichucounter.ui.counter
|
package me.zobrist.tichucounter.ui.counter
|
||||||
|
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.zobrist.tichucounter.domain.Tichu
|
import me.zobrist.tichucounter.domain.Tichu
|
||||||
import me.zobrist.tichucounter.repository.GameRepository
|
import me.zobrist.tichucounter.repository.GameRepository
|
||||||
@@ -19,19 +14,124 @@ import javax.inject.Inject
|
|||||||
interface IKeyboardViewModel {
|
interface IKeyboardViewModel {
|
||||||
var scoreA: MutableState<String>
|
var scoreA: MutableState<String>
|
||||||
var scoreB: MutableState<String>
|
var scoreB: MutableState<String>
|
||||||
fun submitScore(scoreA: Int, scoreB: Int)
|
var enableSubmit: MutableState<Boolean>
|
||||||
|
var isAFocused: MutableState<Boolean>
|
||||||
|
var isBFocused: MutableState<Boolean>
|
||||||
|
var requestFocusA: MutableState<FocusRequester>
|
||||||
|
|
||||||
|
fun appendToFocusedScore(toAppend: String)
|
||||||
|
|
||||||
|
fun negateActiveInput()
|
||||||
|
|
||||||
|
fun addToActiveInput(toAdd: Int)
|
||||||
|
|
||||||
|
fun removeLastCharFromActive()
|
||||||
|
|
||||||
|
fun submitScore()
|
||||||
}
|
}
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class KeyboardViewModel @Inject constructor(private val gameRepository: GameRepository) :
|
class KeyboardViewModel @Inject constructor(private val gameRepository: GameRepository) :
|
||||||
ViewModel(), IKeyboardViewModel {
|
ViewModel(), IKeyboardViewModel {
|
||||||
override var scoreA = mutableStateOf( "")
|
override var scoreA = mutableStateOf("")
|
||||||
override var scoreB = mutableStateOf("")
|
override var scoreB = mutableStateOf("")
|
||||||
|
override var enableSubmit = mutableStateOf(false)
|
||||||
|
override var isAFocused = mutableStateOf(false)
|
||||||
|
override var isBFocused = mutableStateOf(false)
|
||||||
|
override var requestFocusA = mutableStateOf(FocusRequester())
|
||||||
|
|
||||||
|
override fun submitScore() {
|
||||||
override fun submitScore(scoreA: Int, scoreB: Int) {
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
gameRepository.addRoundToActiveGame(scoreA, scoreB)
|
gameRepository.addRoundToActiveGame(scoreA.value.toInt(), scoreB.value.toInt())
|
||||||
|
}
|
||||||
|
scoreA.value = ""
|
||||||
|
scoreB.value = ""
|
||||||
|
enableSubmit.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendToFocusedScore(toAppend: String) {
|
||||||
|
val value = getActiveValue()
|
||||||
|
value.value += toAppend
|
||||||
|
updateOtherScore()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun negateActiveInput() {
|
||||||
|
val value = getActiveValue()
|
||||||
|
|
||||||
|
if (value.value.contains("-")) {
|
||||||
|
value.value = value.value.replace("-", "")
|
||||||
|
} else {
|
||||||
|
value.value = "-" + value.value
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOtherScore()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addToActiveInput(toAdd: Int) {
|
||||||
|
val value = getActiveValue()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val temp = value.value.toInt() + toAdd
|
||||||
|
value.value = temp.toString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
value.value = toAdd.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun removeLastCharFromActive() {
|
||||||
|
val value = getActiveValue()
|
||||||
|
if (value.value != "") {
|
||||||
|
value.value = value.value.dropLast(1)
|
||||||
|
}
|
||||||
|
updateOtherScore()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun giveFocusToAIfNone() {
|
||||||
|
if (!isAFocused.value && !isBFocused.value) {
|
||||||
|
requestFocusA.value.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateOtherScore() {
|
||||||
|
val value = getActiveValue()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val tichu = Tichu()
|
||||||
|
val myScore = value.value.toInt()
|
||||||
|
val hisScore = tichu.calculateOtherScore(myScore)
|
||||||
|
if (tichu.isValidRound(myScore, hisScore)) {
|
||||||
|
updateInactiveValue(hisScore?.toString() ?: "")
|
||||||
|
} else {
|
||||||
|
updateInactiveValue("")
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
updateInactiveValue("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getActiveValue(): MutableState<String> {
|
||||||
|
giveFocusToAIfNone()
|
||||||
|
if (isBFocused.value) {
|
||||||
|
return scoreB
|
||||||
|
}
|
||||||
|
return scoreA
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateInactiveValue(value: String) {
|
||||||
|
giveFocusToAIfNone()
|
||||||
|
if (isBFocused.value) {
|
||||||
|
scoreA.value = value
|
||||||
|
} else {
|
||||||
|
scoreB.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val tichu = Tichu()
|
||||||
|
enableSubmit.value = tichu.isValidRound(scoreA.value.toInt(), scoreB.value.toInt())
|
||||||
|
} catch (_: java.lang.NumberFormatException) {
|
||||||
|
enableSubmit.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package me.zobrist.tichucounter
|
package me.zobrist.tichucounter
|
||||||
|
|
||||||
import me.zobrist.tichucounter.data.Round
|
|
||||||
import me.zobrist.tichucounter.domain.Tichu
|
import me.zobrist.tichucounter.domain.Tichu
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.*
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -37,13 +36,13 @@ class TichuUnitTest {
|
|||||||
assertGeneratedRound(tichu, 400, 0)
|
assertGeneratedRound(tichu, 400, 0)
|
||||||
|
|
||||||
//Good rounds trough Tichu
|
//Good rounds trough Tichu
|
||||||
assertValidRound(tichu, 0, 0)
|
assertValidRound(tichu, 0, 0)
|
||||||
assertValidRound(tichu, -100, 0)
|
assertValidRound(tichu, -100, 0)
|
||||||
|
|
||||||
//Bad rounds
|
//Bad rounds
|
||||||
assertInvalidRound(tichu, 5, 12)
|
assertInvalidRound(tichu, 5, 12)
|
||||||
assertInvalidRound(tichu, 12, 5)
|
assertInvalidRound(tichu, 12, 5)
|
||||||
assertInvalidRound(tichu, 5, 55)
|
assertInvalidRound(tichu, 5, 55)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertGeneratedRound(tichu: Tichu, scoreA: Int, expectedScoreB: Int) {
|
private fun assertGeneratedRound(tichu: Tichu, scoreA: Int, expectedScoreB: Int) {
|
||||||
|
|||||||
Reference in New Issue
Block a user