Infinite Precision using BigDecimal

- Moved to using BigDecimal
- Replaced Deprecated Methods/Classes
This commit is contained in:
Vyas Nellutla 2020-07-16 08:43:51 -05:00
parent 2703514ef2
commit 72eaa36af7
No known key found for this signature in database
GPG key ID: B20BCF5A38C1E088
25 changed files with 348 additions and 344 deletions

View file

@ -20,7 +20,7 @@ This app is just one piece of a bigger series of apps. You can find the rest of
<img alt="App image" src="fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg" width="30%">
</div>
</br>
<br>
It contains a couple UI and unit tests, they can be ran with the following instructions.
<h3>Running Espresso UI tests</h3>

View file

@ -61,9 +61,10 @@ dependencies {
implementation 'com.simplemobiletools:commons:5.28.23'
implementation 'me.grantland:autofittextview:0.2.1'
testImplementation 'junit:junit:4.12'
testImplementation 'androidx.test.ext:junit:1.1.1'
testImplementation 'org.robolectric:robolectric:3.8'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.annotation:annotation:1.0.0'
androidTestImplementation 'androidx.test:runner:1.1.0-beta02'
androidTestImplementation 'androidx.test:rules:1.1.0-beta02'

View file

@ -1,7 +1,7 @@
package com.simplemobiletools.calculator;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.simplemobiletools.calculator.activities.MainActivity;

View file

@ -6,7 +6,7 @@ import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.simplemobiletools.calculator.activities.MainActivity
import org.junit.Rule
import org.junit.Test
@ -74,11 +74,11 @@ class PercentTests {
}
private fun press(id: Int) {
Espresso.onView(ViewMatchers.withId(id)).perform(ViewActions.click())
Espresso.onView(withId(id)).perform(ViewActions.click())
}
private fun longPress(id: Int) {
Espresso.onView(ViewMatchers.withId(id)).perform(ViewActions.longClick())
Espresso.onView(withId(id)).perform(ViewActions.longClick())
}
private fun checkResult(desired: String) {

View file

@ -5,7 +5,7 @@
android:installLocation="auto">
<uses-permission
android:name="android.permission.USE_FINGERPRINT"
android:name="android.permission.USE_BIOMETRIC"
tools:node="remove" />
<application
@ -15,15 +15,242 @@
android:label="@string/app_launcher_name"
android:roundIcon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
<activity
android:name=".activities.SplashActivity"
android:theme="@style/SplashTheme" />
<activity-alias
android:name=".activities.SplashActivity.Grey_black"
android:enabled="false"
android:icon="@mipmap/ic_launcher_grey_black"
android:roundIcon="@mipmap/ic_launcher_grey_black"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Blue_grey"
android:enabled="false"
android:icon="@mipmap/ic_launcher_blue_grey"
android:roundIcon="@mipmap/ic_launcher_blue_grey"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Brown"
android:enabled="false"
android:icon="@mipmap/ic_launcher_brown"
android:roundIcon="@mipmap/ic_launcher_brown"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Deep_orange"
android:enabled="false"
android:icon="@mipmap/ic_launcher_deep_orange"
android:roundIcon="@mipmap/ic_launcher_deep_orange"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Orange"
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Amber"
android:enabled="false"
android:icon="@mipmap/ic_launcher_amber"
android:roundIcon="@mipmap/ic_launcher_amber"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Yellow"
android:enabled="false"
android:icon="@mipmap/ic_launcher_yellow"
android:roundIcon="@mipmap/ic_launcher_yellow"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Lime"
android:enabled="false"
android:icon="@mipmap/ic_launcher_lime"
android:roundIcon="@mipmap/ic_launcher_lime"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Light_green"
android:enabled="false"
android:icon="@mipmap/ic_launcher_light_green"
android:roundIcon="@mipmap/ic_launcher_light_green"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Green"
android:enabled="false"
android:icon="@mipmap/ic_launcher_green"
android:roundIcon="@mipmap/ic_launcher_green"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Teal"
android:enabled="false"
android:icon="@mipmap/ic_launcher_teal"
android:roundIcon="@mipmap/ic_launcher_teal"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Cyan"
android:enabled="false"
android:icon="@mipmap/ic_launcher_cyan"
android:roundIcon="@mipmap/ic_launcher_cyan"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Light_blue"
android:enabled="false"
android:icon="@mipmap/ic_launcher_light_blue"
android:roundIcon="@mipmap/ic_launcher_light_blue"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Blue"
android:enabled="false"
android:icon="@mipmap/ic_launcher_blue"
android:roundIcon="@mipmap/ic_launcher_blue"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Indigo"
android:enabled="false"
android:icon="@mipmap/ic_launcher_indigo"
android:roundIcon="@mipmap/ic_launcher_indigo"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Deep_purple"
android:enabled="false"
android:icon="@mipmap/ic_launcher_deep_purple"
android:roundIcon="@mipmap/ic_launcher_deep_purple"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Purple"
android:enabled="false"
android:icon="@mipmap/ic_launcher_purple"
android:roundIcon="@mipmap/ic_launcher_purple"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Pink"
android:enabled="false"
android:icon="@mipmap/ic_launcher_pink"
android:roundIcon="@mipmap/ic_launcher_pink"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Red"
android:enabled="false"
android:icon="@mipmap/ic_launcher_red"
android:roundIcon="@mipmap/ic_launcher_red"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity
android:name=".activities.MainActivity"
android:screenOrientation="portrait" />
<activity
android:name=".activities.WidgetConfigureActivity"
android:screenOrientation="portrait"
@ -32,27 +259,22 @@
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<activity
android:name=".activities.SettingsActivity"
android:label="@string/settings"
android:parentActivityName=".activities.MainActivity" />
<activity
android:name="com.simplemobiletools.commons.activities.AboutActivity"
android:label="@string/about"
android:parentActivityName=".activities.MainActivity" />
<activity
android:name="com.simplemobiletools.commons.activities.LicenseActivity"
android:label="@string/third_party_licences"
android:parentActivityName="com.simplemobiletools.commons.activities.AboutActivity" />
<activity
android:name="com.simplemobiletools.commons.activities.CustomizationActivity"
android:label="@string/customize_colors"
android:parentActivityName=".activities.SettingsActivity" />
<activity
android:name="com.simplemobiletools.commons.activities.FAQActivity"
android:label="@string/frequently_asked_questions"
@ -69,251 +291,6 @@
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>
<activity-alias
android:name=".activities.SplashActivity.Red"
android:enabled="false"
android:icon="@mipmap/ic_launcher_red"
android:roundIcon="@mipmap/ic_launcher_red"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Pink"
android:enabled="false"
android:icon="@mipmap/ic_launcher_pink"
android:roundIcon="@mipmap/ic_launcher_pink"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Purple"
android:enabled="false"
android:icon="@mipmap/ic_launcher_purple"
android:roundIcon="@mipmap/ic_launcher_purple"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Deep_purple"
android:enabled="false"
android:icon="@mipmap/ic_launcher_deep_purple"
android:roundIcon="@mipmap/ic_launcher_deep_purple"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Indigo"
android:enabled="false"
android:icon="@mipmap/ic_launcher_indigo"
android:roundIcon="@mipmap/ic_launcher_indigo"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Blue"
android:enabled="false"
android:icon="@mipmap/ic_launcher_blue"
android:roundIcon="@mipmap/ic_launcher_blue"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Light_blue"
android:enabled="false"
android:icon="@mipmap/ic_launcher_light_blue"
android:roundIcon="@mipmap/ic_launcher_light_blue"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Cyan"
android:enabled="false"
android:icon="@mipmap/ic_launcher_cyan"
android:roundIcon="@mipmap/ic_launcher_cyan"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Teal"
android:enabled="false"
android:icon="@mipmap/ic_launcher_teal"
android:roundIcon="@mipmap/ic_launcher_teal"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Green"
android:enabled="false"
android:icon="@mipmap/ic_launcher_green"
android:roundIcon="@mipmap/ic_launcher_green"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Light_green"
android:enabled="false"
android:icon="@mipmap/ic_launcher_light_green"
android:roundIcon="@mipmap/ic_launcher_light_green"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Lime"
android:enabled="false"
android:icon="@mipmap/ic_launcher_lime"
android:roundIcon="@mipmap/ic_launcher_lime"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Yellow"
android:enabled="false"
android:icon="@mipmap/ic_launcher_yellow"
android:roundIcon="@mipmap/ic_launcher_yellow"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Amber"
android:enabled="false"
android:icon="@mipmap/ic_launcher_amber"
android:roundIcon="@mipmap/ic_launcher_amber"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Orange"
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Deep_orange"
android:enabled="false"
android:icon="@mipmap/ic_launcher_deep_orange"
android:roundIcon="@mipmap/ic_launcher_deep_orange"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Brown"
android:enabled="false"
android:icon="@mipmap/ic_launcher_brown"
android:roundIcon="@mipmap/ic_launcher_brown"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Blue_grey"
android:enabled="false"
android:icon="@mipmap/ic_launcher_blue_grey"
android:roundIcon="@mipmap/ic_launcher_blue_grey"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".activities.SplashActivity.Grey_black"
android:enabled="false"
android:icon="@mipmap/ic_launcher_grey_black"
android:roundIcon="@mipmap/ic_launcher_grey_black"
android:targetActivity=".activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
</application>
</manifest>

View file

@ -7,11 +7,11 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import com.simplemobiletools.calculator.BuildConfig
import com.simplemobiletools.calculator.R
import com.simplemobiletools.calculator.extensions.config
import com.simplemobiletools.calculator.extensions.updateViewColors
import com.simplemobiletools.calculator.helpers.*
import com.simplemobiletools.calculator.BuildConfig
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.LICENSE_AUTOFITTEXTVIEW
import com.simplemobiletools.commons.helpers.LICENSE_ESPRESSO
@ -20,6 +20,7 @@ import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.commons.models.Release
import kotlinx.android.synthetic.main.activity_main.*
import me.grantland.widget.AutofitHelper
import java.math.BigDecimal
class MainActivity : SimpleActivity(), Calculator {
private var storedTextColor = 0
@ -155,8 +156,8 @@ class MainActivity : SimpleActivity(), Calculator {
}
// used only by Robolectric
override fun setValueDouble(d: Double) {
calc.setValue(Formatter.doubleToString(d))
override fun setValueBigDecimal(d: BigDecimal) {
calc.setValue(Formatter.bigDecimalToString(d))
calc.lastKey = DIGIT
}

View file

@ -11,6 +11,7 @@ import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import kotlinx.android.synthetic.main.activity_settings.*
import java.util.*
import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() {
@ -50,7 +51,7 @@ class SettingsActivity : SimpleActivity() {
settings_use_english_holder.setOnClickListener {
settings_use_english.toggle()
config.useEnglish = settings_use_english.isChecked
System.exit(0)
exitProcess(0)
}
}

View file

@ -1,11 +1,12 @@
package com.simplemobiletools.calculator.helpers
import android.content.Context
import java.math.BigDecimal
interface Calculator {
fun setValue(value: String, context: Context)
fun setValueDouble(d: Double)
fun setValueBigDecimal(d: BigDecimal)
fun setFormula(value: String, context: Context)
}

View file

@ -5,6 +5,7 @@ import android.util.Log
import com.simplemobiletools.calculator.R
import com.simplemobiletools.calculator.operation.OperationFactory
import com.simplemobiletools.commons.extensions.toast
import java.math.BigDecimal
class CalculatorImpl(calculator: Calculator, val context: Context) {
var displayedNumber: String? = null
@ -15,8 +16,8 @@ class CalculatorImpl(calculator: Calculator, val context: Context) {
private var isFirstOperation = false
private var resetValue = false
private var baseValue = 0.0
private var secondValue = 0.0
private var baseValue: BigDecimal = BigDecimal.ZERO
private var secondValue: BigDecimal = BigDecimal.ZERO
init {
resetValues()
@ -32,8 +33,8 @@ class CalculatorImpl(calculator: Calculator, val context: Context) {
}
private fun resetValues() {
baseValue = 0.0
secondValue = 0.0
baseValue = BigDecimal.ZERO
secondValue = BigDecimal.ZERO
resetValue = false
lastOperation = ""
displayedNumber = ""
@ -61,7 +62,7 @@ class CalculatorImpl(calculator: Calculator, val context: Context) {
sign == "" -> setFormula(sign + first)
sign == "!" -> setFormula(first + sign)
sign.isNotEmpty() -> {
if (secondValue == 0.0 && sign == "/") {
if (secondValue.compareTo(BigDecimal.ZERO) == 0 && sign == "/") {
context.toast(context.getString(R.string.formula_divide_by_zero_error))
}
@ -83,16 +84,16 @@ class CalculatorImpl(calculator: Calculator, val context: Context) {
return str
}
val doubleValue = Formatter.stringToDouble(str)
val doubleValue = Formatter.stringToBigDecimal(str)
return doubleValue.format()
}
private fun updateResult(value: Double) {
private fun updateResult(value: BigDecimal) {
setValue(value.format())
baseValue = value
}
private fun getDisplayedNumberAsDouble() = Formatter.stringToDouble(displayedNumber!!)
private fun getDisplayedNumberAsDouble() = Formatter.stringToBigDecimal(displayedNumber!!)
fun handleResult() {
secondValue = getDisplayedNumberAsDouble()

View file

@ -1,11 +1,12 @@
package com.simplemobiletools.calculator.helpers
import java.math.BigDecimal
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.*
object Formatter {
fun doubleToString(d: Double): String {
fun bigDecimalToString(d: BigDecimal): String {
val symbols = DecimalFormatSymbols(Locale.US)
symbols.decimalSeparator = '.'
symbols.groupingSeparator = ','
@ -17,7 +18,7 @@ object Formatter {
return formatter.format(d)
}
fun stringToDouble(str: String) = str.replace(",", "").toDouble()
fun stringToBigDecimal(str: String): BigDecimal = BigDecimal(str.replace(",", ""))
}
fun Double.format(): String = Formatter.doubleToString(this)
fun BigDecimal.format(): String = Formatter.bigDecimalToString(this)

View file

@ -12,8 +12,8 @@ import com.simplemobiletools.calculator.R
import com.simplemobiletools.calculator.activities.MainActivity
import com.simplemobiletools.calculator.extensions.config
import com.simplemobiletools.commons.extensions.applyColorFilter
import com.simplemobiletools.commons.extensions.setBackgroundColor
import com.simplemobiletools.commons.extensions.setText
import java.math.BigDecimal
class MyWidgetProvider : AppWidgetProvider(), Calculator {
companion object {
@ -85,8 +85,7 @@ class MyWidgetProvider : AppWidgetProvider(), Calculator {
}
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
when (action) {
when (val action = intent.action) {
DECIMAL, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, EQUALS, CLEAR, RESET, PLUS, MINUS, MULTIPLY, DIVIDE, PERCENT, POWER, ROOT, FACTORIAL -> myAction(action, context)
else -> super.onReceive(context, intent)
}
@ -125,7 +124,7 @@ class MyWidgetProvider : AppWidgetProvider(), Calculator {
}
}
override fun setValueDouble(d: Double) {
override fun setValueBigDecimal(d: BigDecimal) {
}
override fun setFormula(value: String, context: Context) {

View file

@ -2,14 +2,15 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.BinaryOperation
import com.simplemobiletools.calculator.operation.base.Operation
import java.math.BigDecimal
class DivideOperation(baseValue: Double, secondValue: Double) : BinaryOperation(baseValue, secondValue), Operation {
class DivideOperation(baseValue: BigDecimal, secondValue: BigDecimal) : BinaryOperation(baseValue, secondValue), Operation {
override fun getResult(): Double {
var result = 0.0
if (secondValue != 0.0) {
result = baseValue / secondValue
override fun getResult(): BigDecimal {
return if (secondValue.compareTo(BigDecimal.ZERO) == 0) {
BigDecimal.ZERO
} else {
baseValue.divide(secondValue)
}
return result
}
}

View file

@ -2,19 +2,20 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.Operation
import com.simplemobiletools.calculator.operation.base.UnaryOperation
import java.math.BigDecimal
class FactorialOperation(value: Double) : UnaryOperation(value), Operation {
class FactorialOperation(value: BigDecimal) : UnaryOperation(value), Operation {
override fun getResult(): Double{
var result = 1.0
if (value==0.0 || value==1.0){
return result
}else{
var base = value.toInt()
override fun getResult(): BigDecimal {
return if (value.compareTo(BigDecimal.ZERO) == 0 || value.compareTo(BigDecimal.ONE) == 0 ){
BigDecimal.ONE
} else{
var result = BigDecimal.ONE
val base = value.toInt()
for(i in 1..base){
result *= i
result = result.multiply(BigDecimal(i))
}
result
}
return result
}
}

View file

@ -2,8 +2,9 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.BinaryOperation
import com.simplemobiletools.calculator.operation.base.Operation
import java.math.BigDecimal
class MinusOperation(baseValue: Double, secondValue: Double) : BinaryOperation(baseValue, secondValue), Operation {
class MinusOperation(baseValue: BigDecimal, secondValue: BigDecimal) : BinaryOperation(baseValue, secondValue), Operation {
override fun getResult() = baseValue - secondValue
override fun getResult(): BigDecimal = baseValue.subtract(secondValue)
}

View file

@ -2,8 +2,9 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.BinaryOperation
import com.simplemobiletools.calculator.operation.base.Operation
import java.math.BigDecimal
class MultiplyOperation(baseValue: Double, secondValue: Double) : BinaryOperation(baseValue, secondValue), Operation {
class MultiplyOperation(baseValue: BigDecimal, secondValue: BigDecimal) : BinaryOperation(baseValue, secondValue), Operation {
override fun getResult() = baseValue * secondValue
override fun getResult(): BigDecimal = baseValue.multiply(secondValue)
}

View file

@ -2,10 +2,11 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.helpers.*
import com.simplemobiletools.calculator.operation.base.Operation
import java.math.BigDecimal
object OperationFactory {
fun forId(id: String, baseValue: Double, secondValue: Double): Operation? {
fun forId(id: String, baseValue: BigDecimal, secondValue: BigDecimal): Operation? {
return when (id) {
PLUS -> PlusOperation(baseValue, secondValue)
MINUS -> MinusOperation(baseValue, secondValue)

View file

@ -2,14 +2,15 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.BinaryOperation
import com.simplemobiletools.calculator.operation.base.Operation
import java.math.BigDecimal
class PercentOperation(baseValue: Double, secondValue: Double) : BinaryOperation(baseValue, secondValue), Operation {
class PercentOperation(baseValue: BigDecimal, secondValue: BigDecimal) : BinaryOperation(baseValue, secondValue), Operation {
override fun getResult(): Double {
var result = 0.0
if (secondValue != 0.0) {
result = baseValue / 100 * secondValue
override fun getResult(): BigDecimal {
return if (secondValue.compareTo(BigDecimal.ZERO) == 0) {
BigDecimal.ZERO
} else {
baseValue.divide(BigDecimal(100)).multiply(secondValue)
}
return result
}
}

View file

@ -2,8 +2,9 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.BinaryOperation
import com.simplemobiletools.calculator.operation.base.Operation
import java.math.BigDecimal
class PlusOperation(baseValue: Double, secondValue: Double) : BinaryOperation(baseValue, secondValue), Operation {
class PlusOperation(baseValue: BigDecimal, secondValue: BigDecimal) : BinaryOperation(baseValue, secondValue), Operation {
override fun getResult() = baseValue + secondValue
override fun getResult(): BigDecimal = baseValue.add(secondValue)
}

View file

@ -2,13 +2,18 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.BinaryOperation
import com.simplemobiletools.calculator.operation.base.Operation
import java.math.BigDecimal
import kotlin.math.pow
class PowerOperation(baseValue: Double, secondValue: Double) : BinaryOperation(baseValue, secondValue), Operation {
class PowerOperation(baseValue: BigDecimal, secondValue: BigDecimal) : BinaryOperation(baseValue, secondValue), Operation {
override fun getResult(): Double {
var result = Math.pow(baseValue, secondValue)
if (java.lang.Double.isInfinite(result) || java.lang.Double.isNaN(result))
result = 0.0
return result
override fun getResult(): BigDecimal {
val result = baseValue.toDouble().pow(secondValue.toDouble())
return if (java.lang.Double.isInfinite(result) || java.lang.Double.isNaN(result))
BigDecimal.ZERO
else {
BigDecimal(result)
}
}
}

View file

@ -2,8 +2,10 @@ package com.simplemobiletools.calculator.operation
import com.simplemobiletools.calculator.operation.base.Operation
import com.simplemobiletools.calculator.operation.base.UnaryOperation
import java.math.BigDecimal
import kotlin.math.sqrt
class RootOperation(value: Double) : UnaryOperation(value), Operation {
class RootOperation(value: BigDecimal) : UnaryOperation(value), Operation {
override fun getResult() = Math.sqrt(value)
override fun getResult() = BigDecimal(sqrt(value.toDouble()))
}

View file

@ -1,3 +1,5 @@
package com.simplemobiletools.calculator.operation.base
open class BinaryOperation protected constructor(protected var baseValue: Double, protected var secondValue: Double)
import java.math.BigDecimal
open class BinaryOperation protected constructor(protected val baseValue: BigDecimal, protected val secondValue: BigDecimal)

View file

@ -1,5 +1,7 @@
package com.simplemobiletools.calculator.operation.base
import java.math.BigDecimal
interface Operation {
fun getResult(): Double
fun getResult(): BigDecimal
}

View file

@ -1,3 +1,5 @@
package com.simplemobiletools.calculator.operation.base
open class UnaryOperation protected constructor(protected var value: Double)
import java.math.BigDecimal
open class UnaryOperation protected constructor(protected var value: BigDecimal)

View file

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.MainActivity"
tools:context="com.simplemobiletools.calculator.activities.MainActivity"
tools:ignore="HardcodedText">
<TextView

View file

@ -2,13 +2,15 @@ package com.simplemobiletools.calculator
import com.simplemobiletools.calculator.activities.MainActivity
import com.simplemobiletools.calculator.helpers.*
import junit.framework.Assert.assertEquals
import com.simplemobiletools.calculator.BuildConfig
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import java.math.BigDecimal
@RunWith(RobolectricTestRunner::class)
@Config(constants = BuildConfig::class, sdk = [21])
@ -37,35 +39,35 @@ class MainActivityTest {
@Test
fun additionTest() {
val res = calcResult(-1.2, PLUS, 3.4)
val res = calcResult(BigDecimal.valueOf(-1.2), PLUS, BigDecimal.valueOf(3.4))
assertEquals("2.2", res)
checkFormula("-1.2+3.4")
}
@Test
fun subtractionTest() {
val res = calcResult(7.8, MINUS, 2.5)
val res = calcResult(BigDecimal.valueOf(7.8), MINUS, BigDecimal.valueOf(2.5))
assertEquals("5.3", res)
checkFormula("7.8-2.5")
}
@Test
fun multiplyTest() {
val res = calcResult(-3.2, MULTIPLY, 6.6)
val res = calcResult(BigDecimal.valueOf(-3.2), MULTIPLY, BigDecimal.valueOf(6.6))
assertEquals("-21.12", res)
checkFormula("-3.2*6.6")
}
@Test
fun divisionTest() {
val res = calcResult(18.25, DIVIDE, 5.0)
val res = calcResult(BigDecimal.valueOf(18.25), DIVIDE, BigDecimal.valueOf(5.0))
assertEquals("3.65", res)
checkFormula("18.25/5")
}
@Test
fun divisionByZero_returnsZero() {
val res = calcResult(6.0, DIVIDE, 0.0)
val res = calcResult(BigDecimal.valueOf(6.0), DIVIDE, BigDecimal.valueOf(0.0))
assertEquals("0", res)
checkFormula("6/0")
}
@ -79,14 +81,14 @@ class MainActivityTest {
@Test
fun powerTest() {
val res = calcResult(3.0, POWER, 6.0)
val res = calcResult(BigDecimal.valueOf(3.0), POWER, BigDecimal.valueOf(6.0))
assertEquals("729", res)
checkFormula("3^6")
}
@Test
fun rootTest() {
setDouble(16.0)
setBigDecimal(BigDecimal(16.0))
handleOperation(ROOT)
assertEquals("4", getDisplayedNumber())
checkFormula("√16")
@ -94,14 +96,14 @@ class MainActivityTest {
@Test
fun clearBtnSimpleTest() {
setDouble(156.0)
setBigDecimal(BigDecimal(156.0))
activity.calc.handleClear()
assertEquals("15", getDisplayedNumber())
}
@Test
fun clearBtnComplexTest() {
setDouble(-26.0)
setBigDecimal(BigDecimal(-26.0))
activity.calc.handleClear()
assertEquals("-2", getDisplayedNumber())
activity.calc.handleClear()
@ -110,10 +112,10 @@ class MainActivityTest {
@Test
fun clearBtnLongClick_resetsEverything() {
calcResult(-1.2, PLUS, 3.4)
calcResult(BigDecimal.valueOf(-1.2), PLUS, BigDecimal.valueOf(3.4))
activity.calc.handleReset()
handleOperation(PLUS)
setDouble(3.0)
setBigDecimal(BigDecimal.valueOf(3.0))
activity.calc.handleResult()
assertEquals("3", getDisplayedNumber())
checkFormula("")
@ -121,14 +123,14 @@ class MainActivityTest {
@Test
fun complexTest() {
setDouble(-12.2)
setBigDecimal(BigDecimal.valueOf(-12.2))
handleOperation(PLUS)
setDouble(21.0)
setBigDecimal(BigDecimal(21.0))
handleOperation(MINUS)
assertEquals("8.8", getDisplayedNumber())
checkFormula("-12.2+21")
setDouble(1.6)
setBigDecimal(BigDecimal(1.6))
activity.calc.handleEquals()
assertEquals("7.2", getDisplayedNumber())
checkFormula("8.8-1.6")
@ -137,22 +139,22 @@ class MainActivityTest {
checkFormula("7.2-1.6")
handleOperation(MULTIPLY)
setDouble(5.0)
setBigDecimal(BigDecimal(5.0))
handleOperation(DIVIDE)
assertEquals("28", getDisplayedNumber())
checkFormula("5.6*5")
setDouble(4.0)
setBigDecimal(BigDecimal(4.0))
handleOperation(DIVIDE)
assertEquals("7", getDisplayedNumber())
checkFormula("28/4")
setDouble(5.0)
setBigDecimal(BigDecimal(5.0))
handleOperation(POWER)
assertEquals("2", getDisplayedNumber())
checkFormula("7%5")
setDouble(8.0)
setBigDecimal(BigDecimal(8.0))
handleOperation(ROOT)
assertEquals("16", getDisplayedNumber())
checkFormula("√256")
@ -161,8 +163,8 @@ class MainActivityTest {
assertEquals("1", getDisplayedNumber())
}
private fun setDouble(d: Double) {
activity.setValueDouble(d)
private fun setBigDecimal(d: BigDecimal) {
activity.setValueBigDecimal(d)
}
private fun handleOperation(operation: String) {
@ -173,10 +175,10 @@ class MainActivityTest {
assertEquals(desired, activity.calc.displayedFormula)
}
private fun calcResult(baseValue: Double, operation: String, secondValue: Double): String? {
setDouble(baseValue)
private fun calcResult(baseValue: BigDecimal, operation: String, secondValue: BigDecimal): String? {
setBigDecimal(baseValue)
handleOperation(operation)
setDouble(secondValue)
setBigDecimal(secondValue)
activity.calc.handleResult()
return getDisplayedNumber()
}