diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18e081c --- /dev/null +++ b/.gitignore @@ -0,0 +1,74 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.externalNativeBuild +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +.idea/caches + +# Keystore files +# Uncomment the following line if you do not want to check your keystore files in. +#*.jks + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..5c9d4a8 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0d45e8d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..8ffdad4 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml new file mode 100644 index 0000000..5cf41c4 --- /dev/null +++ b/.idea/navEditor.xml @@ -0,0 +1,55 @@ + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..8306744 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Dart/design_container.dart b/Dart/design_container.dart deleted file mode 100644 index a4233f9..0000000 --- a/Dart/design_container.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'package:flutter/material.dart'; - -void main()=>runApp(MaterialApp( - home: ContainerApp(), - debugShowCheckedModeBanner: false, -)); - -class ContainerApp extends StatefulWidget { - @override - _ContainerAppState createState() => _ContainerAppState(); -} - -class _ContainerAppState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - body: MainApp(), - ); - } -} - -class MainApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - color: Colors.grey[700], - alignment: FractionalOffset.center, - child: ListView( - children: [ - LittleApp(), - Question(), - Answer() - ], - ), - ); - } -} - -class LittleApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.fromLTRB(50.0, 100.0, 50.0, 50.0), - child: Image.asset("asset/flight_0.jpg"), - constraints:BoxConstraints( - maxHeight: 250.0, - minHeight: 50.0, - maxWidth: 250.0, - minWidth: 50.0 - ), - decoration: BoxDecoration( - //color: Colors.blueAccent, - boxShadow: [BoxShadow( - color: Colors.blueGrey[800], - spreadRadius: 20.0, - blurRadius: 20.0, - )] - ), - ); - } -} - -class Question extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.all(50.0), - child: Text("Is it a plane ? ",style:TextStyle(fontSize:25.0,color:Colors.white),textAlign: TextAlign.center,), - constraints:BoxConstraints( - maxHeight: 50.0, - minHeight: 50.0, - maxWidth: 50.0, - minWidth: 50.0 - ), - decoration: BoxDecoration( - //color: Colors.blueAccent, - boxShadow: [BoxShadow( - color: Colors.blueGrey[800], - spreadRadius: 20.0, - blurRadius: 20.0, - )] - ), - ); - } -} - -class Answer extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.all(20.0), - child: Row( - children: [ - Yes(), - No(), - ], - ), - ); - } -} - -class Yes extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - child: Center(child: Text("Yes",style: TextStyle(color: Colors.white,fontSize: 20.0))), - margin: EdgeInsets.only(left: 10.0), - constraints:BoxConstraints( - maxHeight: 50.0, - minHeight: 50.0, - maxWidth: 100.0, - minWidth: 50.0 - ), - decoration: BoxDecoration( - border: Border.all( - width: 1, - color: Colors.white - ), - borderRadius: BorderRadius.all(Radius.circular(15.0),) - ), - ); - } -} - -class No extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - child: Center(child: Text("No",style: TextStyle(color: Colors.white,fontSize: 20.0))), - margin: EdgeInsets.only(left: 100.0), - constraints:BoxConstraints( - maxHeight: 50.0, - minHeight: 50.0, - maxWidth: 100.0, - minWidth: 50.0 - ), - decoration: BoxDecoration( - border: Border.all( - width: 1, - color: Colors.white - ), - borderRadius: BorderRadius.all(Radius.circular(15.0),) - ), - ); - } -} diff --git a/Dart/hello_world.dart b/Dart/hello_world.dart deleted file mode 100644 index 73461c2..0000000 --- a/Dart/hello_world.dart +++ /dev/null @@ -1,3 +0,0 @@ -void main(){ - print("Hello World"); -} diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 63a9d57..0000000 --- a/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -BSD 2-Clause License - -Copyright (c) 2020, DSC_TIU -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index c226243..d7940fd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# Hacktoberfest_FirstTimers -Fork and Do PR +# calculator +Simple Calculator for Android API Level 23 diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..7f7809d --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,48 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.mthrsj.calculator" + minSdkVersion 23 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +allprojects { + repositories { + google() + jcenter() + mavenCentral() + maven { url 'https://maven.google.com' } + } +} + + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'androidx.appcompat:appcompat:1.0.0-beta01' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.google.android.material:material:1.0.0' + implementation 'com.android.support:design:28.0.0' + implementation 'android.arch.navigation:navigation-fragment:1.0.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /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 diff --git a/app/src/androidTest/java/com/mthrsj/calculator/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/mthrsj/calculator/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..117841c --- /dev/null +++ b/app/src/androidTest/java/com/mthrsj/calculator/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.mthrsj.calculator + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.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.getTargetContext() + assertEquals("com.mthrsj.calculator", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..eb23914 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..6e78459 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/com/mthrsj/calculator/BasicCalculator.kt b/app/src/main/java/com/mthrsj/calculator/BasicCalculator.kt new file mode 100644 index 0000000..590b4dd --- /dev/null +++ b/app/src/main/java/com/mthrsj/calculator/BasicCalculator.kt @@ -0,0 +1,90 @@ +package com.mthrsj.calculator + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import kotlinx.android.synthetic.main.activity_basic_calculator.* + +class BasicCalculator : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_basic_calculator) + + var toolbar: Toolbar = findViewById(toolbar.id) + setSupportActionBar(toolbar) + + plusButton.setOnClickListener { view -> operation("plus"); view.clearFocus() } + minusButton.setOnClickListener { view -> operation("minus"); view.clearFocus() } + divideButton.setOnClickListener { view -> operation("divide"); view.clearFocus() } + multiplyButton.setOnClickListener { view -> operation("multiply"); view.clearFocus() } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.main_menu, menu) + return true + } + + private fun navigateComplex() { + var it = Intent(this, ComplexCalculator::class.java) + startActivity(it) + } + + private fun navigateBasic() { + var it = Intent(this, BasicCalculator::class.java) + startActivity(it) + } + + override fun onOptionsItemSelected(item: MenuItem) = when (item.title) { + "Basic" -> { + false + } + "Complex" -> { + navigateComplex() + true + } + else -> { + // If we got here, the user's action was not recognized. + // Invoke the superclass to handle it. + super.onOptionsItemSelected(item) + } + } + + private fun operation(type: String) { + try { + val value1 = input1.text.toString().toDouble() + val value2 = input2.text.toString().toDouble() + calculate(type, value1, value2) + } + catch(e: NumberFormatException){ + + } + } + + private fun calculate(type: String, value1: Double, value2: Double) { + Log.d("TYPE", type) + if (type == "plus") { + val result = value1 + value2 + Log.d("CALC", "$result") + resultText.text = result.toString() + } else if (type == "minus") { + val result = value1 - value2 + Log.d("CALC", "$result") + resultText.text = result.toString() + } else if (type == "divide") { + if (value2 != 0.0) { + val result = value1 / value2 + Log.d("CALC", "$result") + resultText.text = result.toString() + } + } else if (type === "multiply") { + val result = value1 * value2 + Log.d("CALC", "$result") + resultText.text = result.toString() + } + } +} diff --git a/app/src/main/java/com/mthrsj/calculator/ComplexCalculator.kt b/app/src/main/java/com/mthrsj/calculator/ComplexCalculator.kt new file mode 100644 index 0000000..7c1b661 --- /dev/null +++ b/app/src/main/java/com/mthrsj/calculator/ComplexCalculator.kt @@ -0,0 +1,209 @@ +package com.mthrsj.calculator + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import kotlinx.android.synthetic.main.activity_complex_calculator.* + +class ComplexCalculator : AppCompatActivity() { + + private var operations: MutableList = mutableListOf() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_complex_calculator) + + var toolbar: Toolbar = findViewById(toolbar.id) + setSupportActionBar(toolbar) + + // Setting operation listeners + plusButtonComplex.setOnClickListener { view -> addOperation(view) } + minusButtonComplex.setOnClickListener { view -> addOperation(view) } + divideButtonComplex.setOnClickListener { view -> addOperation(view) } + multiplyButtonComplex.setOnClickListener { view -> addOperation(view) } + dotButton.setOnClickListener { addDot() } + clearButton.setOnClickListener { clearInput() } + deleteButton.setOnClickListener { deleteLast() } + equalButton.setOnClickListener { result() } + + // Setting number buttons listeners + button0.setOnClickListener { view -> addNum(view) } + button1.setOnClickListener { view -> addNum(view) } + button2.setOnClickListener { view -> addNum(view) } + button3.setOnClickListener { view -> addNum(view) } + button4.setOnClickListener { view -> addNum(view) } + button5.setOnClickListener { view -> addNum(view) } + button6.setOnClickListener { view -> addNum(view) } + button7.setOnClickListener { view -> addNum(view) } + button8.setOnClickListener { view -> addNum(view) } + button9.setOnClickListener { view -> addNum(view) } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.main_menu, menu) + return true + } + + private fun navigateBasic() { + var it = Intent(this, BasicCalculator::class.java) + startActivity(it) + } + + override fun onOptionsItemSelected(item: MenuItem) = when (item.title) { + "Basic" -> { + navigateBasic() + true + } + + "Complex" -> { + false + } + + else -> { + // If we got here, the user's action was not recognized. + // Invoke the superclass to handle it. + super.onOptionsItemSelected(item) + } + } + + private fun addOperation(v: View) { + var op = v.tag.toString() + try { + if(operations.isNotEmpty()) { + operations[operations.size - 1].toDouble() + Log.d("OPER", "$op added to operations") + when (op) { + "plus" -> operations.add("+") + "minus" -> operations.add("-") + "divide" -> operations.add("/") + "multiply" -> operations.add("x") + } + formatInput() + } + } catch (e: NumberFormatException) { + + } + } + + private fun addNum(v: View) { + var tag = v.tag.toString() + var number = tag[tag.length - 1].toString() + Log.d("OPER", "button$number got clicked") + try { + if (operations.isNotEmpty()) { + var lastItem = operations[operations.size - 1] + if (lastItem.indexOf(".") != -1) { + operations[operations.size - 1] = "$lastItem$number" + formatInput() + return + } else { + lastItem.toDouble() + operations[operations.size - 1] = "$lastItem$number" + formatInput() + return + } + } else { + if(number == "0") + operations.add("0.") + else operations.add(number) + } + } catch (e: NumberFormatException) { + if(number == "0") + operations.add("0.") + else operations.add(number) + } + formatInput() + } + + private fun addDot() { + var size = operations.size + if (size > 0) { + var last = operations[size - 1] + if (last.indexOf(".") != -1) { + // Nothing should be done + } else { + try { + last.toDouble() + operations[size - 1] = "$last." + } catch (e: NumberFormatException) { + operations.add("0.") + } + } + } else { + operations.add("0.") + } + formatInput() + } + + private fun deleteLast() { + if (operations.size > 0) { + try { + var string = operations[operations.size - 1] + Log.d("DEB", "String length=${string.length}") + if (string.indexOf(".") != -1) { + var result = string.dropLast(1) + operations[operations.size - 1] = result + } else { + operations.removeAt(operations.size - 1) + } + } catch (e: NumberFormatException) { + operations.removeAt(operations.size - 1) + } + formatInput() + } + } + + private fun clearInput() { + Log.d("OPER", "Input cleared") + operations = mutableListOf() + inputBox.setText("") + } + + private fun formatInput() { + var text = "" + for (i in operations) { + text = "$text$i " + } + inputBox.setText(text) + } + + private fun result() { + var result: Double = 1.0 + var last = -1.0 + var op = "" + for (item in operations) { + try { + Log.d("CALC", "Actual item: $item") + var value = item.toDouble() + if (last != -1.0) { + try { + Log.d("CALC", "Operation: $last $op $value") + when (op) { + "+" -> result = last + value + "-" -> result = last - value + "/" -> result = last / value + "x" -> result = last * value + } + Log.d("CALC", "Result is: $result ") + last = result + } catch (e: ArithmeticException) { + text_input_error.setText(R.string.zeroDivision) + } + } else { + last = value + } + } catch (e: java.lang.NumberFormatException) { + op = item + } + } + inputBox.setText(result.toString()) + operations = mutableListOf() + operations.add(result.toString()) + } +} + + diff --git a/app/src/main/java/com/mthrsj/calculator/MainActivity.kt b/app/src/main/java/com/mthrsj/calculator/MainActivity.kt new file mode 100644 index 0000000..b622a49 --- /dev/null +++ b/app/src/main/java/com/mthrsj/calculator/MainActivity.kt @@ -0,0 +1,53 @@ +package com.mthrsj.calculator + +import android.content.Intent +import android.os.Bundle +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import kotlinx.android.synthetic.main.activity_main.* + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + var appToolbar: Toolbar = findViewById(toolbar.id) + setSupportActionBar(appToolbar) + + basicButton.setOnClickListener { + navigateBasic() + } + complexButton.setOnClickListener { + navigateComplex() + } + } + + private fun navigateComplex() { + var it = Intent(this, ComplexCalculator::class.java) + startActivity(it) + } + + private fun navigateBasic() { + var it = Intent(this, BasicCalculator::class.java) + startActivity(it) + } + + override fun onOptionsItemSelected(item: MenuItem) = when (item.title) { + "Basic" -> { + navigateBasic() + true + } + + "Complex" -> { + navigateComplex() + true + } + + else -> { + // If we got here, the user's action was not recognized. + // Invoke the superclass to handle it. + super.onOptionsItemSelected(item) + } + } +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + 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..2408e30 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/rounded_button.xml b/app/src/main/res/drawable/rounded_button.xml new file mode 100644 index 0000000..d8e2eb8 --- /dev/null +++ b/app/src/main/res/drawable/rounded_button.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_basic_calculator.xml b/app/src/main/res/layout/activity_basic_calculator.xml new file mode 100644 index 0000000..1faa4fa --- /dev/null +++ b/app/src/main/res/layout/activity_basic_calculator.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + +