From 387f10b9204b75f64c0a41c93a9adff3c094682d Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Tue, 28 Feb 2023 20:57:21 +0700 Subject: [PATCH] All done --- .gitignore | 1 + .idea/.gitignore | 3 + .idea/.name | 1 + .idea/compiler.xml | 6 + .idea/deploymentTargetDropDown.xml | 17 ++ .idea/gradle.xml | 19 ++ .idea/misc.xml | 10 + .idea/vcs.xml | 6 + app/.gitignore | 1 + app/build.gradle | 70 +++++++ app/proguard-rules.pro | 21 ++ .../nuark/pomslab1/ExampleInstrumentedTest.kt | 24 +++ app/src/main/AndroidManifest.xml | 59 ++++++ app/src/main/ic_launcher-playstore.png | Bin 0 -> 12410 bytes .../main/java/xyz/nuark/pomslab1/PomsApp.kt | 25 +++ .../pomslab1/model/data/CalculationRecord.kt | 12 ++ .../model/data/QuadraticEquationModel.kt | 61 ++++++ .../xyz/nuark/pomslab1/model/data/SumModel.kt | 45 +++++ .../model/interfaces/CalculationRecordDao.kt | 20 ++ .../nuark/pomslab1/model/repo/AppDatabase.kt | 14 ++ .../xyz/nuark/pomslab1/services/HeavyTask.kt | 88 +++++++++ .../nuark/pomslab1/utils/RoomConverters.kt | 16 ++ .../view/activities/GraphicsActivity.kt | 54 +++++ .../view/activities/LinkerActivity.kt | 36 ++++ .../pomslab1/view/activities/MainActivity.kt | 96 +++++++++ .../view/activities/ResultActivity.kt | 33 ++++ .../activities/ServiceCommunicatorActivity.kt | 146 ++++++++++++++ .../view/activities/SwitcherActivity.kt | 78 ++++++++ .../adapters/CalculationHistoryAdapter.kt | 58 ++++++ .../view/fragments/QuadraticFragment.kt | 36 ++++ .../pomslab1/view/fragments/SumFragment.kt | 36 ++++ .../QuadraticCalculationViewModel.kt | 23 +++ .../viewmodels/ResultActivityViewModel.kt | 10 + .../viewmodels/SumCalculationViewModel.kt | 23 +++ .../res/drawable/baseline_play_arrow_24.xml | 5 + .../main/res/drawable/baseline_stop_24.xml | 5 + .../res/drawable/ic_launcher_background.xml | 10 + .../res/drawable/ic_launcher_foreground.xml | 22 +++ .../main/res/layout-land/activity_main.xml | 49 +++++ .../res/layout-land/fragment_quadratic.xml | 112 +++++++++++ app/src/main/res/layout-land/fragment_sum.xml | 99 ++++++++++ .../main/res/layout-sw600dp/activity_main.xml | 60 ++++++ .../res/layout-sw600dp/fragment_quadratic.xml | 111 +++++++++++ .../main/res/layout-sw600dp/fragment_sum.xml | 98 ++++++++++ app/src/main/res/layout/activity_graphics.xml | 79 ++++++++ app/src/main/res/layout/activity_linker.xml | 61 ++++++ app/src/main/res/layout/activity_main.xml | 49 +++++ app/src/main/res/layout/activity_result.xml | 45 +++++ .../layout/activity_service_communicator.xml | 164 ++++++++++++++++ app/src/main/res/layout/activity_switcher.xml | 19 ++ .../res/layout/calculation_history_item.xml | 80 ++++++++ .../main/res/layout/fragment_quadratic.xml | 113 +++++++++++ app/src/main/res/layout/fragment_sum.xml | 97 +++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1504 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3429 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1102 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2167 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2141 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4903 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3173 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 7634 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 4526 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 11285 bytes app/src/main/res/raw/shining_tractor.png | Bin 0 -> 421682 bytes app/src/main/res/values-night/themes.xml | 16 ++ app/src/main/res/values-ru/strings.xml | 37 ++++ app/src/main/res/values/colors.xml | 12 ++ .../res/values/ic_launcher_background.xml | 4 + app/src/main/res/values/strings.xml | 40 ++++ app/src/main/res/values/themes.xml | 16 ++ app/src/main/res/xml/backup_rules.xml | 13 ++ .../main/res/xml/data_extraction_rules.xml | 19 ++ .../xyz/nuark/pomslab1/ExampleUnitTest.kt | 17 ++ build.gradle | 6 + gradle.properties | 4 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 ++++++++++++++++++ gradlew.bat | 89 +++++++++ settings.gradle | 16 ++ 82 files changed, 2916 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/xyz/nuark/pomslab1/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/java/xyz/nuark/pomslab1/PomsApp.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/model/data/CalculationRecord.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/model/data/QuadraticEquationModel.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/model/data/SumModel.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/model/interfaces/CalculationRecordDao.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/model/repo/AppDatabase.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/services/HeavyTask.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/utils/RoomConverters.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/activities/GraphicsActivity.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/activities/LinkerActivity.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/activities/MainActivity.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/activities/ResultActivity.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/activities/ServiceCommunicatorActivity.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/activities/SwitcherActivity.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/adapters/CalculationHistoryAdapter.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/fragments/QuadraticFragment.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/view/fragments/SumFragment.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/viewmodels/QuadraticCalculationViewModel.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/viewmodels/ResultActivityViewModel.kt create mode 100644 app/src/main/java/xyz/nuark/pomslab1/viewmodels/SumCalculationViewModel.kt create mode 100644 app/src/main/res/drawable/baseline_play_arrow_24.xml create mode 100644 app/src/main/res/drawable/baseline_stop_24.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 app/src/main/res/layout-land/activity_main.xml create mode 100644 app/src/main/res/layout-land/fragment_quadratic.xml create mode 100644 app/src/main/res/layout-land/fragment_sum.xml create mode 100644 app/src/main/res/layout-sw600dp/activity_main.xml create mode 100644 app/src/main/res/layout-sw600dp/fragment_quadratic.xml create mode 100644 app/src/main/res/layout-sw600dp/fragment_sum.xml create mode 100644 app/src/main/res/layout/activity_graphics.xml create mode 100644 app/src/main/res/layout/activity_linker.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/activity_result.xml create mode 100644 app/src/main/res/layout/activity_service_communicator.xml create mode 100644 app/src/main/res/layout/activity_switcher.xml create mode 100644 app/src/main/res/layout/calculation_history_item.xml create mode 100644 app/src/main/res/layout/fragment_quadratic.xml create mode 100644 app/src/main/res/layout/fragment_sum.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/raw/shining_tractor.png create mode 100644 app/src/main/res/values-night/themes.xml create mode 100644 app/src/main/res/values-ru/strings.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/ic_launcher_background.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/main/res/xml/backup_rules.xml create mode 100644 app/src/main/res/xml/data_extraction_rules.xml create mode 100644 app/src/test/java/xyz/nuark/pomslab1/ExampleUnitTest.kt create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore index 935e026..987bfe3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.iml .gradle /local.properties +/app/signing.properties /.idea/caches /.idea/libraries /.idea/modules.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..50c98fc --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Poms Lab 1 \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..46b5ae0 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..a2d7c21 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..54d5acd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file 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 b/app/build.gradle new file mode 100644 index 0000000..587a4c0 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,70 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' +} + +android { + namespace 'xyz.nuark.pomslab1' + compileSdk 33 + + defaultConfig { + applicationId "xyz.nuark.pomslab1" + minSdk 24 + targetSdk 33 + versionCode 1 + versionName "1.0" + + vectorDrawables.useSupportLibrary = true + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + signingConfigs { + release { + def props = new Properties() + file("signing.properties").withInputStream { props.load(it) } + + storeFile file(props.RELEASE_STORE_FILE) + storePassword props.RELEASE_STORE_PASSWORD + keyAlias props.RELEASE_KEY_ALIAS + keyPassword props.RELEASE_KEY_PASSWORD + + v1SigningEnabled true + v2SigningEnabled true + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + buildFeatures { + viewBinding true + dataBinding true + } +} + +dependencies { + implementation 'androidx.core:core-ktx:1.9.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.8.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation "androidx.activity:activity-ktx:1.6.1" + implementation "androidx.fragment:fragment-ktx:1.5.5" + implementation "androidx.room:room-runtime:2.5.0" + annotationProcessor "androidx.room:room-compiler:2.5.0" + kapt "androidx.room:room-compiler:2.5.0" + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' +} \ 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/src/androidTest/java/xyz/nuark/pomslab1/ExampleInstrumentedTest.kt b/app/src/androidTest/java/xyz/nuark/pomslab1/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..cc178ed --- /dev/null +++ b/app/src/androidTest/java/xyz/nuark/pomslab1/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package xyz.nuark.pomslab1 + +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("xyz.nuark.pomslab1", 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..5b569ff --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 0000000000000000000000000000000000000000..2d20878b5bd030c999f2d74d129c681236bfe506 GIT binary patch literal 12410 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 + get() { + if (!ok) { + return emptyArray() + } + val _a = a!! + val _b = b!! + val _c = c!! + val d = _b * _b - 4 * _a * _c + if (d < 0) { + return emptyArray() + } + val x1 = (-_b + sqrt(d)) / (2 * _a) + val x2 = (-_b - sqrt(d)) / (2 * _a) + return arrayOf(x1, x2) + } + + fun setAV(v: String) { + a = v.toDoubleOrNull() + } + + fun setBV(v: String) { + b = v.toDoubleOrNull() + } + + fun setCV(v: String) { + c = v.toDoubleOrNull() + } + + val formatMain: String + get() = when (ok) { + true -> "$a*x^2 + $b*x + $c" + false -> "" + } + + val formatResult: String + get() = when (result.size) { + 0 -> "x = []" + 1 -> "x = ${result[0]}" + 2 -> "x = [${result[0]}; ${result[1]}]" + else -> "" + } + + override fun toString(): String { + if (!ok) { + return "" + } + return "$formatMain;\n$formatResult" + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/model/data/SumModel.kt b/app/src/main/java/xyz/nuark/pomslab1/model/data/SumModel.kt new file mode 100644 index 0000000..2172d6c --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/model/data/SumModel.kt @@ -0,0 +1,45 @@ +package xyz.nuark.pomslab1.model.data + +class SumModel { + var a: Double? = null + var b: Double? = null + + val ok: Boolean get() = a != null && b != null + + val result: Array + get() { + if (a == null || b == null) { + return emptyArray() + } + val _a = a!! + val _b = b!! + return arrayOf(_a + _b) + } + + fun setAV(v: String) { + a = v.toDoubleOrNull() + } + + fun setBV(v: String) { + b = v.toDoubleOrNull() + } + + val formatMain: String + get() = when (ok) { + true -> "$a + $b" + false -> "" + } + + val formatResult: String + get() = when (result.size) { + 1 -> "${result[0]}" + else -> "" + } + + override fun toString(): String { + if (!ok) { + return "" + } + return "$formatMain = $formatResult" + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/model/interfaces/CalculationRecordDao.kt b/app/src/main/java/xyz/nuark/pomslab1/model/interfaces/CalculationRecordDao.kt new file mode 100644 index 0000000..5305a2c --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/model/interfaces/CalculationRecordDao.kt @@ -0,0 +1,20 @@ +package xyz.nuark.pomslab1.model.interfaces + +import androidx.lifecycle.LiveData +import androidx.room.* +import xyz.nuark.pomslab1.model.data.CalculationRecord + +@Dao +interface CalculationRecordDao { + @Query("SELECT * FROM calc_records") + fun getAll(): LiveData> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertOne(record: CalculationRecord) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertAll(vararg records: CalculationRecord) + + @Delete + fun delete(user: CalculationRecord) +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/model/repo/AppDatabase.kt b/app/src/main/java/xyz/nuark/pomslab1/model/repo/AppDatabase.kt new file mode 100644 index 0000000..e6dc9f4 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/model/repo/AppDatabase.kt @@ -0,0 +1,14 @@ +package xyz.nuark.pomslab1.model.repo + +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.TypeConverters +import xyz.nuark.pomslab1.model.data.CalculationRecord +import xyz.nuark.pomslab1.model.interfaces.CalculationRecordDao +import xyz.nuark.pomslab1.utils.RoomConverters + +@Database(entities = [CalculationRecord::class], version = 1) +@TypeConverters(RoomConverters::class) +abstract class AppDatabase : RoomDatabase() { + abstract fun calculationRecordDao(): CalculationRecordDao +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/services/HeavyTask.kt b/app/src/main/java/xyz/nuark/pomslab1/services/HeavyTask.kt new file mode 100644 index 0000000..3e41700 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/services/HeavyTask.kt @@ -0,0 +1,88 @@ +package xyz.nuark.pomslab1.services + +import android.app.Service +import android.content.Context +import android.content.Intent +import android.os.Binder +import android.os.IBinder +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import xyz.nuark.pomslab1.R +import java.io.* + +class HeavyTask : Service() { + private val binder = HeavyTaskBinder() + + private val _messengerChannel = MutableLiveData() + val messengerChannel: LiveData = _messengerChannel + + private var outputStreamWriter: OutputStreamWriter? = null + + override fun onBind(intent: Intent): IBinder { + return binder + } + + override fun onUnbind(intent: Intent?): Boolean { + return true + } + + fun startCalculationOfPI(steps: Int) { + outputStreamWriter = OutputStreamWriter(applicationContext.openFileOutput(LOG_FILENAME, Context.MODE_APPEND)) + log("startCalculationOfPI: starting\n") + Thread { + _messengerChannel.postValue(buildString { + append(getString(R.string.messagePICalculationStarted)) + append(steps) + }) + var index = 0 + var pi = 0.0 + var denominator = 1 + + while (index < steps) { + if (index % 2 == 0) { + pi += 4.0 / denominator + } else { + pi -= 4.0 / denominator + } + + index += 1 + denominator += 2 + } + + log("startCalculationOfPI: posting value $pi to live data channel\n") + _messengerChannel.postValue(getString(R.string.messagePICalculationEnded).format(steps, pi)) + outputStreamWriter?.flush() + outputStreamWriter?.close() + }.start() + } + + fun getLogText(): String { + return try { + val inputStream: InputStream = applicationContext.openFileInput(LOG_FILENAME) + inputStream.bufferedReader().use(BufferedReader::readText) + } catch (e: FileNotFoundException) { + Log.e(TAG, "getLogText: ENOENT", e) + e.stackTraceToString() + } catch (e: IOException) { + Log.e(TAG, "getLogText: IOE", e) + e.stackTraceToString() + }.ifEmpty { getString(R.string.empty) } + } + + private fun log(line: String) { + outputStreamWriter?.write(line) + Log.i(TAG, "log: $outputStreamWriter") + Log.i(TAG, line) + } + + inner class HeavyTaskBinder : Binder() { + val service: HeavyTask get() = this@HeavyTask + } + + companion object { + const val TAG = "HeavyTask" + + const val LOG_FILENAME = "heavy_task.log" + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/utils/RoomConverters.kt b/app/src/main/java/xyz/nuark/pomslab1/utils/RoomConverters.kt new file mode 100644 index 0000000..18c8639 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/utils/RoomConverters.kt @@ -0,0 +1,16 @@ +package xyz.nuark.pomslab1.utils + +import androidx.room.TypeConverter +import java.util.* + +class RoomConverters { + @TypeConverter + fun fromTimestamp(value: Long?): Date? { + return if (value == null) null else Date(value) + } + + @TypeConverter + fun dateToTimestamp(date: Date?): Long? { + return date?.time + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/activities/GraphicsActivity.kt b/app/src/main/java/xyz/nuark/pomslab1/view/activities/GraphicsActivity.kt new file mode 100644 index 0000000..42514f9 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/activities/GraphicsActivity.kt @@ -0,0 +1,54 @@ +package xyz.nuark.pomslab1.view.activities + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import xyz.nuark.pomslab1.databinding.ActivityGraphicsBinding + +class GraphicsActivity : AppCompatActivity() { + private var _binding: ActivityGraphicsBinding? = null + private val binding get() = _binding!! + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + _binding = ActivityGraphicsBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.tractor.setOnClickListener { + binding.tractor.apply { + clearAnimation() + rotation = 0f + scaleX = 1f + scaleY = 1f + translationX = 0f + translationY = 0f + alpha = 1f + } + } + + binding.rotate.setOnClickListener { + binding.tractor.animate().rotation(3600f).duration = 500 + } + + binding.scale.setOnClickListener { + binding.tractor.animate().scaleXBy(-4f).scaleYBy(-4f).setDuration(1000).withEndAction { + binding.tractor.animate().scaleXBy(4f).scaleYBy(4f).duration = 1000 + } + + } + + binding.translate.setOnClickListener { + binding.tractor.animation + binding.tractor.animate().translationXBy(-100f).setDuration(100).withEndAction { + binding.tractor.animate().translationXBy(200f).setDuration(800).withEndAction { + binding.tractor.animate().translationXBy(-100f).duration = 100 + } + } + } + + binding.alpha.setOnClickListener { + binding.tractor.animate().alpha(0f).setDuration(100).withEndAction { + binding.tractor.animate().alpha(1f).duration = 1000 + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/activities/LinkerActivity.kt b/app/src/main/java/xyz/nuark/pomslab1/view/activities/LinkerActivity.kt new file mode 100644 index 0000000..4d40e3c --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/activities/LinkerActivity.kt @@ -0,0 +1,36 @@ +package xyz.nuark.pomslab1.view.activities + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.text.buildSpannedString +import xyz.nuark.pomslab1.R +import xyz.nuark.pomslab1.databinding.ActivityLinkerBinding + +class LinkerActivity : AppCompatActivity() { + private var _binding: ActivityLinkerBinding? = null + private val binding get() = _binding!! + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + _binding = ActivityLinkerBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.intentContents.text = intent.let { + buildSpannedString { + append(getString(R.string.youTriedToOpen)) + appendLine(it.dataString) + } + } + + binding.openInBrowser.setOnClickListener { + try { + startActivity(Intent.createChooser(Intent(Intent.ACTION_VIEW).apply { + data = Uri.parse(binding.linkEditor.text.toString()) + }, getString(R.string.chooseBrowserTitle))) + } catch (_: Exception) { + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/activities/MainActivity.kt b/app/src/main/java/xyz/nuark/pomslab1/view/activities/MainActivity.kt new file mode 100644 index 0000000..17eb107 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/activities/MainActivity.kt @@ -0,0 +1,96 @@ +package xyz.nuark.pomslab1.view.activities + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.Menu +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.content.edit +import xyz.nuark.pomslab1.R +import xyz.nuark.pomslab1.databinding.ActivityMainBinding + +class MainActivity : AppCompatActivity() { + private var _binding: ActivityMainBinding? = null + private val binding get() = _binding!! + + override fun onCreate(savedInstanceState: Bundle?) { + updateTheme() + super.onCreate(savedInstanceState) + _binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + return super.onCreateOptionsMenu(menu?.apply { + addSubMenu(getString(R.string.openActionsLabel)).apply { + add(getString(R.string.openSwitcher))?.apply { + setOnMenuItemClickListener { + startActivity(Intent(this@MainActivity, SwitcherActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + }) + true + } + } + add(getString(R.string.openCalcHistory))?.apply { + setOnMenuItemClickListener { + startActivity(Intent(this@MainActivity, ResultActivity::class.java)) + true + } + } + add(getString(R.string.openHeavyTaskConnector))?.apply { + setOnMenuItemClickListener { + startActivity(Intent(this@MainActivity, ServiceCommunicatorActivity::class.java)) + true + } + } + add(getString(R.string.openGraphicsActivity))?.apply { + setOnMenuItemClickListener { + startActivity(Intent(this@MainActivity, GraphicsActivity::class.java)) + true + } + } + } + val sp = getSharedPreferences(SPG_THEME_MODE, Context.MODE_PRIVATE) + if (sp.getBoolean(SP_LIGHT_MODE_ENABLED, false)) { + add(getString(R.string.switchToDarkLabel))?.apply { + setOnMenuItemClickListener { + sp.edit(true) { + putBoolean(SP_LIGHT_MODE_ENABLED, false) + } + updateTheme() + true + } + } + } else { + add(getString(R.string.switchToLightLabel))?.apply { + setOnMenuItemClickListener { + sp.edit(true) { + putBoolean(SP_LIGHT_MODE_ENABLED, true) + } + updateTheme() + true + } + } + } + }) + } + + private fun updateTheme() { + val sp = getSharedPreferences(SPG_THEME_MODE, Context.MODE_PRIVATE) + val lightMode = when (sp.getBoolean(SP_LIGHT_MODE_ENABLED, false)) { + true -> AppCompatDelegate.MODE_NIGHT_NO + false -> AppCompatDelegate.MODE_NIGHT_YES + } + Log.i(TAG, "updateTheme: lightMode") + AppCompatDelegate.setDefaultNightMode(lightMode) + } + + companion object { + const val TAG = "MainActivity" + + const val SPG_THEME_MODE = "SPG_THEME_MODE" + const val SP_LIGHT_MODE_ENABLED = "SP_LIGHT_MODE_ENABLED" + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/activities/ResultActivity.kt b/app/src/main/java/xyz/nuark/pomslab1/view/activities/ResultActivity.kt new file mode 100644 index 0000000..9ec0d2c --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/activities/ResultActivity.kt @@ -0,0 +1,33 @@ +package xyz.nuark.pomslab1.view.activities + +import android.os.Bundle +import android.view.View +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import xyz.nuark.pomslab1.databinding.ActivityResultBinding +import xyz.nuark.pomslab1.view.adapters.CalculationHistoryAdapter +import xyz.nuark.pomslab1.viewmodels.ResultActivityViewModel + +class ResultActivity : AppCompatActivity() { + private var _binding: ActivityResultBinding? = null + private val binding get() = _binding!! + + private val viewModel: ResultActivityViewModel by viewModels() + + private val adapter = CalculationHistoryAdapter() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + _binding = ActivityResultBinding.inflate(layoutInflater) + setContentView(binding.root) + + viewModel.records.observe(this) { + binding.noHistoryLabel.visibility = if (it.isEmpty()) View.VISIBLE else View.GONE + adapter.setRecords(it) + } + + binding.historyList.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true) + binding.historyList.adapter = adapter + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/activities/ServiceCommunicatorActivity.kt b/app/src/main/java/xyz/nuark/pomslab1/view/activities/ServiceCommunicatorActivity.kt new file mode 100644 index 0000000..0acfa5e --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/activities/ServiceCommunicatorActivity.kt @@ -0,0 +1,146 @@ +package xyz.nuark.pomslab1.view.activities + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.Bundle +import android.os.IBinder +import android.util.Log +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import xyz.nuark.pomslab1.R +import xyz.nuark.pomslab1.databinding.ActivityServiceCommunicatorBinding +import xyz.nuark.pomslab1.services.HeavyTask + +class ServiceCommunicatorActivity : AppCompatActivity() { + private var _binding: ActivityServiceCommunicatorBinding? = null + private val binding get() = _binding!! + + private val connection = HeavyServiceConnector() + private lateinit var heavyIntentService: Intent + + private var subscribed = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + _binding = ActivityServiceCommunicatorBinding.inflate(layoutInflater) + setContentView(binding.root) + + heavyIntentService = Intent(this, HeavyTask::class.java) + + binding.serviceController.setOnClickListener { + if (connection.bound.value == true) { + unbindService(connection) + connection.stopService(this) + subscribed = false + } else { + binding.logHolder.text = "" + bindService(heavyIntentService, connection, Context.BIND_AUTO_CREATE) + } + } + + binding.calc.setOnClickListener { + val stepsString = binding.stepsCount.editText?.text?.toString() ?: "" + if (stepsString.isEmpty()) { + return@setOnClickListener + } + val steps = stepsString.toIntOrNull() + if (steps == null || steps <= 0) { + return@setOnClickListener + } + + val binder = connection.binder + if (connection.bound.value == true && binder != null && binder.isBinderAlive) { + Log.i(TAG, "onCreate: service is ready for work!") + binder.service.startCalculationOfPI(steps) + Log.i(TAG, "onCreate: started calculation thread in service for 200 steps") + if (!subscribed) { + binder.service.messengerChannel.observe(this) { + appendLogLine(it) + } + subscribed = true + } + } else { + Log.i(TAG, "onCreate: service is not ready! (binder: $binder)") + } + } + + binding.readServiceLog.setOnClickListener { + connection.binder?.service?.let { + binding.serviceLogHolder.text = it.getLogText() + } + } + + connection.bound.observe(this) { result -> + binding.serviceController.apply { + setChipIconResource(if (result) R.drawable.baseline_play_arrow_24 else R.drawable.baseline_stop_24) + setChipIconTintResource(if (result) R.color.green else R.color.red) + text = getText(if (result) R.string.serviceStatusRunning else R.string.serviceStatusStopped) + } + } + } + + private fun appendLogLine(line: String) { + binding.logHolder.text = buildString { + appendLine(line) + append(binding.logHolder.text) + } + } + + override fun onDestroy() { + if (connection.bound.value == true) { + unbindService(connection) + } + super.onDestroy() + } + + class HeavyServiceConnector : ServiceConnection { + private var _bound = MutableLiveData() + val bound: LiveData get() = _bound + + var binder: HeavyTask.HeavyTaskBinder? = null + private set + + init { + _bound.value = false + } + + override fun onServiceConnected(service: ComponentName?, binder: IBinder?) { + Log.i(TAG, "onServiceConnected: service connected, got $service and $binder") + if (binder == null) { + Log.e(TAG, "onServiceConnected: binder is null!") + return + } + if (binder !is HeavyTask.HeavyTaskBinder) { + Log.e(TAG, "onServiceConnected: binder is not ours!") + return + } + this.binder = binder + _bound.value = true + } + + override fun onServiceDisconnected(service: ComponentName?) { + Log.i(TAG, "onServiceDisconnected: service disconnected, got $service") + binder = null + _bound.value = false + } + + fun stopService(lifecycleOwner: LifecycleOwner) { + binder?.service?.stopSelf() + binder?.service?.messengerChannel?.removeObservers(lifecycleOwner) + binder = null + _bound.value = false + } + + companion object { + const val TAG = "HeavyServiceConnector" + } + } + + companion object { + const val TAG = "ServiceCommunicatorActivity" + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/activities/SwitcherActivity.kt b/app/src/main/java/xyz/nuark/pomslab1/view/activities/SwitcherActivity.kt new file mode 100644 index 0000000..2424037 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/activities/SwitcherActivity.kt @@ -0,0 +1,78 @@ +package xyz.nuark.pomslab1.view.activities + +import android.content.Intent +import android.os.Bundle +import android.view.Menu +import androidx.appcompat.app.AppCompatActivity +import xyz.nuark.pomslab1.R +import xyz.nuark.pomslab1.databinding.ActivitySwitcherBinding +import xyz.nuark.pomslab1.view.fragments.QuadraticFragment +import xyz.nuark.pomslab1.view.fragments.SumFragment + +class SwitcherActivity : AppCompatActivity() { + private var _binding: ActivitySwitcherBinding? = null + private val binding get() = _binding!! + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + _binding = ActivitySwitcherBinding.inflate(layoutInflater) + setContentView(binding.root) + + supportFragmentManager + .beginTransaction().apply { + add(binding.fragmentHolder.id, sumFragment) + add(binding.fragmentHolder.id, quadraticFragment) + } + .commit() + supportFragmentManager.executePendingTransactions() + supportFragmentManager + .beginTransaction().apply { + detach(sumFragment) + } + .commit() + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + return super.onCreateOptionsMenu(menu?.apply { + add(getString(R.string.openMultipanel))?.apply { + setOnMenuItemClickListener { + startActivity(Intent(this@SwitcherActivity, MainActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + }) + true + } + } + add(getString(R.string.switchFragment))?.apply { + setOnMenuItemClickListener { + this@SwitcherActivity.switchFragment() + true + } + } + add(getString(R.string.openCalcHistory))?.apply { + setOnMenuItemClickListener { + startActivity(Intent(this@SwitcherActivity, ResultActivity::class.java)) + true + } + } + }) + } + + private fun switchFragment() { + supportFragmentManager + .beginTransaction().apply { + if (quadraticFragment.isDetached) { + detach(sumFragment) + attach(quadraticFragment) + } else if (sumFragment.isDetached) { + attach(sumFragment) + detach(quadraticFragment) + } + } + .commit() + } + + companion object { + private val quadraticFragment = QuadraticFragment() + private val sumFragment = SumFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/adapters/CalculationHistoryAdapter.kt b/app/src/main/java/xyz/nuark/pomslab1/view/adapters/CalculationHistoryAdapter.kt new file mode 100644 index 0000000..d9593f9 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/adapters/CalculationHistoryAdapter.kt @@ -0,0 +1,58 @@ +package xyz.nuark.pomslab1.view.adapters + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import xyz.nuark.pomslab1.databinding.CalculationHistoryItemBinding +import xyz.nuark.pomslab1.model.data.CalculationRecord +import java.text.SimpleDateFormat +import java.util.* + +class CalculationHistoryAdapter : RecyclerView.Adapter() { + private val records = arrayListOf() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { + val inflater = LayoutInflater.from(parent.context) + val binding = CalculationHistoryItemBinding.inflate( + inflater, parent, + false + ) + return VH(binding) + } + + override fun getItemCount(): Int { + return records.size + } + + override fun onBindViewHolder(holder: VH, position: Int) { + holder.bind(records[position]) + } + + fun setRecords(newRecords: List) { + val size = records.size + records.clear() + if (size > 0) { + notifyItemRangeRemoved(0, size) + } + records.addAll(newRecords) + if (records.size > 0) { + notifyItemRangeInserted(0, records.size) + } + } + + fun isEmpty(): Boolean { + return records.isEmpty() + } + + class VH(private val binding: CalculationHistoryItemBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(record: CalculationRecord) { + binding.dateHolder.text = formatter.format(record.date) + binding.equHolder.text = record.equation + binding.resultHolder.text = record.result + } + } + + companion object { + private val formatter = SimpleDateFormat("dd.MM.yy HH:mm:ss", Locale.CANADA) + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/fragments/QuadraticFragment.kt b/app/src/main/java/xyz/nuark/pomslab1/view/fragments/QuadraticFragment.kt new file mode 100644 index 0000000..d13bae4 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/fragments/QuadraticFragment.kt @@ -0,0 +1,36 @@ +package xyz.nuark.pomslab1.view.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import xyz.nuark.pomslab1.databinding.FragmentQuadraticBinding +import xyz.nuark.pomslab1.viewmodels.QuadraticCalculationViewModel + +class QuadraticFragment : Fragment() { + private var _binding: FragmentQuadraticBinding? = null + private val binding get() = _binding!! + + private val calculationViewModel: QuadraticCalculationViewModel by activityViewModels() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentQuadraticBinding.inflate(inflater) + binding.equation = calculationViewModel.quadraticEquationModel + binding.resultString = calculationViewModel.quadraticEquationModel.toString() + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.button.setOnClickListener { v: View? -> + binding.resultString = calculationViewModel.quadraticEquationModel.toString() + calculationViewModel.saveQuadraticCalculation() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/view/fragments/SumFragment.kt b/app/src/main/java/xyz/nuark/pomslab1/view/fragments/SumFragment.kt new file mode 100644 index 0000000..ed95ea1 --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/view/fragments/SumFragment.kt @@ -0,0 +1,36 @@ +package xyz.nuark.pomslab1.view.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import xyz.nuark.pomslab1.databinding.FragmentSumBinding +import xyz.nuark.pomslab1.viewmodels.SumCalculationViewModel + +class SumFragment : Fragment() { + private var _binding: FragmentSumBinding? = null + private val binding get() = _binding!! + + private val calculationViewModel: SumCalculationViewModel by activityViewModels() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentSumBinding.inflate(inflater) + binding.equation = calculationViewModel.sumModel + binding.resultString = calculationViewModel.sumModel.toString() + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.button.setOnClickListener { v: View? -> + binding.resultString = calculationViewModel.sumModel.toString() + calculationViewModel.saveSumCalculation() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/viewmodels/QuadraticCalculationViewModel.kt b/app/src/main/java/xyz/nuark/pomslab1/viewmodels/QuadraticCalculationViewModel.kt new file mode 100644 index 0000000..47e8c4c --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/viewmodels/QuadraticCalculationViewModel.kt @@ -0,0 +1,23 @@ +package xyz.nuark.pomslab1.viewmodels + +import androidx.lifecycle.ViewModel +import xyz.nuark.pomslab1.PomsApp +import xyz.nuark.pomslab1.model.data.CalculationRecord +import xyz.nuark.pomslab1.model.data.QuadraticEquationModel +import java.util.* + +class QuadraticCalculationViewModel : ViewModel() { + val quadraticEquationModel = QuadraticEquationModel() + + fun saveQuadraticCalculation() { + if (quadraticEquationModel.ok) { + Thread { + PomsApp.instance.db.calculationRecordDao().insertOne( + CalculationRecord( + Date(), quadraticEquationModel.formatMain, quadraticEquationModel.formatResult + ) + ) + }.start() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/viewmodels/ResultActivityViewModel.kt b/app/src/main/java/xyz/nuark/pomslab1/viewmodels/ResultActivityViewModel.kt new file mode 100644 index 0000000..113ef4c --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/viewmodels/ResultActivityViewModel.kt @@ -0,0 +1,10 @@ +package xyz.nuark.pomslab1.viewmodels + +import androidx.lifecycle.LiveData +import androidx.lifecycle.ViewModel +import xyz.nuark.pomslab1.PomsApp +import xyz.nuark.pomslab1.model.data.CalculationRecord + +class ResultActivityViewModel : ViewModel() { + val records: LiveData> = PomsApp.instance.db.calculationRecordDao().getAll() +} \ No newline at end of file diff --git a/app/src/main/java/xyz/nuark/pomslab1/viewmodels/SumCalculationViewModel.kt b/app/src/main/java/xyz/nuark/pomslab1/viewmodels/SumCalculationViewModel.kt new file mode 100644 index 0000000..4b64c9b --- /dev/null +++ b/app/src/main/java/xyz/nuark/pomslab1/viewmodels/SumCalculationViewModel.kt @@ -0,0 +1,23 @@ +package xyz.nuark.pomslab1.viewmodels + +import androidx.lifecycle.ViewModel +import xyz.nuark.pomslab1.PomsApp +import xyz.nuark.pomslab1.model.data.CalculationRecord +import xyz.nuark.pomslab1.model.data.SumModel +import java.util.* + +class SumCalculationViewModel : ViewModel() { + val sumModel = SumModel() + + fun saveSumCalculation() { + if (sumModel.ok) { + Thread { + PomsApp.instance.db.calculationRecordDao().insertOne( + CalculationRecord( + Date(), sumModel.formatMain, sumModel.formatResult + ) + ) + }.start() + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/baseline_play_arrow_24.xml b/app/src/main/res/drawable/baseline_play_arrow_24.xml new file mode 100644 index 0000000..e3fd2e9 --- /dev/null +++ b/app/src/main/res/drawable/baseline_play_arrow_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_stop_24.xml b/app/src/main/res/drawable/baseline_stop_24.xml new file mode 100644 index 0000000..19bcbee --- /dev/null +++ b/app/src/main/res/drawable/baseline_stop_24.xml @@ -0,0 +1,5 @@ + + + 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..910da4f --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,10 @@ + + + + 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..1d46844 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml new file mode 100644 index 0000000..b81dbb6 --- /dev/null +++ b/app/src/main/res/layout-land/activity_main.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/fragment_quadratic.xml b/app/src/main/res/layout-land/fragment_quadratic.xml new file mode 100644 index 0000000..09e22eb --- /dev/null +++ b/app/src/main/res/layout-land/fragment_quadratic.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + +