diff --git a/app/src/main/java/com/sadellie/unitto/data/KeypadSymbols.kt b/app/src/main/java/com/sadellie/unitto/data/KeypadSymbols.kt index 1b74a7ea..d5c31a51 100644 --- a/app/src/main/java/com/sadellie/unitto/data/KeypadSymbols.kt +++ b/app/src/main/java/com/sadellie/unitto/data/KeypadSymbols.kt @@ -51,17 +51,34 @@ const val KEY_EXPONENT = "^" const val KEY_SQRT = "√" -val OPERATORS = listOf( - KEY_PLUS, - KEY_MINUS, - KEY_MINUS_DISPLAY, - KEY_MULTIPLY, - KEY_MULTIPLY_DISPLAY, - KEY_DIVIDE, - KEY_DIVIDE_DISPLAY, - KEY_SQRT, - KEY_EXPONENT, -) +val OPERATORS by lazy { + listOf( + KEY_PLUS, + KEY_MINUS, + KEY_MINUS_DISPLAY, + KEY_MULTIPLY, + KEY_MULTIPLY_DISPLAY, + KEY_DIVIDE, + KEY_DIVIDE_DISPLAY, + KEY_SQRT, + KEY_EXPONENT, + ) +} + +val DIGITS by lazy { + listOf( + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_0, + ) +} val INTERNAL_DISPLAY: Map = hashMapOf( KEY_MINUS to KEY_MINUS_DISPLAY, diff --git a/app/src/main/java/com/sadellie/unitto/screens/main/MainViewModel.kt b/app/src/main/java/com/sadellie/unitto/screens/main/MainViewModel.kt index a798a82d..d4120be5 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/main/MainViewModel.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/main/MainViewModel.kt @@ -27,6 +27,7 @@ import androidx.lifecycle.viewModelScope import com.github.keelar.exprk.ExpressionException import com.github.keelar.exprk.Expressions import com.sadellie.unitto.FirebaseHelper +import com.sadellie.unitto.data.DIGITS import com.sadellie.unitto.data.INTERNAL_DISPLAY import com.sadellie.unitto.data.KEY_0 import com.sadellie.unitto.data.KEY_1 @@ -328,18 +329,33 @@ class MainViewModel @Inject constructor( } } KEY_0 -> { - // Don't add zero if the input is already a zero - if (inputValue.value == KEY_0) return - // Prevents things like "-00" and "4+000" - if ((lastSecondSymbol in OPERATORS) and (lastSymbol == KEY_0)) return - setInputSymbols(symbolToAdd) + when { + // Don't add zero if the input is already a zero + (inputValue.value == KEY_0) -> {} + (lastSymbol == KEY_RIGHT_BRACKET) -> { + processInput(KEY_MULTIPLY) + setInputSymbols(symbolToAdd) + } + // Prevents things like "-00" and "4+000" + ((lastSecondSymbol in OPERATORS + KEY_LEFT_BRACKET) and (lastSymbol == KEY_0)) -> {} + else -> { + setInputSymbols(symbolToAdd) + } + } } KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 -> { // Replace single zero (default input) if it's here - if (inputValue.value == KEY_0) { - setInputSymbols(symbolToAdd, false) - } else { - setInputSymbols(symbolToAdd) + when { + (inputValue.value == KEY_0) -> { + setInputSymbols(symbolToAdd, false) + } + (lastSymbol == KEY_RIGHT_BRACKET) -> { + processInput(KEY_MULTIPLY) + setInputSymbols(symbolToAdd) + } + else -> { + setInputSymbols(symbolToAdd) + } } } KEY_MINUS -> { @@ -371,6 +387,10 @@ class MainViewModel @Inject constructor( (inputValue.value == KEY_0) -> { setInputSymbols(symbolToAdd, false) } + (lastSymbol == KEY_RIGHT_BRACKET) || (lastSymbol in DIGITS) || (lastSymbol == KEY_DOT) -> { + processInput(KEY_MULTIPLY) + setInputSymbols(symbolToAdd) + } else -> { setInputSymbols(symbolToAdd) } @@ -379,9 +399,7 @@ class MainViewModel @Inject constructor( KEY_RIGHT_BRACKET -> { when { // Replace single zero with minus (to support negative numbers) - (inputValue.value == KEY_0) -> { - setInputSymbols(symbolToAdd, false) - } + (inputValue.value == KEY_0) -> {} (lastSymbol == KEY_LEFT_BRACKET) -> {} (latestInputStack.filter { it == KEY_LEFT_BRACKET }.size == latestInputStack.filter { it == KEY_RIGHT_BRACKET }.size) -> {} @@ -396,6 +414,10 @@ class MainViewModel @Inject constructor( (inputValue.value == KEY_0) -> { setInputSymbols(symbolToAdd, false) } + (lastSymbol == KEY_RIGHT_BRACKET) || (lastSymbol in DIGITS) || (lastSymbol == KEY_DOT) -> { + processInput(KEY_MULTIPLY) + setInputSymbols(symbolToAdd) + } else -> { setInputSymbols(symbolToAdd) } diff --git a/app/src/test/java/com/sadellie/unitto/screens/MainViewModelTest.kt b/app/src/test/java/com/sadellie/unitto/screens/MainViewModelTest.kt index 76b8bb66..c0b14da3 100644 --- a/app/src/test/java/com/sadellie/unitto/screens/MainViewModelTest.kt +++ b/app/src/test/java/com/sadellie/unitto/screens/MainViewModelTest.kt @@ -167,6 +167,48 @@ class MainViewModelTest { assertEquals("√0", viewModel.inputValue.value) assertEquals("√0", viewModel.mainFlow.value.inputValue) viewModel.clearInput() + + // ( | 000 | (0 + viewModel.processInput(KEY_LEFT_BRACKET) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_0) + assertEquals("(0", viewModel.inputValue.value) + assertEquals("(0", viewModel.mainFlow.value.inputValue) + viewModel.clearInput() + + // (1+12) | 000 | (1+12)*0 + viewModel.processInput(KEY_LEFT_BRACKET) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_PLUS) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_2) + viewModel.processInput(KEY_RIGHT_BRACKET) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_0) + assertEquals("(1+12)*0", viewModel.inputValue.value) + assertEquals("(1+12)×0", viewModel.mainFlow.value.inputValue) + viewModel.clearInput() + + // (1.002+120) | 000 | (1+120)*0 + viewModel.processInput(KEY_LEFT_BRACKET) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_DOT) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_2) + viewModel.processInput(KEY_PLUS) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_2) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_RIGHT_BRACKET) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_0) + assertEquals("(1.002+120)*0", viewModel.inputValue.value) + assertEquals("(1.002+120)×0", viewModel.mainFlow.value.inputValue) + viewModel.clearInput() } private fun `test digits from 1 to 9`() { @@ -183,6 +225,19 @@ class MainViewModelTest { assertEquals("123456789", viewModel.inputValue.value) assertEquals("123456789", viewModel.mainFlow.value.inputValue) viewModel.clearInput() + + // (1+1) | 111 | (1+1)*111 + viewModel.processInput(KEY_LEFT_BRACKET) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_PLUS) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_RIGHT_BRACKET) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_1) + assertEquals("(1+1)*111", viewModel.inputValue.value) + assertEquals("(1+1)×111", viewModel.mainFlow.value.inputValue) + viewModel.clearInput() } private fun `test plus, divide, multiply and exponent operators`() { @@ -407,10 +462,12 @@ class MainViewModelTest { } private fun `test brackets`() { - // 0 | ( | ( - viewModel.processInput(KEY_LEFT_BRACKET) - assertEquals("(", viewModel.inputValue.value) - assertEquals("(", viewModel.mainFlow.value.inputValue) + // 0 | ))) | 0 + viewModel.processInput(KEY_RIGHT_BRACKET) + viewModel.processInput(KEY_RIGHT_BRACKET) + viewModel.processInput(KEY_RIGHT_BRACKET) + assertEquals("0", viewModel.inputValue.value) + assertEquals("0", viewModel.mainFlow.value.inputValue) viewModel.clearInput() // 0 | ((( | ((( @@ -421,7 +478,7 @@ class MainViewModelTest { assertEquals("(((", viewModel.mainFlow.value.inputValue) viewModel.clearInput() - // √ | (10+2) | √(10+2) + // √(10+2 | )( | √(10+2)*( viewModel.processInput(KEY_SQRT) viewModel.processInput(KEY_LEFT_BRACKET) viewModel.processInput(KEY_1) @@ -429,8 +486,23 @@ class MainViewModelTest { viewModel.processInput(KEY_PLUS) viewModel.processInput(KEY_2) viewModel.processInput(KEY_RIGHT_BRACKET) - assertEquals("√(10+2)", viewModel.inputValue.value) - assertEquals("√(10+2)", viewModel.mainFlow.value.inputValue) + viewModel.processInput(KEY_LEFT_BRACKET) + assertEquals("√(10+2)*(", viewModel.inputValue.value) + assertEquals("√(10+2)×(", viewModel.mainFlow.value.inputValue) + viewModel.clearInput() + + // √(10+2./ | ( | √(10+2./( + viewModel.processInput(KEY_SQRT) + viewModel.processInput(KEY_LEFT_BRACKET) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_PLUS) + viewModel.processInput(KEY_2) + viewModel.processInput(KEY_DOT) + viewModel.processInput(KEY_DIVIDE) + viewModel.processInput(KEY_LEFT_BRACKET) + assertEquals("√(10+2./(", viewModel.inputValue.value) + assertEquals("√(10+2.÷(", viewModel.mainFlow.value.inputValue) viewModel.clearInput() // 0 | ()()))(( | (((( @@ -445,6 +517,20 @@ class MainViewModelTest { assertEquals("((((", viewModel.inputValue.value) assertEquals("((((", viewModel.mainFlow.value.inputValue) viewModel.clearInput() + + // √(10+2)^ | ( | √(10+2)^( + viewModel.processInput(KEY_SQRT) + viewModel.processInput(KEY_LEFT_BRACKET) + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_0) + viewModel.processInput(KEY_PLUS) + viewModel.processInput(KEY_2) + viewModel.processInput(KEY_RIGHT_BRACKET) + viewModel.processInput(KEY_EXPONENT) + viewModel.processInput(KEY_LEFT_BRACKET) + assertEquals("√(10+2)^(", viewModel.inputValue.value) + assertEquals("√(10+2)^(", viewModel.mainFlow.value.inputValue) + viewModel.clearInput() } private fun `test square root`() { @@ -455,6 +541,17 @@ class MainViewModelTest { assertEquals("√√√", viewModel.inputValue.value) assertEquals("√√√", viewModel.mainFlow.value.inputValue) viewModel.clearInput() + + // 123 | √√√ | 123*√√√ + viewModel.processInput(KEY_1) + viewModel.processInput(KEY_2) + viewModel.processInput(KEY_3) + viewModel.processInput(KEY_SQRT) + viewModel.processInput(KEY_SQRT) + viewModel.processInput(KEY_SQRT) + assertEquals("123*√√√", viewModel.inputValue.value) + assertEquals("123×√√√", viewModel.mainFlow.value.inputValue) + viewModel.clearInput() } @Test