summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/.gitignore1
-rw-r--r--app/build.gradle.kts60
-rw-r--r--app/proguard-rules.pro21
-rw-r--r--app/release/app-release.apkbin0 -> 692395 bytes
-rw-r--r--app/release/baselineProfiles/0/app-release.dmbin0 -> 3521 bytes
-rw-r--r--app/release/baselineProfiles/1/app-release.dmbin0 -> 3475 bytes
-rw-r--r--app/release/output-metadata.json37
-rw-r--r--app/src/androidTest/java/com/a404m/calculator/ExampleInstrumentedTest.kt27
-rw-r--r--app/src/main/AndroidManifest.xml28
-rw-r--r--app/src/main/ic_launcher-playstore.pngbin0 -> 2688 bytes
-rw-r--r--app/src/main/java/com/a404m/calculator/MainActivity.kt27
-rw-r--r--app/src/main/java/com/a404m/calculator/MathHelper.kt309
-rw-r--r--app/src/main/java/com/a404m/calculator/model/CalcButtonModel.kt139
-rw-r--r--app/src/main/java/com/a404m/calculator/ui/page/Home.kt120
-rw-r--r--app/src/main/java/com/a404m/calculator/ui/theme/Color.kt11
-rw-r--r--app/src/main/java/com/a404m/calculator/ui/theme/Theme.kt58
-rw-r--r--app/src/main/java/com/a404m/calculator/ui/theme/Type.kt34
-rw-r--r--app/src/main/java/com/a404m/calculator/ui/util/Container.kt31
-rw-r--r--app/src/main/res/drawable/ic_launcher_background.xml170
-rw-r--r--app/src/main/res/drawable/ic_launcher_foreground.xml16
-rw-r--r--app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml5
-rw-r--r--app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml5
-rw-r--r--app/src/main/res/mipmap-hdpi/ic_launcher.webpbin0 -> 558 bytes
-rw-r--r--app/src/main/res/mipmap-hdpi/ic_launcher_round.webpbin0 -> 1972 bytes
-rw-r--r--app/src/main/res/mipmap-mdpi/ic_launcher.webpbin0 -> 446 bytes
-rw-r--r--app/src/main/res/mipmap-mdpi/ic_launcher_round.webpbin0 -> 1156 bytes
-rw-r--r--app/src/main/res/mipmap-xhdpi/ic_launcher.webpbin0 -> 702 bytes
-rw-r--r--app/src/main/res/mipmap-xhdpi/ic_launcher_round.webpbin0 -> 2746 bytes
-rw-r--r--app/src/main/res/mipmap-xxhdpi/ic_launcher.webpbin0 -> 944 bytes
-rw-r--r--app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webpbin0 -> 4174 bytes
-rw-r--r--app/src/main/res/mipmap-xxxhdpi/ic_launcher.webpbin0 -> 1266 bytes
-rw-r--r--app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webpbin0 -> 5964 bytes
-rw-r--r--app/src/main/res/values/colors.xml10
-rw-r--r--app/src/main/res/values/ic_launcher_background.xml4
-rw-r--r--app/src/main/res/values/strings.xml3
-rw-r--r--app/src/main/res/values/themes.xml5
-rw-r--r--app/src/main/res/xml/backup_rules.xml13
-rw-r--r--app/src/main/res/xml/data_extraction_rules.xml19
-rw-r--r--app/src/test/java/com/a404m/calculator/ExampleUnitTest.kt20
39 files changed, 1173 insertions, 0 deletions
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build \ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..6848831
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,60 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+ alias(libs.plugins.kotlin.compose)
+}
+
+android {
+ namespace = "com.a404m.calculator"
+ compileSdk = 35
+
+ defaultConfig {
+ applicationId = "com.a404m.calculator"
+ minSdk = 21
+ targetSdk = 35
+ versionCode = 2
+ versionName = "0.1.0"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = true
+ isShrinkResources = true
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+ kotlinOptions {
+ jvmTarget = "11"
+ }
+ buildFeatures {
+ compose = true
+ }
+}
+
+dependencies {
+
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.lifecycle.runtime.ktx)
+ implementation(libs.androidx.activity.compose)
+ implementation(platform(libs.androidx.compose.bom))
+ implementation(libs.androidx.ui)
+ implementation(libs.androidx.ui.graphics)
+ implementation(libs.androidx.ui.tooling.preview)
+ implementation(libs.androidx.material3)
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.junit)
+ androidTestImplementation(libs.androidx.espresso.core)
+ androidTestImplementation(platform(libs.androidx.compose.bom))
+ androidTestImplementation(libs.androidx.ui.test.junit4)
+ debugImplementation(libs.androidx.ui.tooling)
+ debugImplementation(libs.androidx.ui.test.manifest)
+} \ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile \ No newline at end of file
diff --git a/app/release/app-release.apk b/app/release/app-release.apk
new file mode 100644
index 0000000..4763c61
--- /dev/null
+++ b/app/release/app-release.apk
Binary files differ
diff --git a/app/release/baselineProfiles/0/app-release.dm b/app/release/baselineProfiles/0/app-release.dm
new file mode 100644
index 0000000..2df2b65
--- /dev/null
+++ b/app/release/baselineProfiles/0/app-release.dm
Binary files differ
diff --git a/app/release/baselineProfiles/1/app-release.dm b/app/release/baselineProfiles/1/app-release.dm
new file mode 100644
index 0000000..829ee1a
--- /dev/null
+++ b/app/release/baselineProfiles/1/app-release.dm
Binary files differ
diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json
new file mode 100644
index 0000000..4b3565e
--- /dev/null
+++ b/app/release/output-metadata.json
@@ -0,0 +1,37 @@
+{
+ "version": 3,
+ "artifactType": {
+ "type": "APK",
+ "kind": "Directory"
+ },
+ "applicationId": "com.a404m.calculator",
+ "variantName": "release",
+ "elements": [
+ {
+ "type": "SINGLE",
+ "filters": [],
+ "attributes": [],
+ "versionCode": 2,
+ "versionName": "0.1.0",
+ "outputFile": "app-release.apk"
+ }
+ ],
+ "elementType": "File",
+ "baselineProfiles": [
+ {
+ "minApi": 28,
+ "maxApi": 30,
+ "baselineProfiles": [
+ "baselineProfiles/1/app-release.dm"
+ ]
+ },
+ {
+ "minApi": 31,
+ "maxApi": 2147483647,
+ "baselineProfiles": [
+ "baselineProfiles/0/app-release.dm"
+ ]
+ }
+ ],
+ "minSdkVersionForDexing": 21
+} \ No newline at end of file
diff --git a/app/src/androidTest/java/com/a404m/calculator/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/a404m/calculator/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..785fe9a
--- /dev/null
+++ b/app/src/androidTest/java/com/a404m/calculator/ExampleInstrumentedTest.kt
@@ -0,0 +1,27 @@
+package com.a404m.calculator
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals(
+ "com.a404m.calculator",
+ appContext.packageName
+ )
+ }
+} \ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8d7bca4
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <application
+ android:allowBackup="true"
+ android:dataExtractionRules="@xml/data_extraction_rules"
+ android:fullBackupContent="@xml/backup_rules"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/Theme.Calculator"
+ tools:targetApi="31">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.Calculator">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
new file mode 100644
index 0000000..2d94637
--- /dev/null
+++ b/app/src/main/ic_launcher-playstore.png
Binary files differ
diff --git a/app/src/main/java/com/a404m/calculator/MainActivity.kt b/app/src/main/java/com/a404m/calculator/MainActivity.kt
new file mode 100644
index 0000000..9a40e9b
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/MainActivity.kt
@@ -0,0 +1,27 @@
+package com.a404m.calculator
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import com.a404m.calculator.ui.page.HomePage
+import com.a404m.calculator.ui.theme.CalculatorTheme
+
+class MainActivity : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ setContent {
+ CalculatorTheme {
+ HomePage()
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/com/a404m/calculator/MathHelper.kt b/app/src/main/java/com/a404m/calculator/MathHelper.kt
new file mode 100644
index 0000000..fa6cfc7
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/MathHelper.kt
@@ -0,0 +1,309 @@
+package com.a404m.calculator
+
+import android.util.Log
+import com.a404m.calculator.MathHelper.Operator.Kind
+import java.nio.charset.UnsupportedCharsetException
+
+object MathHelper {
+ private val operatorStrings = arrayOf(
+ '+',
+ '-',
+ '×',
+ '÷',
+ '%',
+ )
+ private val numberStrings = arrayOf(
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ '.',
+ )
+
+ private val plus = Operator(
+ '+',
+ Kind.PREFIX,
+ {
+ Operand(it.first().value)
+ }
+ )
+ private val minus = Operator(
+ '-',
+ Kind.PREFIX,
+ {
+ Operand(-it.first().value)
+ }
+ )
+ private val add = Operator(
+ '+',
+ Kind.INFIX,
+ {
+ Operand(it.first().value+it.last().value)
+ }
+ )
+ private val sub = Operator(
+ '-',
+ Kind.INFIX,
+ {
+ Operand(it.first().value-it.last().value)
+ }
+ )
+ private val mul = Operator(
+ '×',
+ Kind.INFIX,
+ {
+ Operand(it.first().value*it.last().value)
+ }
+ )
+ private val div = Operator(
+ '÷',
+ Kind.INFIX,
+ {
+ Operand(it.first().value/it.last().value)
+ }
+ )
+ private val rem = Operator(
+ '%',
+ Kind.INFIX,
+ {
+ Operand(it.first().value%it.last().value)
+ }
+ )
+ private val operatorOrders = arrayOf(
+ arrayOf(
+ plus,
+ minus,
+ ),
+ arrayOf(
+ mul,
+ div,
+ rem,
+ ),
+ arrayOf(
+ add,
+ sub,
+ )
+ )
+ private val operators = arrayOf(
+ plus,
+ minus,
+ add,
+ sub,
+ mul,
+ div,
+ rem,
+ )
+
+ fun eval(expression: String): String {
+ return try {
+ parse(lex(expression)).eval().toString()
+ } catch (e: Exception) {
+ e.message ?: "Exception"
+ }
+ }
+
+ private fun parse(lexed: ArrayList<Any>): Operator {
+ for (order in operatorOrders) {
+ if (lexed.size == 1) {
+ break
+ }
+ for (i in lexed.indices) {
+ val item = lexed[i]
+ if (item is BasicOperator) {
+ var op = item.toOperator(
+ lexed,
+ i
+ )
+ if (op in order) {
+ op = op.cloneWithoutOperands()
+ Log.d(
+ "A404M",
+ "parse: $op"
+ )
+ lexed[i] = op
+ when (op.kind) {
+ Kind.NONE -> {}
+ Kind.INFIX -> {
+ op.operands.add(lexed.removeAt(i - 1))
+ op.operands.add(lexed.removeAt(i))
+ }
+
+ Kind.PREFIX -> {
+ op.operands.add(lexed.removeAt(i + 1))
+ }
+
+ Kind.POSTFIX -> {
+ op.operands.add(lexed.removeAt(i - 1))
+ }
+ }
+ break
+ }
+ }
+ }
+ }
+ return if (lexed.size != 1) {
+ throw UnsupportedOperationException("lexed.size = ${lexed.size}: $lexed")
+ } else if (lexed.first() is Operator) {
+ lexed.first() as Operator
+ } else if (lexed.first() is Operand) {
+ plus.cloneWithoutOperands().cloneWithOperator(arrayListOf(lexed.first()))
+ } else {
+ throw UnsupportedOperationException("unsupported type ${lexed.first().javaClass}")
+ }
+ }
+
+ private fun lex(expression: String): ArrayList<Any> {
+ val items = arrayListOf<Any>()
+
+ var i = 0
+ while (i < expression.length) {
+ when (val c = expression[i]) {
+ in numberStrings -> {
+ val start = i
+ while (++i < expression.length && expression[i] in numberStrings);
+ items.add(
+ Operand(
+ value = expression.substring(
+ start,
+ i
+ ).toDouble()
+ )
+ )
+ --i
+ }
+
+ in operatorStrings -> {
+ items.add(
+ BasicOperator(c)
+ )
+ }
+
+ else -> throw UnsupportedCharsetException(c.toString())
+ }
+ ++i
+ }
+
+ return items
+ }
+
+ private class Operator(
+ val operator: Char,
+ val kind: Kind,
+ val operate: (operands:List<Operand>)->Operand,
+ val operands: ArrayList<Any> = arrayListOf(),
+ ) {
+ fun cloneWithoutOperands():Operator{
+ return Operator(
+ operator,
+ kind,
+ operate,
+ )
+ }
+
+ fun cloneWithOperator(operands: ArrayList<Any>): Operator {
+ return Operator(
+ operator,
+ kind,
+ operate,
+ operands,
+ )
+ }
+
+ fun eval(): Operand {
+ Log.d(
+ "A404M",
+ "eval: $operator $operands"
+ )
+ if(operandSize() != operands.size){
+ throw UnsupportedOperationException("Not enough operands")
+ }
+
+ val evaledOperands = operands.map {
+ if(it is Operator){
+ it.eval()
+ }else{
+ it as Operand
+ }
+ }
+
+ return operate(evaledOperands)
+ }
+
+ fun operandSize(): Int {
+ return when (kind) {
+ Kind.INFIX -> 2
+ Kind.PREFIX, Kind.POSTFIX -> 1
+ Kind.NONE -> 0
+ }
+ }
+
+ override fun toString(): String {
+ return "$operator $kind $operands"
+ }
+
+ enum class Kind {
+ NONE,
+ INFIX,
+ PREFIX,
+ POSTFIX,
+ }
+ }
+
+ private class BasicOperator(
+ val operator: Char,
+ ) {
+ fun toOperator(
+ items: List<Any>,
+ i: Int
+ ): Operator {
+ val left = items.getOrElse(
+ i - 1,
+ { Any() },
+ ) is Operand
+
+ val right = items.getOrElse(
+ i + 1,
+ { Any() },
+ ) is Operand
+
+ val k:Kind
+
+ if (left) {
+ if (right) {
+ k = Kind.INFIX
+ } else {
+ k = Kind.POSTFIX
+ }
+ } else if (right) {
+ k = Kind.PREFIX
+ } else {
+ k = Kind.NONE
+ }
+
+ return operators.first {
+ it.operator == operator && it.kind == k
+ }
+ }
+
+ override fun toString(): String {
+ return operator.toString();
+ }
+ }
+
+ private class Operand(
+ val value: Double,
+ ){
+ override fun toString(): String {
+ if(value % 1 == 0.0){
+ return "%.0f".format(value)
+ }
+ return value.toString()
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/com/a404m/calculator/model/CalcButtonModel.kt b/app/src/main/java/com/a404m/calculator/model/CalcButtonModel.kt
new file mode 100644
index 0000000..435acef
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/model/CalcButtonModel.kt
@@ -0,0 +1,139 @@
+package com.a404m.calculator.model
+
+import com.a404m.calculator.MathHelper
+
+data class CalcButtonModel(
+ val text: String,
+ val weight:Float = 1F,
+ val op: (expression: String) -> String,
+) {
+ companion object {
+ val K_0 = CalcButtonModel(
+ text = "0",
+ op = {
+ it + '0'
+ }
+ )
+ val K_1 = CalcButtonModel(
+ text = "1",
+ op = {
+ it + '1'
+ }
+ )
+ val K_2 = CalcButtonModel(
+ text = "2",
+ op = {
+ it + '2'
+ }
+ )
+ val K_3 = CalcButtonModel(
+ text = "3",
+ op = {
+ it + '3'
+ }
+ )
+ val K_4 = CalcButtonModel(
+ text = "4",
+ op = {
+ it + '4'
+ }
+ )
+ val K_5 = CalcButtonModel(
+ text = "5",
+ op = {
+ it + '5'
+ }
+ )
+ val K_6 = CalcButtonModel(
+ text = "6",
+ op = {
+ it + '6'
+ }
+ )
+ val K_7 = CalcButtonModel(
+ text = "7",
+ op = {
+ it + '7'
+ }
+ )
+ val K_8 = CalcButtonModel(
+ text = "8",
+ op = {
+ it + '8'
+ }
+ )
+ val K_9 = CalcButtonModel(
+ text = "9",
+ op = {
+ it + '9'
+ }
+ )
+ val K_PLUS = CalcButtonModel(
+ text = "+",
+ op = {
+ it + '+'
+ }
+ )
+ val K_MINUS = CalcButtonModel(
+ text = "-",
+ op = {
+ it + '-'
+ }
+ )
+ val K_MULTIPLY = CalcButtonModel(
+ text = "×",
+ op = {
+ it + '×'
+ }
+ )
+ val K_DIVISION = CalcButtonModel(
+ text = "÷",
+ op = {
+ it + '÷'
+ }
+ )
+ val K_REMINDER = CalcButtonModel(
+ text = "%",
+ op = {
+ it + '%'
+ }
+ )
+ val K_EQUAL = CalcButtonModel(
+ text = "=",
+ op = {
+ MathHelper.eval(it)
+ }
+ )
+ val K_DOT = CalcButtonModel(
+ text = ".",
+ op = {
+ it + '.'
+ }
+ )
+ val K_C = CalcButtonModel(
+ text = "C",
+ op = {
+ ""
+ }
+ )
+ val K_BACKSPACE = CalcButtonModel(
+ text = "⌫",
+ op = {
+ if (it.length <= 1) {
+ ""
+ } else {
+ it.substring(
+ 0,
+ it.length - 1,
+ )
+ }
+ }
+ )
+ val K_SWITCH_MODE = CalcButtonModel(
+ text = "\u2026",
+ op = {
+ it
+ }
+ )
+ }
+}
diff --git a/app/src/main/java/com/a404m/calculator/ui/page/Home.kt b/app/src/main/java/com/a404m/calculator/ui/page/Home.kt
new file mode 100644
index 0000000..ba9a21e
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/ui/page/Home.kt
@@ -0,0 +1,120 @@
+package com.a404m.calculator.ui.page
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.contentColorFor
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.a404m.calculator.model.CalcButtonModel
+import com.a404m.calculator.ui.theme.CalculatorTheme
+import com.a404m.calculator.ui.util.CalcGrid
+
+@Composable
+fun HomePage(modifier: Modifier = Modifier) {
+ var expression by rememberSaveable {
+ mutableStateOf("")
+ }
+ Scaffold(
+ modifier = modifier,
+ ) { paddingValues ->
+ Column(
+ modifier = Modifier
+ .padding(paddingValues)
+ .fillMaxSize(),
+ verticalArrangement = Arrangement.Bottom,
+ ) {
+ Text(
+ modifier = Modifier.padding(8.dp).fillMaxWidth(),
+ text = expression,
+ style = MaterialTheme.typography.titleLarge,
+ textAlign = TextAlign.Right,
+ fontSize = 35.sp,
+ )
+ HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp))
+ CalcGrid(
+ modifier = Modifier
+ .padding(4.dp),
+ columns = 4,
+ items = arrayOf(
+ CalcButtonModel.K_C,
+ CalcButtonModel.K_BACKSPACE,
+ CalcButtonModel.K_REMINDER,
+ CalcButtonModel.K_DIVISION,
+ CalcButtonModel.K_7,
+ CalcButtonModel.K_8,
+ CalcButtonModel.K_9,
+ CalcButtonModel.K_MULTIPLY,
+ CalcButtonModel.K_4,
+ CalcButtonModel.K_5,
+ CalcButtonModel.K_6,
+ CalcButtonModel.K_MINUS,
+ CalcButtonModel.K_1,
+ CalcButtonModel.K_2,
+ CalcButtonModel.K_3,
+ CalcButtonModel.K_PLUS,
+ CalcButtonModel.K_0,
+ CalcButtonModel.K_DOT,
+ CalcButtonModel.K_SWITCH_MODE,
+ CalcButtonModel.K_EQUAL,
+ ),
+ ) {
+ val backColor = MaterialTheme.colorScheme.primary
+ Box(
+ modifier = Modifier
+ .padding(4.dp)
+ .height(70.dp)
+ .weight(it.weight)
+ .clip(
+ shape = RoundedCornerShape(10.dp),
+ )
+ .background(
+ color = backColor,
+ shape = RoundedCornerShape(10.dp),
+ )
+ .clickable {
+ expression = it.op(expression)
+ },
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = it.text,
+ style = MaterialTheme.typography.titleLarge,
+ color = MaterialTheme.colorScheme.contentColorFor(backColor)
+ )
+ }
+ }
+ }
+ }
+}
+
+@Preview
+@Composable
+private fun HomePagePreview() {
+ CalculatorTheme {
+ HomePage(
+ modifier = Modifier.fillMaxSize(),
+ )
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/com/a404m/calculator/ui/theme/Color.kt b/app/src/main/java/com/a404m/calculator/ui/theme/Color.kt
new file mode 100644
index 0000000..6a4fd22
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/ui/theme/Color.kt
@@ -0,0 +1,11 @@
+package com.a404m.calculator.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val Purple80 = Color(0xFFD0BCFF)
+val PurpleGrey80 = Color(0xFFCCC2DC)
+val Pink80 = Color(0xFFEFB8C8)
+
+val Purple40 = Color(0xFF6650a4)
+val PurpleGrey40 = Color(0xFF625b71)
+val Pink40 = Color(0xFF7D5260) \ No newline at end of file
diff --git a/app/src/main/java/com/a404m/calculator/ui/theme/Theme.kt b/app/src/main/java/com/a404m/calculator/ui/theme/Theme.kt
new file mode 100644
index 0000000..20d6120
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/ui/theme/Theme.kt
@@ -0,0 +1,58 @@
+package com.a404m.calculator.ui.theme
+
+import android.app.Activity
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+
+private val DarkColorScheme = darkColorScheme(
+ primary = Purple80,
+ secondary = PurpleGrey80,
+ tertiary = Pink80
+)
+
+private val LightColorScheme = lightColorScheme(
+ primary = Purple40,
+ secondary = PurpleGrey40,
+ tertiary = Pink40
+
+ /* Other default colors to override
+ background = Color(0xFFFFFBFE),
+ surface = Color(0xFFFFFBFE),
+ onPrimary = Color.White,
+ onSecondary = Color.White,
+ onTertiary = Color.White,
+ onBackground = Color(0xFF1C1B1F),
+ onSurface = Color(0xFF1C1B1F),
+ */
+)
+
+@Composable
+fun CalculatorTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ // Dynamic color is available on Android 12+
+ dynamicColor: Boolean = true,
+ content: @Composable () -> Unit
+) {
+ val colorScheme = when {
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+ val context = LocalContext.current
+ if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+ }
+
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content
+ )
+} \ No newline at end of file
diff --git a/app/src/main/java/com/a404m/calculator/ui/theme/Type.kt b/app/src/main/java/com/a404m/calculator/ui/theme/Type.kt
new file mode 100644
index 0000000..42ec494
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/ui/theme/Type.kt
@@ -0,0 +1,34 @@
+package com.a404m.calculator.ui.theme
+
+import androidx.compose.material3.Typography
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Set of Material typography styles to start with
+val Typography = Typography(
+ bodyLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp
+ )
+ /* Other default text styles to override
+ titleLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 22.sp,
+ lineHeight = 28.sp,
+ letterSpacing = 0.sp
+ ),
+ labelSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 11.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ )
+ */
+) \ No newline at end of file
diff --git a/app/src/main/java/com/a404m/calculator/ui/util/Container.kt b/app/src/main/java/com/a404m/calculator/ui/util/Container.kt
new file mode 100644
index 0000000..ba27afe
--- /dev/null
+++ b/app/src/main/java/com/a404m/calculator/ui/util/Container.kt
@@ -0,0 +1,31 @@
+package com.a404m.calculator.ui.util
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+
+@Composable
+fun <T> CalcGrid(
+ modifier: Modifier = Modifier,
+ columns: Int,
+ items: Array<T>,
+ builder: @Composable (T) -> Unit,
+) {
+ Column(
+ modifier = modifier,
+ ) {
+ var index = 0
+ while (index != items.size) {
+ Row {
+ for (j in 0 until columns) {
+ if(index == items.size){
+ break
+ }
+ builder(items[index])
+ ++index
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:fillColor="#3DDC84"
+ android:pathData="M0,0h108v108h-108z" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M9,0L9,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,0L19,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,0L29,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,0L39,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,0L49,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,0L59,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,0L69,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,0L79,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M89,0L89,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M99,0L99,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,9L108,9"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,19L108,19"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,29L108,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,39L108,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,49L108,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,59L108,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,69L108,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,79L108,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,89L108,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,99L108,99"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,29L89,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,39L89,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,49L89,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,59L89,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,69L89,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,79L89,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,19L29,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,19L39,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,19L49,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,19L59,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,19L69,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,19L79,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c5eec94
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="87"
+ android:viewportHeight="167.625">
+ <group android:scaleX="0.23874721"
+ android:scaleY="0.46"
+ android:translateX="33.1145"
+ android:translateY="45.25875">
+ <group android:translateY="133.66406">
+ <path android:pathData="M6.1875,-36.84375L80.515625,-36.84375L80.515625,-24.75L6.1875,-24.75L6.1875,-36.84375ZM6.1875,-65.390625L80.515625,-65.390625L80.515625,-53.4375L6.1875,-53.4375L6.1875,-65.390625Z"
+ android:fillColor="#A437DB"/>
+ </group>
+ </group>
+</vector> \ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..7353dbd
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/ic_launcher_background"/>
+ <foreground android:drawable="@drawable/ic_launcher_foreground"/>
+</adaptive-icon> \ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..7353dbd
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/ic_launcher_background"/>
+ <foreground android:drawable="@drawable/ic_launcher_foreground"/>
+</adaptive-icon> \ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000..ee62035
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..6452b49
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000..8f60d53
--- /dev/null
+++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..3cd3848
--- /dev/null
+++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000..9cb323b
--- /dev/null
+++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..6941df4
--- /dev/null
+++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..eb514e1
--- /dev/null
+++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..749d7c1
--- /dev/null
+++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..e404ad0
--- /dev/null
+++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Binary files differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..f7f408b
--- /dev/null
+++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Binary files differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="purple_200">#FFBB86FC</color>
+ <color name="purple_500">#FF6200EE</color>
+ <color name="purple_700">#FF3700B3</color>
+ <color name="teal_200">#FF03DAC5</color>
+ <color name="teal_700">#FF018786</color>
+ <color name="black">#FF000000</color>
+ <color name="white">#FFFFFFFF</color>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..3376515
--- /dev/null
+++ b/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="ic_launcher_background">#35185A</color>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..665ca8d
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">Calculator</string>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..f244678
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="Theme.Calculator" parent="android:Theme.Material.Light.NoActionBar" />
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000..fa0f996
--- /dev/null
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Sample backup rules file; uncomment and customize as necessary.
+ See https://developer.android.com/guide/topics/data/autobackup
+ for details.
+ Note: This file is ignored for devices older that API 31
+ See https://developer.android.com/about/versions/12/backup-restore
+-->
+<full-backup-content>
+ <!--
+ <include domain="sharedpref" path="."/>
+ <exclude domain="sharedpref" path="device.xml"/>
+-->
+</full-backup-content> \ No newline at end of file
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000..9ee9997
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Sample data extraction rules file; uncomment and customize as necessary.
+ See https://developer.android.com/about/versions/12/backup-restore#xml-changes
+ for details.
+-->
+<data-extraction-rules>
+ <cloud-backup>
+ <!-- TODO: Use <include> and <exclude> to control what is backed up.
+ <include .../>
+ <exclude .../>
+ -->
+ </cloud-backup>
+ <!--
+ <device-transfer>
+ <include .../>
+ <exclude .../>
+ </device-transfer>
+ -->
+</data-extraction-rules> \ No newline at end of file
diff --git a/app/src/test/java/com/a404m/calculator/ExampleUnitTest.kt b/app/src/test/java/com/a404m/calculator/ExampleUnitTest.kt
new file mode 100644
index 0000000..4e8caf3
--- /dev/null
+++ b/app/src/test/java/com/a404m/calculator/ExampleUnitTest.kt
@@ -0,0 +1,20 @@
+package com.a404m.calculator
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(
+ 4,
+ 2 + 2
+ )
+ }
+} \ No newline at end of file