From 61ee2b88b9adce3841a996230711c9ee2b8713ee Mon Sep 17 00:00:00 2001 From: Jay Barria Date: Thu, 24 Sep 2020 10:27:10 +0800 Subject: [PATCH] percent support and callback for division by zero error --- .../com/github/jairrab/calc/Calculator.kt | 3 +- .../github/jairrab/calc/CalculatorUpdate.kt | 6 ++- .../github/jairrab/calc/driver/TestDriver.kt | 11 ++--- .../jairrab/calc/lib/CalculatorUtility.kt | 8 +++- .../lib/controls/buttons/ClearProcessor.kt | 1 + .../lib/controls/outputs/DisplayManager.kt | 46 +++++++++++-------- .../lib/mathutils/DivideByZeroException.kt | 3 ++ .../calculators/BasicMdasCalculator.kt | 35 ++++++++------ .../calculators/BasicNonMdasCalculator.kt | 17 +++++-- 9 files changed, 80 insertions(+), 50 deletions(-) create mode 100644 src/main/kotlin/com/github/jairrab/calc/lib/mathutils/DivideByZeroException.kt diff --git a/src/main/kotlin/com/github/jairrab/calc/Calculator.kt b/src/main/kotlin/com/github/jairrab/calc/Calculator.kt index 6621bfb..2ba1d2d 100644 --- a/src/main/kotlin/com/github/jairrab/calc/Calculator.kt +++ b/src/main/kotlin/com/github/jairrab/calc/Calculator.kt @@ -10,6 +10,7 @@ import com.github.jairrab.calc.lib.controls.entries.EntriesManager interface Calculator { fun press(button: CalculatorButton) fun clear() + fun resetToNumber(number: Double) fun pressOne() fun pressTwo() fun pressThree() @@ -30,7 +31,7 @@ interface Calculator { fun pressEquals() fun setListener(listener: Listener) - interface Listener { + fun interface Listener { fun onCalculatorUpdate(update: CalculatorUpdate) } diff --git a/src/main/kotlin/com/github/jairrab/calc/CalculatorUpdate.kt b/src/main/kotlin/com/github/jairrab/calc/CalculatorUpdate.kt index 3f6e3a8..619166d 100644 --- a/src/main/kotlin/com/github/jairrab/calc/CalculatorUpdate.kt +++ b/src/main/kotlin/com/github/jairrab/calc/CalculatorUpdate.kt @@ -1,7 +1,7 @@ package com.github.jairrab.calc sealed class CalculatorUpdate { - object Initializing : CalculatorUpdate() + class Initializing(val number: Double) : CalculatorUpdate() class OnUpdate( val key: String?, @@ -10,4 +10,8 @@ sealed class CalculatorUpdate { ) : CalculatorUpdate() class InvalidKey(val invalidKeyType: InvalidKeyType) : CalculatorUpdate() + + sealed class Error : CalculatorUpdate() { + class DivideByZero(val key: String?, val entries: List) : Error() + } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/jairrab/calc/driver/TestDriver.kt b/src/main/kotlin/com/github/jairrab/calc/driver/TestDriver.kt index 0b42eb2..c9b8bf7 100644 --- a/src/main/kotlin/com/github/jairrab/calc/driver/TestDriver.kt +++ b/src/main/kotlin/com/github/jairrab/calc/driver/TestDriver.kt @@ -15,13 +15,10 @@ import com.github.jairrab.calc.CalculatorUpdate fun main() { val calculator = Calculator.getInstance( calculatorType = CalculatorType.BASIC_MDAS, - initialNumber = 0.0, - listener = object : Calculator.Listener { - override fun onCalculatorUpdate(update: CalculatorUpdate) { - //See runtime logs for output - } - } - ) + initialNumber = 0.0 + ) { + //See runtime logs for output + } calculator.pressOne() calculator.pressTwo() diff --git a/src/main/kotlin/com/github/jairrab/calc/lib/CalculatorUtility.kt b/src/main/kotlin/com/github/jairrab/calc/lib/CalculatorUtility.kt index f5eac3e..4de5e1d 100644 --- a/src/main/kotlin/com/github/jairrab/calc/lib/CalculatorUtility.kt +++ b/src/main/kotlin/com/github/jairrab/calc/lib/CalculatorUtility.kt @@ -11,8 +11,7 @@ internal open class CalculatorUtility( private val controlProcessor: ControlProcessor ) : Calculator { init { - controlProcessor.clearProcessor.initialize(initialNumber) - controlProcessor.displayManager.update(null) + resetToNumber(initialNumber) } override fun press(button: CalculatorButton) { @@ -44,6 +43,11 @@ internal open class CalculatorUtility( controlProcessor.displayManager.update(CalculatorButton.CLEAR) } + final override fun resetToNumber(number: Double) { + controlProcessor.clearProcessor.initialize(number) + controlProcessor.displayManager.update(number) + } + override fun pressOne() { controlProcessor.numberProcessor.processNumber(CalculatorButton.ONE) controlProcessor.displayManager.update(CalculatorButton.ONE) diff --git a/src/main/kotlin/com/github/jairrab/calc/lib/controls/buttons/ClearProcessor.kt b/src/main/kotlin/com/github/jairrab/calc/lib/controls/buttons/ClearProcessor.kt index bff87d5..b57436c 100644 --- a/src/main/kotlin/com/github/jairrab/calc/lib/controls/buttons/ClearProcessor.kt +++ b/src/main/kotlin/com/github/jairrab/calc/lib/controls/buttons/ClearProcessor.kt @@ -8,6 +8,7 @@ class ClearProcessor( private val entriesManager: EntriesManager ) { fun initialize(initialNumber: Double) { + entriesManager.clear() if (initialNumber != 0.0) { val entry = if (initialNumber % 1 == 0.0) { initialNumber.toInt().toString() diff --git a/src/main/kotlin/com/github/jairrab/calc/lib/controls/outputs/DisplayManager.kt b/src/main/kotlin/com/github/jairrab/calc/lib/controls/outputs/DisplayManager.kt index d946fd6..384a602 100644 --- a/src/main/kotlin/com/github/jairrab/calc/lib/controls/outputs/DisplayManager.kt +++ b/src/main/kotlin/com/github/jairrab/calc/lib/controls/outputs/DisplayManager.kt @@ -6,7 +6,9 @@ import com.github.jairrab.calc.Calculator import com.github.jairrab.calc.CalculatorButton import com.github.jairrab.calc.CalculatorType import com.github.jairrab.calc.CalculatorUpdate +import com.github.jairrab.calc.CalculatorUpdate.Error import com.github.jairrab.calc.lib.controls.entries.EntriesManager +import com.github.jairrab.calc.lib.mathutils.DivideByZeroException import com.github.jairrab.calc.lib.mathutils.EquationSolver import com.github.jairrab.calc.lib.utils.Logger.LOG @@ -15,36 +17,40 @@ class DisplayManager private constructor( private val entriesManager: EntriesManager, private val equationSolver: EquationSolver ) { - fun update(button: CalculatorButton?) { + fun update(button: CalculatorButton) { val entries = entriesManager.getEntries() - - val result = when { - entriesManager.isNoEntries() -> 0.0 - entriesManager.isSingleEntry() -> when { - entriesManager.isLastEntryADecimal() -> 0.0 - entriesManager.isLastEntryAPercentNumber() -> entriesManager.getLastDoubleEntry() - entriesManager.isLastEntryANumber() -> entriesManager.getLastDoubleEntry() - else -> { - throw IllegalStateException("Invalid entry: ${entriesManager.getLastEntry()}") + try { + val result = when { + entriesManager.isNoEntries() -> 0.0 + entriesManager.isSingleEntry() -> when { + entriesManager.isLastEntryADecimal() -> 0.0 + entriesManager.isLastEntryAPercentNumber() -> entriesManager.getLastDoubleEntry() + entriesManager.isLastEntryANumber() -> entriesManager.getLastDoubleEntry() + else -> { + throw IllegalStateException("Invalid entry: ${entriesManager.getLastEntry()}") + } } + else -> equationSolver.solve(entries) } - else -> equationSolver.solve(entries) - } - if (button == null) { - updateListener(CalculatorUpdate.Initializing) - LOG.info("Initializing calculator") - } else { LOG.info("Key: ${button.tag} | Entries: $entries | Result: $result") updateListener(CalculatorUpdate.OnUpdate(button.tag, entries, result)) - } - if (button == CalculatorButton.EQUALS) { - entriesManager.lastResult = result + if (button == CalculatorButton.EQUALS) { + entriesManager.lastResult = result + } + } catch (e: DivideByZeroException) { + LOG.warning("Divide by zero error") + listener?.onCalculatorUpdate(Error.DivideByZero(button.tag, entries)) } } - fun updateListener(calculatorUpdate: CalculatorUpdate){ + fun update(number: Double) { + updateListener(CalculatorUpdate.Initializing(number)) + LOG.info("Initializing calculator") + } + + fun updateListener(calculatorUpdate: CalculatorUpdate) { listener?.onCalculatorUpdate(calculatorUpdate) } diff --git a/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/DivideByZeroException.kt b/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/DivideByZeroException.kt new file mode 100644 index 0000000..fb58c76 --- /dev/null +++ b/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/DivideByZeroException.kt @@ -0,0 +1,3 @@ +package com.github.jairrab.calc.lib.mathutils + +class DivideByZeroException:Exception("Division by zero error!") \ No newline at end of file diff --git a/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicMdasCalculator.kt b/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicMdasCalculator.kt index 835408b..43fcc45 100644 --- a/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicMdasCalculator.kt +++ b/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicMdasCalculator.kt @@ -3,6 +3,7 @@ package com.github.jairrab.calc.lib.mathutils.calculators import com.github.jairrab.calc.CalculatorButton.* +import com.github.jairrab.calc.lib.mathutils.DivideByZeroException import com.github.jairrab.calc.lib.mathutils.EntriesCalculator import com.github.jairrab.calc.lib.mathutils.OperatorUtils.isOperator import com.github.jairrab.calc.lib.utils.trimEndChar @@ -45,7 +46,7 @@ class BasicMdasCalculator : EntriesCalculator { a += b } DIVISION.tag -> { - b /= getEntryWithPercentFactor(entries[i]) + b /= getDivisor(entries, i) a += b } else -> throw IllegalStateException("Error solving last entry") @@ -63,7 +64,7 @@ class BasicMdasCalculator : EntriesCalculator { b = 0.0 } DIVISION.tag -> { - b /= getEntryWithPercentFactor(entries[i]) + b /= getDivisor(entries, i) a += b b = 0.0 } @@ -78,7 +79,7 @@ class BasicMdasCalculator : EntriesCalculator { b = 0.0 } DIVISION.tag -> { - b /= getEntryWithPercentFactor(entries[i]) + b /= getDivisor(entries, i) a += b b = 0.0 } @@ -88,14 +89,14 @@ class BasicMdasCalculator : EntriesCalculator { PLUS.tag -> b = getEntryWithPercentFactor(entries[i]) MINUS.tag -> b = -getEntryWithPercentFactor(entries[i]) MULTIPLY.tag -> b *= getEntryWithPercentFactor(entries[i]) - DIVISION.tag -> b /= getEntryWithPercentFactor(entries[i]) + DIVISION.tag -> b /= getDivisor(entries, i) else -> throw IllegalStateException("Error checking multiply tag") } DIVISION.tag -> when (entries[i - 1]) { PLUS.tag -> b = getEntryWithPercentFactor(entries[i]) MINUS.tag -> b = -getEntryWithPercentFactor(entries[i]) MULTIPLY.tag -> b *= getEntryWithPercentFactor(entries[i]) - DIVISION.tag -> b /= getEntryWithPercentFactor(entries[i]) + DIVISION.tag -> b /= getDivisor(entries, i) else -> throw IllegalStateException("Error checking division tag") } else -> throw IllegalStateException("Error checking next operator tag") @@ -104,19 +105,25 @@ class BasicMdasCalculator : EntriesCalculator { throw IllegalStateException("Error solving equation") } + private fun getDivisor(entries: List, i: Int): Double { + val divisor = getEntryWithPercentFactor(entries[i]) + if (divisor == 0.0) throw DivideByZeroException() + return divisor + } + private fun getEntryWithPercentFactor(entry: String, baseNumber: Double): Double { - return if (entry.endsWith(PERCENT.tag)) { - baseNumber * entry.trimEndChar().toDouble() / 100.0 - } else { - entry.toDouble() + return when { + entry == DECIMAL.tag -> 0.0 + entry.endsWith(PERCENT.tag) -> baseNumber * entry.trimEndChar().toDouble() / 100.0 + else -> entry.toDouble() } } - private fun getEntryWithPercentFactor(entry:String): Double { - return if (entry.endsWith(PERCENT.tag)) { - entry.trimEndChar().toDouble() / 100.0 - } else { - entry.toDouble() + private fun getEntryWithPercentFactor(entry: String): Double { + return when { + entry == DECIMAL.tag -> 1.0 + entry.endsWith(PERCENT.tag) -> entry.trimEndChar().toDouble() / 100.0 + else -> entry.toDouble() } } } \ No newline at end of file diff --git a/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicNonMdasCalculator.kt b/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicNonMdasCalculator.kt index 4e281ef..df422fb 100644 --- a/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicNonMdasCalculator.kt +++ b/src/main/kotlin/com/github/jairrab/calc/lib/mathutils/calculators/BasicNonMdasCalculator.kt @@ -3,6 +3,7 @@ package com.github.jairrab.calc.lib.mathutils.calculators import com.github.jairrab.calc.CalculatorButton.* +import com.github.jairrab.calc.lib.mathutils.DivideByZeroException import com.github.jairrab.calc.lib.mathutils.EntriesCalculator import com.github.jairrab.calc.lib.mathutils.OperatorUtils.isOperator import com.github.jairrab.calc.lib.utils.trimEndChar @@ -40,7 +41,7 @@ class BasicNonMdasCalculator : EntriesCalculator { PLUS.tag -> a += getEntryWithPercentFactor(entries[i], a) MINUS.tag -> a -= getEntryWithPercentFactor(entries[i], a) MULTIPLY.tag -> a *= getEntryWithPercentFactor(entries[i]) - DIVISION.tag -> a /= getEntryWithPercentFactor(entries[i]) + DIVISION.tag -> a /= getDivisor(entries, i) else -> throw IllegalStateException("Error solving last entry") } return a @@ -51,28 +52,28 @@ class BasicNonMdasCalculator : EntriesCalculator { PLUS.tag -> a += getEntryWithPercentFactor(entries[i], a) MINUS.tag -> a -= getEntryWithPercentFactor(entries[i], a) MULTIPLY.tag -> a *= getEntryWithPercentFactor(entries[i]) - DIVISION.tag -> a /= getEntryWithPercentFactor(entries[i]) + DIVISION.tag -> a /= getDivisor(entries, i) else -> throw IllegalStateException("Error checking plus tag") } MINUS.tag -> when (entries[i - 1]) { PLUS.tag -> a += getEntryWithPercentFactor(entries[i], a) MINUS.tag -> a -= getEntryWithPercentFactor(entries[i], a) MULTIPLY.tag -> a *= getEntryWithPercentFactor(entries[i]) - DIVISION.tag -> a /= getEntryWithPercentFactor(entries[i]) + DIVISION.tag -> a /= getDivisor(entries, i) else -> throw IllegalStateException("Error checking minus tag") } MULTIPLY.tag -> when (entries[i - 1]) { PLUS.tag -> a += getEntryWithPercentFactor(entries[i]) MINUS.tag -> a -= getEntryWithPercentFactor(entries[i]) MULTIPLY.tag -> a *= getEntryWithPercentFactor(entries[i]) - DIVISION.tag -> a /= getEntryWithPercentFactor(entries[i]) + DIVISION.tag -> a /= getDivisor(entries, i) else -> throw IllegalStateException("Error checking multiply tag") } DIVISION.tag -> when (entries[i - 1]) { PLUS.tag -> a += getEntryWithPercentFactor(entries[i]) MINUS.tag -> a -= getEntryWithPercentFactor(entries[i]) MULTIPLY.tag -> a *= getEntryWithPercentFactor(entries[i]) - DIVISION.tag -> a /= getEntryWithPercentFactor(entries[i]) + DIVISION.tag -> a /= getDivisor(entries, i) else -> throw IllegalStateException("Error checking division tag") } else -> throw IllegalStateException("Error checking next operator tag") @@ -81,6 +82,12 @@ class BasicNonMdasCalculator : EntriesCalculator { throw IllegalStateException("Error solving equation") } + private fun getDivisor(entries: List, i: Int): Double { + val divisor = getEntryWithPercentFactor(entries[i]) + if (divisor == 0.0) throw DivideByZeroException() + return divisor + } + private fun getEntryWithPercentFactor(entry: String, baseNumber: Double): Double { return if (entry.endsWith(PERCENT.tag)) { baseNumber * entry.trimEndChar().toDouble() / 100.0