diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt index 96a13452..03039646 100644 --- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt +++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt @@ -13,23 +13,25 @@ class Styler @Inject constructor(private val prefs: SharedPreferences, private v enum class Style(@StyleRes val style: Int) { PDC_2018(R.style.Pdc_2018), + BDO_2018(R.style.Bdo_2018), BDO(R.style.Bdo), PDC(R.style.Pdc); } fun get(): Int { - return prefs.getInt("curStyle", Style.PDC.style) + return prefs.getInt("curStyle", Style.PDC_2018.style) } fun switch() { - val curStyle = prefs.getInt("curStyle", Style.PDC.style) + val curStyle = prefs.getInt("curStyle", Style.PDC_2018.style) prefs.edit().putInt("curStyle", swap(curStyle)).apply() activity.recreate() } private fun swap(style: Int): Int { return when (style) { - R.style.Pdc_2018 -> Style.BDO.style + R.style.Pdc_2018 -> Style.BDO_2018.style + R.style.Bdo_2018 -> Style.BDO.style R.style.Bdo -> Style.PDC.style else -> Style.PDC_2018.style } diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt index 7cf508ef..160ec084 100644 --- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt +++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt @@ -66,7 +66,10 @@ class Play01Activity : ViewModelActivity() { override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item?.itemId) { - R.id.menu_play_settings -> swapStyle() + R.id.menu_play_settings -> { + swapStyle() + viewModel.loading.set(true) + } } return super.onOptionsItemSelected(item) } diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputBindings.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputBindings.kt index 341c06d4..706e89dc 100644 --- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputBindings.kt +++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputBindings.kt @@ -3,6 +3,7 @@ package nl.entreco.dartsscorecard.play.input import android.databinding.BindingAdapter import android.support.design.widget.FloatingActionButton import android.view.View +import android.view.animation.AccelerateDecelerateInterpolator import android.widget.TextView import nl.entreco.dartsscorecard.R import nl.entreco.domain.play.listeners.events.BustEvent @@ -55,6 +56,15 @@ abstract class InputBindings { } + @JvmStatic + @BindingAdapter("ask4finish") + fun showAsk4Finish(view: View, shouldAsk: Boolean) { + view.visibility = if (shouldAsk) View.VISIBLE else View.GONE + view.pivotY = if (shouldAsk) 0F else view.height.toFloat() + view.animate().setInterpolator(AccelerateDecelerateInterpolator()).setDuration(DEFAULT_ANIMATION_TIME).scaleY(if (shouldAsk) 1F else 0F).start() + } + + @JvmStatic @BindingAdapter("special") fun showSpecialEvents(view: TextView, event: SpecialEvent?) { diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt index cd9fbfca..5a636262 100644 --- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt +++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt @@ -32,6 +32,7 @@ class InputViewModel @Inject constructor(private val analytics: Analytics, priva val hintProvider = ObservableField(HintKeyProvider(toggle.get())) val special = ObservableField() val required = ObservableField() + val finalTurn = ObservableField() val dartsLeft = ObservableInt() val resumeDescription = ObservableInt(R.string.game_on) @@ -64,7 +65,7 @@ class InputViewModel @Inject constructor(private val analytics: Analytics, priva scoredTxt.set(scoredTxt.get().dropLast(1)) } - fun clear() : Boolean { + fun clear(): Boolean { scoredTxt.set("") return true } @@ -91,7 +92,7 @@ class InputViewModel @Inject constructor(private val analytics: Analytics, priva submit(scored, listener) } - fun onUndoPressed(listener: InputListener){ + fun onUndoPressed(listener: InputListener) { listener.onUndo() clearScoreInput() } @@ -136,10 +137,27 @@ class InputViewModel @Inject constructor(private val analytics: Analytics, priva } private fun submitScore(turn: Turn, listener: InputListener) { - listener.onTurnSubmitted(turn.copy(), nextUp?.player!!) + askForDartsAtFinish(turn, required.get(), listener) + } + + private fun askForDartsAtFinish(turn: Turn, score: Score?, listener: InputListener) { + if (turn.total() == score?.score && turn.hasZeros()) { + finalTurn.set(turn) + } else { + done(turn, listener) + } + } + + fun onFinishWith(dartsUsed: Int, listener: InputListener) { + val turn = finalTurn.get()?.setDartsUsedForFinish(dartsUsed)!! + done(turn, listener) + } + private fun done(turn: Turn, listener: InputListener) { + listener.onTurnSubmitted(turn.copy(), nextUp?.player!!) this.scoredTxt.set(turn.total().toString()) this.analytics.trackAchievement("scored: $turn") + clearScoreInput() } private fun clearScoreInput() { @@ -156,6 +174,7 @@ class InputViewModel @Inject constructor(private val analytics: Analytics, priva nextDescription.set(descriptionFromNext(next)) resumeDescription.set(resumeDescriptionFromNext(next)) current.set(next.player) + finalTurn.set(null) turn = Turn() dartsLeft.set(turn.dartsLeft()) } diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModel.kt index bcae0ed3..0e330232 100644 --- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModel.kt +++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModel.kt @@ -48,7 +48,7 @@ class TeamScoreViewModel(val team: Team, startScore: Score, fun threw(turn: Turn, player: Player) { if (team.contains(player)) { - scored.set(turn.total()) + scored.set(this.score.get().score - turn.total()) calculateFinish(this.score.get(), player, turn) } } diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModel.kt index fbf50b0c..2610a0de 100644 --- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModel.kt +++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModel.kt @@ -1,6 +1,10 @@ package nl.entreco.dartsscorecard.play.stats +import android.databinding.ObservableArrayList import android.databinding.ObservableArrayMap +import android.databinding.ObservableField +import android.databinding.ObservableInt +import android.widget.AdapterView import nl.entreco.dartsscorecard.base.BaseViewModel import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier import nl.entreco.dartsscorecard.play.score.UiCallback @@ -15,15 +19,32 @@ import javax.inject.Inject /** * Created by entreco on 11/01/2018. */ -class MatchStatViewModel @Inject constructor( - private val fetchGameStatsUsecase: FetchGameStatsUsecase, - private val fetchGameStatUsecase: FetchGameStatUsecase, - private val logger: Logger -) : BaseViewModel(), GameLoadedNotifier, StatListener { +class MatchStatViewModel @Inject constructor(private val fetchGameStatsUsecase: FetchGameStatsUsecase, private val fetchGameStatUsecase: FetchGameStatUsecase, private val logger: Logger) : BaseViewModel(), GameLoadedNotifier, StatListener { + val team0 = ObservableField() + val team1 = ObservableField() + val teamEntries = ObservableArrayList() val teamStats = ObservableArrayMap() + + val team0Index = ObservableInt() + val team1Index = ObservableInt() + private lateinit var teams: Array + fun onTeamStat0Selected(adapter: AdapterView<*>, index: Int){ + val resolved = adapter.getItemAtPosition(index).toString() + val selected = teams.indexOfFirst { it.toString().toLowerCase() == resolved.toLowerCase() } + team0.set(teamStats[selected]) + team0Index.set(selected) + } + + fun onTeamStat1Selected(adapter: AdapterView<*>, index: Int){ + val resolved = adapter.getItemAtPosition(index).toString() + val selected = teams.indexOfFirst { it.toString().toLowerCase() == resolved.toLowerCase() } + team1.set(teamStats[selected]) + team1Index.set(selected) + } + override fun onLoaded(teams: Array, scores: Array, info: Play01Response, uiCallback: UiCallback?) { initializeStats(teams) fetchGameStatsUsecase.exec(FetchGameStatsRequest(info.game.id, info.teamIds), @@ -33,10 +54,16 @@ class MatchStatViewModel @Inject constructor( private fun initializeStats(teams: Array) { this.teamStats.clear() + this.teamEntries.clear() this.teams = teams + teams.forEachIndexed { index, team -> teamStats[index] = TeamStatModel(team) } + + teamEntries.addAll(teams.map { it.toString().capitalize() }) + team0Index.set(0) + team1Index.set(if(teams.size > 1) 1 else 0) } private fun onStatsFetched(teams: Array): (FetchGameStatsResponse) -> Unit { diff --git a/android/DartsScorecard/app/src/main/res/drawable/score.xml b/android/DartsScorecard/app/src/main/res/drawable/score.xml index 82ab0da3..b10ae9ca 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/score_entry.xml b/android/DartsScorecard/app/src/main/res/drawable/score_entry.xml index 243d370d..a779acdb 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score_entry.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score_entry.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/score_footer.xml b/android/DartsScorecard/app/src/main/res/drawable/score_footer.xml index 761e3a3b..aa0b8fcf 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score_footer.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score_footer.xml @@ -3,9 +3,9 @@ + android:angle="?attr/gradient_angle" + android:endColor="?attr/grad_score_footer_stop" + android:startColor="?attr/grad_score_footer_start" /> diff --git a/android/DartsScorecard/app/src/main/res/drawable/score_header.xml b/android/DartsScorecard/app/src/main/res/drawable/score_header.xml index 971356bf..b3c81d48 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score_header.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score_header.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/score_header_middle.xml b/android/DartsScorecard/app/src/main/res/drawable/score_header_middle.xml index d38673fa..26a842c9 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score_header_middle.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score_header_middle.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/score_name.xml b/android/DartsScorecard/app/src/main/res/drawable/score_name.xml index f8d8385a..90789585 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score_name.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score_name.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/score_pts.xml b/android/DartsScorecard/app/src/main/res/drawable/score_pts.xml index f3b3ba84..c0592b13 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score_pts.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score_pts.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/score_spinner.xml b/android/DartsScorecard/app/src/main/res/drawable/score_spinner.xml index 19277c50..357cce5d 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/score_spinner.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/score_spinner.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/spinner_player.xml b/android/DartsScorecard/app/src/main/res/drawable/spinner_player.xml new file mode 100644 index 00000000..de3ec82a --- /dev/null +++ b/android/DartsScorecard/app/src/main/res/drawable/spinner_player.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/android/DartsScorecard/app/src/main/res/drawable/stat_player.xml b/android/DartsScorecard/app/src/main/res/drawable/stat_player.xml index 9e6b6707..0fb3c2f4 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/stat_player.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/stat_player.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/drawable/stats_header.xml b/android/DartsScorecard/app/src/main/res/drawable/stats_header.xml index 31a871ca..2b7b480f 100644 --- a/android/DartsScorecard/app/src/main/res/drawable/stats_header.xml +++ b/android/DartsScorecard/app/src/main/res/drawable/stats_header.xml @@ -3,7 +3,7 @@ diff --git a/android/DartsScorecard/app/src/main/res/layout/include_resume.xml b/android/DartsScorecard/app/src/main/res/layout/include_resume.xml index 1c418c75..89fd6d1c 100644 --- a/android/DartsScorecard/app/src/main/res/layout/include_resume.xml +++ b/android/DartsScorecard/app/src/main/res/layout/include_resume.xml @@ -14,7 +14,6 @@ android:layout_height="match_parent" android:orientation="horizontal"> - diff --git a/android/DartsScorecard/app/src/main/res/layout/play_01_input.xml b/android/DartsScorecard/app/src/main/res/layout/play_01_input.xml index 3db18c41..4769faf7 100644 --- a/android/DartsScorecard/app/src/main/res/layout/play_01_input.xml +++ b/android/DartsScorecard/app/src/main/res/layout/play_01_input.xml @@ -1,11 +1,18 @@ + xmlns:fab="http://schemas.android.com/tools"> + + + + @@ -105,7 +112,7 @@ + app:message="@{viewModel.resumeDescription}" /> @@ -200,8 +207,8 @@ @@ -222,8 +229,7 @@ style="@style/Input.Mini" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@{viewModel.toggle ? @string/single_mode : @string/all_mode}" - tools:text="hoi" /> + android:text="@{viewModel.toggle ? @string/single_mode : @string/all_mode}" /> + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/DartsScorecard/app/src/main/res/layout/play_01_loading.xml b/android/DartsScorecard/app/src/main/res/layout/play_01_loading.xml index e3164d46..966f9353 100644 --- a/android/DartsScorecard/app/src/main/res/layout/play_01_loading.xml +++ b/android/DartsScorecard/app/src/main/res/layout/play_01_loading.xml @@ -4,6 +4,9 @@ - + android:layout_weight="1"> + + + + + + tools:text="VS" /> - + android:layout_weight="1"> + + + + + @@ -103,7 +129,7 @@ style="@style/Main.Value" android:layout_width="68dp" android:layout_height="wrap_content" - android:text="@{viewModel.teamStats[0].breaks.toString()}" /> + android:text="@{viewModel.team0.breaks.toString()}" /> + android:text="@{viewModel.team1.breaks.toString()}" /> + android:text="@{viewModel.team0.co.toString()}" /> + android:text="@{viewModel.team1.co.toString()}" /> + android:text="@{viewModel.team0.hCo.toString()}" /> + android:text="@{viewModel.team1.hCo.toString()}" /> + android:text="@{viewModel.team0.n180.toString()}" /> + android:text="@{viewModel.team1.n180.toString()}" /> + android:text="@{viewModel.team0.n140.toString()}" /> + android:text="@{viewModel.team1.n140.toString()}" /> + android:text="@{viewModel.team0.n100.toString()}" /> + android:text="@{viewModel.team1.n100.toString()}" /> + android:text="@{viewModel.team0.avg.toString()}" /> + android:text="@{viewModel.team1.avg.toString()}" /> + @@ -18,6 +19,8 @@ + + diff --git a/android/DartsScorecard/app/src/main/res/values/strings.xml b/android/DartsScorecard/app/src/main/res/values/strings.xml index 6349a055..f9428498 100644 --- a/android/DartsScorecard/app/src/main/res/values/strings.xml +++ b/android/DartsScorecard/app/src/main/res/values/strings.xml @@ -43,6 +43,9 @@ Game on Game shot, and the match + + How many darts did you use? + Match Statistics Breaks Made diff --git a/android/DartsScorecard/app/src/main/res/values/strings_no_translate.xml b/android/DartsScorecard/app/src/main/res/values/strings_no_translate.xml index 01e5d4f8..f7665e67 100644 --- a/android/DartsScorecard/app/src/main/res/values/strings_no_translate.xml +++ b/android/DartsScorecard/app/src/main/res/values/strings_no_translate.xml @@ -9,6 +9,9 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789.@ 180 9 + 1 + 2 + 3 101 201 diff --git a/android/DartsScorecard/app/src/main/res/values/styles_bdo.xml b/android/DartsScorecard/app/src/main/res/values/styles_bdo.xml index 926f034e..079b8af4 100644 --- a/android/DartsScorecard/app/src/main/res/values/styles_bdo.xml +++ b/android/DartsScorecard/app/src/main/res/values/styles_bdo.xml @@ -9,6 +9,7 @@ #760A10 + + \ No newline at end of file diff --git a/android/DartsScorecard/app/src/main/res/values/styles_input.xml b/android/DartsScorecard/app/src/main/res/values/styles_input.xml index d394f373..f512fb10 100644 --- a/android/DartsScorecard/app/src/main/res/values/styles_input.xml +++ b/android/DartsScorecard/app/src/main/res/values/styles_input.xml @@ -56,6 +56,19 @@ 1 + + diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt index 63c1dc17..5271904b 100644 --- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt +++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt @@ -60,7 +60,7 @@ class StylerTest { fun `it should swap to BDO style`() { givenStyle(Styler.Style.PDC_2018.style) val actualStyle = whenSwapping() - assertEquals(R.style.Bdo, actualStyle) + assertEquals(R.style.Bdo_2018, actualStyle) } @Test @@ -71,7 +71,7 @@ class StylerTest { } private fun givenStyle(@StyleRes style: Int) { - whenever(mockPrefs.getInt("curStyle", Styler.Style.PDC.style)).thenReturn(style) + whenever(mockPrefs.getInt("curStyle", Styler.Style.PDC_2018.style)).thenReturn(style) } private fun whenSwapping(): Int { diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputBindingsTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputBindingsTest.kt index db26239d..e2cc18ab 100644 --- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputBindingsTest.kt +++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputBindingsTest.kt @@ -97,4 +97,17 @@ class InputBindingsTest { verify(mockTextView).text = "yeah" } + @Test + fun showAsk4Finish_true() { + whenever(mockAnimator.setInterpolator(any())).thenReturn(mockAnimator) + InputBindings.showAsk4Finish(mockTextView, true) + verify(mockAnimator).scaleY(1F) + } + + @Test + fun showAsk4Finish_false() { + whenever(mockAnimator.setInterpolator(any())).thenReturn(mockAnimator) + InputBindings.showAsk4Finish(mockTextView, false) + verify(mockAnimator).scaleY(0F) + } } \ No newline at end of file diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModelTest.kt index ac5e5bb2..9c0b5f6f 100644 --- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModelTest.kt +++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/TeamScoreViewModelTest.kt @@ -93,7 +93,7 @@ class TeamScoreViewModelTest { fun `it should update 'scored' when player in this team threw`() { givenTeamScoreViewModel(true) whenThrowing(Turn(), playerFromMyTeam) - assertEquals(givenTurn.total(), subject.scored.get()) + assertEquals(givenTurn.total(), subject.score.get().score - subject.scored.get()) } @Test diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModelTest.kt index 28209565..eb50b1b6 100644 --- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModelTest.kt +++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/MatchStatViewModelTest.kt @@ -1,5 +1,6 @@ package nl.entreco.dartsscorecard.play.stats +import android.widget.AdapterView import com.nhaarman.mockito_kotlin.* import nl.entreco.domain.Logger import nl.entreco.domain.model.Game @@ -9,8 +10,7 @@ import nl.entreco.domain.model.players.Player import nl.entreco.domain.model.players.Team import nl.entreco.domain.play.start.Play01Response import nl.entreco.domain.play.stats.* -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull +import org.junit.Assert.* import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock @@ -26,6 +26,7 @@ class MatchStatViewModelTest { @Mock private lateinit var mockFetchGameStatUsecase: FetchGameStatUsecase @Mock private lateinit var mockLogger: Logger @Mock private lateinit var mockGame: Game + @Mock private lateinit var mockAdapterView: AdapterView<*> @Mock private lateinit var mockResponse: Play01Response private lateinit var subject: MatchStatViewModel private var givenGameId: Long = 1003 @@ -33,7 +34,7 @@ class MatchStatViewModelTest { private var givenTeams: Array = emptyArray() private var givenScores: Array = emptyArray() private var givenExistingStats: Map = emptyMap() - private var givenUpdatedStat: Stat = Stat(1,2,3,4,5,6,7,8,9, emptyList(), emptyList()) + private var givenUpdatedStat: Stat = Stat(1, 2, 3, 4, 5, 6, 7, 8, 9, emptyList(), emptyList()) private val statsDoneCaptor = argumentCaptor<(FetchGameStatsResponse) -> Unit>() private val statDoneCaptor = argumentCaptor<(FetchGameStatResponse) -> Unit>() @@ -102,7 +103,7 @@ class MatchStatViewModelTest { fun `it should update stats, when stat fetch succeeds`() { givenTeams("1", "2") givenSubjectLoaded() - givenUpdatedStat(1,180) + givenUpdatedStat(1, 180) whenStatsChangeSucceeds() thenTeamStat180IsEmpty(0) } @@ -114,6 +115,36 @@ class MatchStatViewModelTest { thenErrorIsLogged() } + @Test + fun `it should update team0 when selected`() { + givenTeams("piet", "henk") + givenSubjectLoaded() + whenTeamStat0Selected(1) + thenTeam0IndexIs(1) + } + + @Test(expected = NullPointerException::class) + fun `it should NOT update team0 when invalid index selected`() { + givenTeams("piet", "henk") + givenSubjectLoaded() + whenTeamStat0Selected(-1) + } + + @Test + fun `it should update team1 when selected`() { + givenTeams("piet", "henk") + givenSubjectLoaded() + whenTeamStat1Selected(1) + thenTeam1IndexIs(1) + } + + @Test(expected = NullPointerException::class) + fun `it should NOT update team1 when invalid index selected`() { + givenTeams("piet", "henk") + givenSubjectLoaded() + whenTeamStat0Selected(1000) + } + private fun givenSubjectLoaded() { whenever(mockGame.id).thenReturn(givenGameId) whenever(mockResponse.game).thenReturn(mockGame) @@ -139,7 +170,7 @@ class MatchStatViewModelTest { givenExistingStats = existing } - private fun givenUpdatedStat(playerId: Long, value: Int){ + private fun givenUpdatedStat(playerId: Long, value: Int) { givenUpdatedStat = givenUpdatedStat.copy(playerId = playerId, n180 = value) } @@ -156,12 +187,12 @@ class MatchStatViewModelTest { } private fun whenStatsChange() { - subject.onStatsChange(1,2) + subject.onStatsChange(1, 2) } private fun whenStatsChangeSucceeds() { - val turnId : Long = 1 - val metaId : Long = 20000 + val turnId: Long = 1 + val metaId: Long = 20000 val req = FetchGameStatRequest(turnId, metaId) val response = FetchGameStatResponse(givenUpdatedStat) subject.onStatsChange(turnId, metaId) @@ -170,12 +201,26 @@ class MatchStatViewModelTest { } private fun whenStatsChangeFails(err: Throwable) { - subject.onStatsChange(8,9) + subject.onStatsChange(8, 9) verify(mockFetchGameStatUsecase).exec(any(), any(), failCaptor.capture()) failCaptor.lastValue.invoke(err) } - private fun thenStatIsFetched(){ + private fun whenTeamStat0Selected(index: Int) { + if (index in 0 until givenTeams.size) { + whenever(mockAdapterView.getItemAtPosition(index)).thenReturn(givenTeams[index].toString()) + } else { + whenever(mockAdapterView.getItemAtPosition(index)).thenReturn(null) + } + subject.onTeamStat0Selected(mockAdapterView, index) + } + + private fun whenTeamStat1Selected(index: Int) { + whenever(mockAdapterView.getItemAtPosition(index)).thenReturn(givenTeams[index].toString()) + subject.onTeamStat1Selected(mockAdapterView, index) + } + + private fun thenStatIsFetched() { verify(mockFetchGameStatUsecase).exec(any(), any(), any()) } @@ -213,4 +258,14 @@ class MatchStatViewModelTest { private fun thenTeamStat180IsEmpty(index: Int) { assertEquals("--", subject.teamStats[index]?.n180?.get()) } + + private fun thenTeam0IndexIs(index: Int) { + assertEquals(index, subject.team0Index.get()) + assertTrue(index in 0 until givenTeams.size) + } + + private fun thenTeam1IndexIs(index: Int) { + assertEquals(index, subject.team1Index.get()) + assertTrue(index in 0 until givenTeams.size) + } } \ No newline at end of file diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/TeamStatModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/TeamStatModelTest.kt index 1af72324..d03fedf2 100644 --- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/TeamStatModelTest.kt +++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/stats/TeamStatModelTest.kt @@ -19,6 +19,11 @@ class TeamStatModelTest { private lateinit var mockTeam: Team private lateinit var subject: TeamStatModel + @Test + fun `empty should be double dashes`() { + assertEquals("--", TeamStatModel.empty) + } + @Test fun `it should update stats at the start`() { subject = TeamStatModel(mockTeam, mutableListOf(Stat(1,2,3,4,5, 6, 15, 5, 9, listOf(10), listOf(11)))) diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/edit/EditPlayerViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/edit/EditPlayerViewModelTest.kt index 4039d209..a2e5d256 100644 --- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/edit/EditPlayerViewModelTest.kt +++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/edit/EditPlayerViewModelTest.kt @@ -1,9 +1,11 @@ package nl.entreco.dartsscorecard.setup.edit +import android.content.Context import android.view.inputmethod.EditorInfo import android.widget.TextView import com.nhaarman.mockito_kotlin.* import nl.entreco.domain.model.players.Player +import nl.entreco.domain.setup.players.CreatePlayerResponse import nl.entreco.domain.setup.players.CreatePlayerUsecase import nl.entreco.domain.setup.players.FetchExistingPlayersResponse import nl.entreco.domain.setup.players.FetchExistingPlayersUsecase @@ -23,8 +25,11 @@ class EditPlayerViewModelTest { @Mock private lateinit var mockCreateUsecase: CreatePlayerUsecase @Mock private lateinit var mockFetchUsecase: FetchExistingPlayersUsecase @Mock private lateinit var mockView: TextView + @Mock private lateinit var mockContext: Context @Mock private lateinit var mockNavigator: EditPlayerNavigator + @Mock private lateinit var mockPlayer: Player private val doneCaptor = argumentCaptor<(FetchExistingPlayersResponse) -> Unit>() + private val createDoneCaptor = argumentCaptor<(CreatePlayerResponse) -> Unit>() private val failCaptor = argumentCaptor<(Throwable) -> Unit>() private lateinit var subject: EditPlayerViewModel private lateinit var expectedPlayers: MutableList @@ -90,6 +95,15 @@ class EditPlayerViewModelTest { thenFilteredPlayersContains("Abcdef", "Abcd", "Abc") } + @Test + fun `it should add Players whos name contains substring`() { + givenExistingPlayers("Piet", "Heintje", "Coco") + givenSubject("Player 1") + whenFetchingSucceeds() + whenTypingLetters("t") + thenFilteredPlayersContains("Piet", "Heintje") + } + @Test fun `it should create player when 'Done'`() { givenExistingPlayers("Remco", "EmReCo", "Re") @@ -98,8 +112,28 @@ class EditPlayerViewModelTest { thenPlayerIsCreated() } + @Test - fun `it should NOT create player if it already exists when 'Done'`() { + fun `it should navigate when player created succeeds`() { + givenExistingPlayers("Remco", "EmReCo", "Re") + givenSubject("Player 1") + whenPressingImeAction("Henk", EditorInfo.IME_ACTION_DONE) + whenPlayerIsCreated() + thenNavigateWithSelectedPlayer() + } + + @Test(expected = NullPointerException::class) // Meaning Toast.makeText( is called) + fun `it should NOT navigate when player creation fails`() { + whenever(mockView.context).thenReturn(mockContext) + givenExistingPlayers("Remco", "EmReCo", "Re") + givenSubject("Player 1") + whenPressingImeAction("Willem", EditorInfo.IME_ACTION_DONE) + whenPlayerIsNotCreated(RuntimeException("Unable to create Player")) + thenNotNavigateWithSelectedPlayer() + } + + @Test + fun `it should NOT create player if it already exists when 'Done' pressed`() { givenExistingPlayers("plaYer 1") givenSubject("Player 1") whenFetchingSucceeds() @@ -108,7 +142,7 @@ class EditPlayerViewModelTest { } @Test - fun `it should NOT create player when 'Go'`() { + fun `it should NOT create player when 'Go' pressed`() { givenExistingPlayers("Remco", "EmReCo", "Re") givenSubject("Player 1") whenPressingImeAction("Willem", EditorInfo.IME_ACTION_GO) @@ -156,6 +190,16 @@ class EditPlayerViewModelTest { assertEquals(players.size, subject.filteredPlayers.size) } + private fun whenPlayerIsCreated() { + verify(mockCreateUsecase).exec(any(), createDoneCaptor.capture(), any()) + createDoneCaptor.lastValue.invoke(CreatePlayerResponse(mockPlayer)) + } + + private fun whenPlayerIsNotCreated(err: Throwable) { + verify(mockCreateUsecase).exec(any(), any(), failCaptor.capture()) + failCaptor.lastValue.invoke(err) + } + private fun thenPlayerIsCreated() { verify(mockCreateUsecase).exec(any(), any(), any()) } @@ -164,4 +208,12 @@ class EditPlayerViewModelTest { verifyZeroInteractions(mockCreateUsecase) } + private fun thenNavigateWithSelectedPlayer() { + verify(mockNavigator).onSelected(any()) + } + + private fun thenNotNavigateWithSelectedPlayer() { + verifyZeroInteractions(mockNavigator) + } + } \ No newline at end of file diff --git a/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/meta/MetaMapperTest.kt b/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/meta/MetaMapperTest.kt index 780a4c8e..6e1fcc57 100644 --- a/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/meta/MetaMapperTest.kt +++ b/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/meta/MetaMapperTest.kt @@ -34,6 +34,7 @@ class MetaMapperTest { @Test fun from() { val result = subject.from(givenGameId, givenTurnId, givenMeta, givenAtDouble) + assertEquals(0, result.id) assertEquals(givenTurnId, result.turnId) assertEquals(givenGameId, result.gameId) assertEquals(givenPlayerId, result.playerId) diff --git a/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/turn/TurnMapperTest.kt b/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/turn/TurnMapperTest.kt index a6e38bb8..58f21b6f 100644 --- a/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/turn/TurnMapperTest.kt +++ b/android/DartsScorecard/data/src/test/java/nl/entreco/data/db/turn/TurnMapperTest.kt @@ -42,7 +42,9 @@ class TurnMapperTest { } private fun whenConvertingFromAndTo(turn: Turn) { - expectedTurn = subject.to(subject.from(gameId, playerId, turn)) + val from = subject.from(gameId, playerId, turn) + assertEquals(0, from.id) + expectedTurn = subject.to(from) assertEquals("turn: $turn exp:$expectedTurn",turn, expectedTurn) } diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/model/Turn.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/model/Turn.kt index f9c5195b..30875c5f 100644 --- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/model/Turn.kt +++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/model/Turn.kt @@ -67,4 +67,26 @@ data class Turn (internal val d1: Dart = Dart.NONE, internal val d2: Dart = Dart fun lastIsDouble(): Boolean { return last().isDouble() } + + fun hasZeros(): Boolean{ + return numZeros() > 0 + } + + fun numZeros(): Int{ + var zeros = 0 + if(d1 == Dart.ZERO) zeros++ + if(d2 == Dart.ZERO) zeros++ + if(d3 == Dart.ZERO) zeros++ + return zeros + } + + fun setDartsUsedForFinish(used: Int) : Turn{ + if(dartsUsed() - numZeros() > used) throw IllegalStateException("Darts Mismatch! used darts($used), but thrown $d1, $d2, $d3") + return when(used) { + 1 -> Turn(d3) + 2 -> Turn(d1, d3) + 3 -> Turn(d1, d2, d3) + else -> throw IllegalStateException("Darts Mismatch! used darts($used), but thrown $d1, $d2, $d3") + } + } } \ No newline at end of file diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/ScoreEstimator.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/ScoreEstimator.kt index b6760641..a99d2c54 100644 --- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/ScoreEstimator.kt +++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/ScoreEstimator.kt @@ -139,104 +139,104 @@ class ScoreEstimator @Inject constructor() { 103 -> Turn(Dart.TRIPLE_20, Dart.SINGLE_3, Dart.DOUBLE_20) // "T20 3 D20") 102 -> Turn(Dart.TRIPLE_20, Dart.SINGLE_10, Dart.DOUBLE_16) // "T20 10 D16") 101 -> Turn(Dart.TRIPLE_20, Dart.SINGLE_1, Dart.DOUBLE_20) // "T20 1 D20") - 100 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_20) // "T20 D20") + 100 -> Turn(Dart.TRIPLE_20, Dart.ZERO, Dart.DOUBLE_20) // "T20 D20") 99 -> Turn(Dart.TRIPLE_19, Dart.SINGLE_10, Dart.DOUBLE_16) //"T19 10 D16" - 98 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_19) //"T20 D19" - 97 -> Turn(Dart.ZERO, Dart.TRIPLE_19, Dart.DOUBLE_20) //"T19 D20" - 96 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_18) //"T20 D18" - 95 -> Turn(Dart.ZERO, Dart.TRIPLE_19, Dart.DOUBLE_19) //"T19 D19" - 94 -> Turn(Dart.ZERO, Dart.TRIPLE_18, Dart.DOUBLE_20) //"T18 D20" - 93 -> Turn(Dart.ZERO, Dart.TRIPLE_19, Dart.DOUBLE_18) //"T19 D18" - 92 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_16) //"T20 D16" - 91 -> Turn(Dart.ZERO, Dart.TRIPLE_17, Dart.DOUBLE_20) //"T17 D20" - 90 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_15) //"T20 D15" - 89 -> Turn(Dart.ZERO, Dart.TRIPLE_19, Dart.DOUBLE_16) //"T19 D16" - 88 -> Turn(Dart.ZERO, Dart.TRIPLE_16, Dart.DOUBLE_20) //"T16 D20" - 87 -> Turn(Dart.ZERO, Dart.TRIPLE_17, Dart.DOUBLE_18) //"T17 D18" - 86 -> Turn(Dart.ZERO, Dart.TRIPLE_18, Dart.DOUBLE_16) //"T18 D16" - 85 -> Turn(Dart.ZERO, Dart.TRIPLE_15, Dart.DOUBLE_20) //"T15 D20" - 84 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_12) //"T20 D12" - 83 -> Turn(Dart.ZERO, Dart.TRIPLE_17, Dart.DOUBLE_16) //"T17 D16" - 82 -> Turn(Dart.ZERO, Dart.TRIPLE_14, Dart.DOUBLE_20) //"T14 D20" - 81 -> Turn(Dart.ZERO, Dart.TRIPLE_19, Dart.DOUBLE_12) //"T19 D12" - 80 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_10) //"T20 D10" - 79 -> Turn(Dart.ZERO, Dart.TRIPLE_13, Dart.DOUBLE_20) //"T13 D20" - 78 -> Turn(Dart.ZERO, Dart.TRIPLE_18, Dart.DOUBLE_12) //"T18 D12" - 77 -> Turn(Dart.ZERO, Dart.TRIPLE_19, Dart.DOUBLE_10) //"T19 D10" - 76 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_8) //"T20 D8" - 75 -> Turn(Dart.ZERO, Dart.TRIPLE_17, Dart.DOUBLE_12) //"T17 D12" - 74 -> Turn(Dart.ZERO, Dart.TRIPLE_18, Dart.DOUBLE_10) //"T18 D10" - 73 -> Turn(Dart.ZERO, Dart.TRIPLE_19, Dart.DOUBLE_8) //"T19 D8" - 72 -> Turn(Dart.ZERO, Dart.TRIPLE_12, Dart.DOUBLE_18) //"T12 D18" - 71 -> Turn(Dart.ZERO, Dart.TRIPLE_17, Dart.DOUBLE_10) //"T17 D10" - 70 -> Turn(Dart.ZERO, Dart.TRIPLE_10, Dart.DOUBLE_20) //"T10 D20" - 69 -> Turn(Dart.ZERO, Dart.TRIPLE_13, Dart.DOUBLE_15) //"T13 D15" - 68 -> Turn(Dart.ZERO, Dart.TRIPLE_20, Dart.DOUBLE_4) //"T20 D4" - 67 -> Turn(Dart.ZERO, Dart.TRIPLE_17, Dart.DOUBLE_8) //"T17 D8" - 66 -> Turn(Dart.ZERO, Dart.TRIPLE_10, Dart.DOUBLE_18) //"T10 D18" - 65 -> Turn(Dart.ZERO, Dart.SINGLE_BULL, Dart.DOUBLE_20) //"S.BULL D20" - 64 -> Turn(Dart.ZERO, Dart.TRIPLE_16, Dart.DOUBLE_8) //"T16 D8" - 63 -> Turn(Dart.ZERO, Dart.TRIPLE_13, Dart.DOUBLE_12) //"T13 D12" - 62 -> Turn(Dart.ZERO, Dart.TRIPLE_10, Dart.DOUBLE_16) //"T10 D16" - 61 -> Turn(Dart.ZERO, Dart.SINGLE_BULL, Dart.DOUBLE_18) //"25 D18" - 60 -> Turn(Dart.ZERO, Dart.SINGLE_20, Dart.DOUBLE_20) //"20 D20" - 59 -> Turn(Dart.ZERO, Dart.SINGLE_19, Dart.DOUBLE_20) //"19 D20" - 58 -> Turn(Dart.ZERO, Dart.SINGLE_18, Dart.DOUBLE_20) //"18 D20" - 57 -> Turn(Dart.ZERO, Dart.SINGLE_17, Dart.DOUBLE_20) //"17 D20" - 56 -> Turn(Dart.ZERO, Dart.TRIPLE_16, Dart.DOUBLE_4) //"T16 D4" - 55 -> Turn(Dart.ZERO, Dart.SINGLE_15, Dart.DOUBLE_20) //"15 D20" - 54 -> Turn(Dart.ZERO, Dart.SINGLE_14, Dart.DOUBLE_20) //"14 D20" - 53 -> Turn(Dart.ZERO, Dart.SINGLE_13, Dart.DOUBLE_20) //"13 D20" - 52 -> Turn(Dart.ZERO, Dart.TRIPLE_12, Dart.DOUBLE_8) //"T12 D8" - 51 -> Turn(Dart.ZERO, Dart.SINGLE_11, Dart.DOUBLE_20) //"11 D20" + 98 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_19) //"T20 D19" + 97 -> Turn(Dart.TRIPLE_19,Dart.ZERO, Dart.DOUBLE_20) //"T19 D20" + 96 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_18) //"T20 D18" + 95 -> Turn(Dart.TRIPLE_19,Dart.ZERO, Dart.DOUBLE_19) //"T19 D19" + 94 -> Turn(Dart.TRIPLE_18,Dart.ZERO, Dart.DOUBLE_20) //"T18 D20" + 93 -> Turn(Dart.TRIPLE_19,Dart.ZERO, Dart.DOUBLE_18) //"T19 D18" + 92 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_16) //"T20 D16" + 91 -> Turn(Dart.TRIPLE_17,Dart.ZERO, Dart.DOUBLE_20) //"T17 D20" + 90 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_15) //"T20 D15" + 89 -> Turn(Dart.TRIPLE_19,Dart.ZERO, Dart.DOUBLE_16) //"T19 D16" + 88 -> Turn(Dart.TRIPLE_16,Dart.ZERO, Dart.DOUBLE_20) //"T16 D20" + 87 -> Turn(Dart.TRIPLE_17,Dart.ZERO, Dart.DOUBLE_18) //"T17 D18" + 86 -> Turn(Dart.TRIPLE_18,Dart.ZERO, Dart.DOUBLE_16) //"T18 D16" + 85 -> Turn(Dart.TRIPLE_15,Dart.ZERO, Dart.DOUBLE_20) //"T15 D20" + 84 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_12) //"T20 D12" + 83 -> Turn(Dart.TRIPLE_17,Dart.ZERO, Dart.DOUBLE_16) //"T17 D16" + 82 -> Turn(Dart.TRIPLE_14,Dart.ZERO, Dart.DOUBLE_20) //"T14 D20" + 81 -> Turn(Dart.TRIPLE_19,Dart.ZERO, Dart.DOUBLE_12) //"T19 D12" + 80 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_10) //"T20 D10" + 79 -> Turn(Dart.TRIPLE_13,Dart.ZERO, Dart.DOUBLE_20) //"T13 D20" + 78 -> Turn(Dart.TRIPLE_18,Dart.ZERO, Dart.DOUBLE_12) //"T18 D12" + 77 -> Turn(Dart.TRIPLE_19,Dart.ZERO, Dart.DOUBLE_10) //"T19 D10" + 76 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_8) //"T20 D8" + 75 -> Turn(Dart.TRIPLE_17,Dart.ZERO, Dart.DOUBLE_12) //"T17 D12" + 74 -> Turn(Dart.TRIPLE_18,Dart.ZERO, Dart.DOUBLE_10) //"T18 D10" + 73 -> Turn(Dart.TRIPLE_19,Dart.ZERO, Dart.DOUBLE_8) //"T19 D8" + 72 -> Turn(Dart.TRIPLE_12,Dart.ZERO, Dart.DOUBLE_18) //"T12 D18" + 71 -> Turn(Dart.TRIPLE_17,Dart.ZERO, Dart.DOUBLE_10) //"T17 D10" + 70 -> Turn(Dart.TRIPLE_10,Dart.ZERO, Dart.DOUBLE_20) //"T10 D20" + 69 -> Turn(Dart.TRIPLE_13,Dart.ZERO, Dart.DOUBLE_15) //"T13 D15" + 68 -> Turn(Dart.TRIPLE_20,Dart.ZERO, Dart.DOUBLE_4) //"T20 D4" + 67 -> Turn(Dart.TRIPLE_17, Dart.ZERO, Dart.DOUBLE_8) //"T17 D8" + 66 -> Turn(Dart.TRIPLE_10, Dart.ZERO, Dart.DOUBLE_18) //"T10 D18" + 65 -> Turn(Dart.SINGLE_BULL, Dart.ZERO, Dart.DOUBLE_20) //"S.BULL D20" + 64 -> Turn(Dart.TRIPLE_16, Dart.ZERO, Dart.DOUBLE_8) //"T16 D8" + 63 -> Turn(Dart.TRIPLE_13, Dart.ZERO, Dart.DOUBLE_12) //"T13 D12" + 62 -> Turn(Dart.TRIPLE_10, Dart.ZERO, Dart.DOUBLE_16) //"T10 D16" + 61 -> Turn(Dart.SINGLE_BULL, Dart.ZERO, Dart.DOUBLE_18) //"25 D18" + 60 -> Turn(Dart.SINGLE_20, Dart.ZERO, Dart.DOUBLE_20) //"20 D20" + 59 -> Turn(Dart.SINGLE_19, Dart.ZERO, Dart.DOUBLE_20) //"19 D20" + 58 -> Turn(Dart.SINGLE_18, Dart.ZERO, Dart.DOUBLE_20) //"18 D20" + 57 -> Turn(Dart.SINGLE_17, Dart.ZERO, Dart.DOUBLE_20) //"17 D20" + 56 -> Turn(Dart.TRIPLE_16, Dart.ZERO, Dart.DOUBLE_4) //"T16 D4" + 55 -> Turn(Dart.SINGLE_15, Dart.ZERO, Dart.DOUBLE_20) //"15 D20" + 54 -> Turn(Dart.SINGLE_14, Dart.ZERO, Dart.DOUBLE_20) //"14 D20" + 53 -> Turn(Dart.SINGLE_13, Dart.ZERO, Dart.DOUBLE_20) //"13 D20" + 52 -> Turn(Dart.TRIPLE_12, Dart.ZERO, Dart.DOUBLE_8) //"T12 D8" + 51 -> Turn(Dart.SINGLE_11, Dart.ZERO, Dart.DOUBLE_20) //"11 D20" 50 -> Turn(Dart.ZERO, Dart.ZERO, Dart.BULL) //"BULL" // Special case - 49 -> Turn(Dart.ZERO, Dart.SINGLE_9, Dart.DOUBLE_20) //"9 D20" - 48 -> Turn(Dart.ZERO, Dart.SINGLE_16, Dart.DOUBLE_16) //"16 D16" - 47 -> Turn(Dart.ZERO, Dart.SINGLE_15, Dart.DOUBLE_16) //"15 D16" - 46 -> Turn(Dart.ZERO, Dart.SINGLE_6, Dart.DOUBLE_20) //"6 D20" - 45 -> Turn(Dart.ZERO, Dart.SINGLE_13, Dart.DOUBLE_16) //"13 D16" - 44 -> Turn(Dart.ZERO, Dart.SINGLE_12, Dart.DOUBLE_16) //"12 D16" - 43 -> Turn(Dart.ZERO, Dart.SINGLE_11, Dart.DOUBLE_16) //"11 D16" - 42 -> Turn(Dart.ZERO, Dart.SINGLE_10, Dart.DOUBLE_16) //"10 D16" - 41 -> Turn(Dart.ZERO, Dart.SINGLE_9, Dart.DOUBLE_16) //"9 D16" + 49 -> Turn(Dart.SINGLE_9, Dart.ZERO, Dart.DOUBLE_20) //"9 D20" + 48 -> Turn(Dart.SINGLE_16, Dart.ZERO, Dart.DOUBLE_16) //"16 D16" + 47 -> Turn(Dart.SINGLE_15, Dart.ZERO, Dart.DOUBLE_16) //"15 D16" + 46 -> Turn(Dart.SINGLE_6, Dart.ZERO, Dart.DOUBLE_20) //"6 D20" + 45 -> Turn(Dart.SINGLE_13, Dart.ZERO, Dart.DOUBLE_16) //"13 D16" + 44 -> Turn(Dart.SINGLE_12, Dart.ZERO, Dart.DOUBLE_16) //"12 D16" + 43 -> Turn(Dart.SINGLE_11, Dart.ZERO, Dart.DOUBLE_16) //"11 D16" + 42 -> Turn(Dart.SINGLE_10, Dart.ZERO, Dart.DOUBLE_16) //"10 D16" + 41 -> Turn(Dart.SINGLE_9, Dart.ZERO, Dart.DOUBLE_16) //"9 D16" 40 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_20) //"D20" - 39 -> Turn(Dart.ZERO, Dart.SINGLE_7, Dart.DOUBLE_16) //"7 D16" + 39 -> Turn(Dart.SINGLE_7, Dart.ZERO, Dart.DOUBLE_16) //"7 D16" 38 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_19) //"D19" - 37 -> Turn(Dart.ZERO, Dart.SINGLE_5, Dart.DOUBLE_16) //"5 D16" + 37 -> Turn(Dart.SINGLE_5, Dart.ZERO, Dart.DOUBLE_16) //"5 D16" 36 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_18) //"D18" - 35 -> Turn(Dart.ZERO, Dart.SINGLE_3, Dart.DOUBLE_16) //"3 D16" + 35 -> Turn(Dart.SINGLE_3, Dart.ZERO, Dart.DOUBLE_16) //"3 D16" 34 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_17) //"D17" - 33 -> Turn(Dart.ZERO, Dart.SINGLE_1, Dart.DOUBLE_16) //"1 D16" + 33 -> Turn(Dart.SINGLE_1, Dart.ZERO, Dart.DOUBLE_16) //"1 D16" 32 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_16) //"D16" - 31 -> Turn(Dart.ZERO, Dart.SINGLE_15, Dart.DOUBLE_8) //"15 D8" + 31 -> Turn(Dart.SINGLE_15, Dart.ZERO, Dart.DOUBLE_8) //"15 D8" 30 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_15) //"D15" - 29 -> Turn(Dart.ZERO, Dart.SINGLE_13, Dart.DOUBLE_8) //"13 D8" + 29 -> Turn(Dart.SINGLE_13, Dart.ZERO, Dart.DOUBLE_8) //"13 D8" 28 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_14) //"D14" - 27 -> Turn(Dart.ZERO, Dart.SINGLE_19, Dart.DOUBLE_4) //"19 D4" + 27 -> Turn(Dart.SINGLE_19, Dart.ZERO, Dart.DOUBLE_4) //"19 D4" 26 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_13) //"D13" - 25 -> Turn(Dart.ZERO, Dart.SINGLE_17, Dart.DOUBLE_4) //"17 D4" + 25 -> Turn(Dart.SINGLE_17, Dart.ZERO, Dart.DOUBLE_4) //"17 D4" 24 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_12) //"D12" - 23 -> Turn(Dart.ZERO, Dart.SINGLE_7, Dart.DOUBLE_8) //"7 D8" + 23 -> Turn(Dart.SINGLE_7, Dart.ZERO, Dart.DOUBLE_8) //"7 D8" 22 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_11) //"D11" - 21 -> Turn(Dart.ZERO, Dart.SINGLE_5, Dart.DOUBLE_8) //"5 D8" + 21 -> Turn(Dart.SINGLE_5, Dart.ZERO, Dart.DOUBLE_8) //"5 D8" 20 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_10) //"D10" - 19 -> Turn(Dart.ZERO, Dart.SINGLE_11, Dart.DOUBLE_4) //"11 D4" + 19 -> Turn(Dart.SINGLE_11, Dart.ZERO, Dart.DOUBLE_4) //"11 D4" 18 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_9) //"D9" - 17 -> Turn(Dart.ZERO, Dart.SINGLE_9, Dart.DOUBLE_4) //"9 D4" + 17 -> Turn(Dart.SINGLE_9, Dart.ZERO, Dart.DOUBLE_4) //"9 D4" 16 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_8) //"D8" - 15 -> Turn(Dart.ZERO, Dart.SINGLE_7, Dart.DOUBLE_4) //"7 D4" + 15 -> Turn(Dart.SINGLE_7, Dart.ZERO, Dart.DOUBLE_4) //"7 D4" 14 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_7) //"D7" - 13 -> Turn(Dart.ZERO, Dart.SINGLE_5, Dart.DOUBLE_4) //"5 D4" + 13 -> Turn(Dart.SINGLE_5, Dart.ZERO, Dart.DOUBLE_4) //"5 D4" 12 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_6) //"D6" - 11 -> Turn(Dart.ZERO, Dart.SINGLE_3, Dart.DOUBLE_4) //"3 D4" + 11 -> Turn(Dart.SINGLE_3, Dart.ZERO, Dart.DOUBLE_4) //"3 D4" 10 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_5) //"D5" - 9 -> Turn(Dart.ZERO, Dart.SINGLE_1, Dart.DOUBLE_4) + 9 -> Turn(Dart.SINGLE_1, Dart.ZERO, Dart.DOUBLE_4) 8 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_4) - 7 -> Turn(Dart.ZERO, Dart.SINGLE_3, Dart.DOUBLE_2) + 7 -> Turn(Dart.SINGLE_3, Dart.ZERO, Dart.DOUBLE_2) 6 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_3) - 5 -> Turn(Dart.ZERO, Dart.SINGLE_1, Dart.DOUBLE_2) + 5 -> Turn(Dart.SINGLE_1, Dart.ZERO, Dart.DOUBLE_2) 4 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_2) - 3 -> Turn(Dart.ZERO, Dart.SINGLE_1, Dart.DOUBLE_1) + 3 -> Turn(Dart.SINGLE_1, Dart.ZERO, Dart.DOUBLE_1) 2 -> Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_1) 1 -> Turn(Dart.ZERO, Dart.ZERO, Dart.SINGLE_1) 0 -> Turn(Dart.ZERO, Dart.ZERO, Dart.ZERO) diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/model/TurnAtFinishTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/model/TurnAtFinishTest.kt new file mode 100644 index 00000000..fc366c0b --- /dev/null +++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/model/TurnAtFinishTest.kt @@ -0,0 +1,50 @@ +package nl.entreco.domain.model + +import nl.entreco.domain.play.ScoreEstimator +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * Created by entreco on 28/01/2018. + */ +class TurnAtFinishTest{ + + private val estimator = ScoreEstimator() + + @Test + fun `it should correct for Darts at Finish (2)`() { + assertEquals(Turn(Dart.DOUBLE_1), estimator.guess(2, false).setDartsUsedForFinish(1)) + assertEquals(Turn(Dart.ZERO, Dart.DOUBLE_1), estimator.guess(2, false).setDartsUsedForFinish(2)) + assertEquals(Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_1), estimator.guess(2, false).setDartsUsedForFinish(3)) + } + + @Test + fun `it should correct for Darts at Finish (3)`() { + assertEquals(Turn(Dart.SINGLE_1, Dart.DOUBLE_1), estimator.guess(3, false).setDartsUsedForFinish(2)) + assertEquals(Turn(Dart.SINGLE_1, Dart.ZERO, Dart.DOUBLE_1), estimator.guess(3, false).setDartsUsedForFinish(3)) + } + + @Test + fun `it should correct for Darts at Finish (21)`() { + assertEquals(Turn(Dart.SINGLE_5, Dart.DOUBLE_8), estimator.guess(21, false).setDartsUsedForFinish(2)) + assertEquals(Turn(Dart.SINGLE_5, Dart.ZERO, Dart.DOUBLE_8), estimator.guess(21, false).setDartsUsedForFinish(3)) + } + + @Test + fun `it should correct for Darts at Finish (20)`() { + assertEquals(Turn(Dart.DOUBLE_10), estimator.guess(20, false).setDartsUsedForFinish(1)) + assertEquals(Turn(Dart.ZERO, Dart.DOUBLE_10), estimator.guess(20, false).setDartsUsedForFinish(2)) + assertEquals(Turn(Dart.ZERO, Dart.ZERO, Dart.DOUBLE_10), estimator.guess(20, false).setDartsUsedForFinish(3)) + } + + @Test(expected = IllegalStateException::class) + fun `it should throw if impossible combination (21 in 1)`() { + estimator.guess(21, false).setDartsUsedForFinish(1) + } + + + @Test(expected = IllegalStateException::class) + fun `it should throw if impossible combination (3 in 1)`() { + estimator.guess(3, false).setDartsUsedForFinish(1) + } +} \ No newline at end of file diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/model/TurnTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/model/TurnTest.kt index 169b2ac0..c62471ce 100644 --- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/model/TurnTest.kt +++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/model/TurnTest.kt @@ -1,6 +1,6 @@ package nl.entreco.domain.model -import org.junit.Assert.assertEquals +import org.junit.Assert.* import org.junit.Test /** @@ -149,4 +149,20 @@ class TurnTest { assertEquals("BULL", Turn(Dart.BULL).asFinish()) assertEquals("S.BULL BULL", Turn(Dart.SINGLE_BULL, Dart.BULL).asFinish()) } + + + @Test + fun `it should return false for turns without zeros`() { + assertTrue(Turn(Dart.ZERO).hasZeros()) + assertTrue(Turn(Dart.ZERO, Dart.DOUBLE_1).hasZeros()) + assertTrue(Turn(Dart.ZERO, Dart.DOUBLE_1, Dart.SINGLE_2).hasZeros()) + } + + @Test + fun `it should return true for turns with zeros`() { + assertFalse(Turn().hasZeros()) + assertFalse(Turn(Dart.DOUBLE_1).hasZeros()) + assertFalse(Turn(Dart.DOUBLE_1, Dart.SINGLE_2).hasZeros()) + assertFalse(Turn(Dart.DOUBLE_1, Dart.SINGLE_14, Dart.SINGLE_3).hasZeros()) + } } \ No newline at end of file diff --git a/store/artboards.sketch b/store/artboards.sketch index 48b33fee..db08f9eb 100644 Binary files a/store/artboards.sketch and b/store/artboards.sketch differ diff --git a/store/screenshots/dsc_32.png b/store/screenshots/dsc_32.png new file mode 100644 index 00000000..1eee7115 Binary files /dev/null and b/store/screenshots/dsc_32.png differ diff --git a/store/screenshots/dsc_33.png b/store/screenshots/dsc_33.png new file mode 100644 index 00000000..959c1dd5 Binary files /dev/null and b/store/screenshots/dsc_33.png differ diff --git a/store/screenshots/dsc_34.png b/store/screenshots/dsc_34.png new file mode 100644 index 00000000..d7aced2e Binary files /dev/null and b/store/screenshots/dsc_34.png differ diff --git a/store/screenshots/dsc_35.png b/store/screenshots/dsc_35.png new file mode 100644 index 00000000..355a4493 Binary files /dev/null and b/store/screenshots/dsc_35.png differ diff --git a/store/screenshots/dsc_36.png b/store/screenshots/dsc_36.png new file mode 100644 index 00000000..d015be46 Binary files /dev/null and b/store/screenshots/dsc_36.png differ diff --git a/store/screenshots/dsc_37.png b/store/screenshots/dsc_37.png new file mode 100644 index 00000000..4cf9cb33 Binary files /dev/null and b/store/screenshots/dsc_37.png differ diff --git a/store/screenshots/dsc_38.png b/store/screenshots/dsc_38.png new file mode 100644 index 00000000..90a1f79e Binary files /dev/null and b/store/screenshots/dsc_38.png differ