summaryrefslogtreecommitdiffstats
path: root/app/src/main/java/com/pwc/calculatorv2/data
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/pwc/calculatorv2/data')
-rw-r--r--app/src/main/java/com/pwc/calculatorv2/data/dao/FunctionDao.kt51
-rw-r--r--app/src/main/java/com/pwc/calculatorv2/data/datasources/FunctionListDataSource.kt70
-rw-r--r--app/src/main/java/com/pwc/calculatorv2/data/models/FunctionDTO.kt28
-rw-r--r--app/src/main/java/com/pwc/calculatorv2/data/repositories/FunctionListRepository.kt121
-rw-r--r--app/src/main/java/com/pwc/calculatorv2/data/responses/FunctionListResponse.kt8
-rw-r--r--app/src/main/java/com/pwc/calculatorv2/data/viewmodels/CalculatorViewModel.kt316
6 files changed, 594 insertions, 0 deletions
diff --git a/app/src/main/java/com/pwc/calculatorv2/data/dao/FunctionDao.kt b/app/src/main/java/com/pwc/calculatorv2/data/dao/FunctionDao.kt
new file mode 100644
index 0000000..341f961
--- /dev/null
+++ b/app/src/main/java/com/pwc/calculatorv2/data/dao/FunctionDao.kt
@@ -0,0 +1,51 @@
+package com.pwc.calculatorv2.data.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import com.pwc.calculatorv2.data.models.Function
+
+@Dao
+interface FunctionDao {
+ @Query("SELECT * FROM Function")
+ fun getAll(): List<Function>
+
+ @Query("SELECT * FROM Function WHERE function LIKE '%+%'")
+ fun getPlus(): List<Function>
+
+ @Query("SELECT * FROM Function WHERE function LIKE '%-%'")
+ fun getMinus(): List<Function>
+
+ @Query("SELECT * FROM Function WHERE function LIKE '%*%'")
+ fun getPer(): List<Function>
+
+ @Query("SELECT * FROM Function WHERE function LIKE '%/%'")
+ fun getDivide(): List<Function>
+
+ @Insert
+ fun insertAll(functionList: List<Function>)
+
+ @Insert
+ fun insert(function: Function)
+
+ @Delete
+ fun delete(function: Function)
+
+ @Query("DELETE FROM Function")
+ fun wipe()
+
+ @Query("DELETE FROM Function WHERE function LIKE '%+%'")
+ fun wipePlus()
+
+ @Query("DELETE FROM Function WHERE function LIKE '%-%'")
+ fun wipeMinus()
+
+ @Query("DELETE FROM Function WHERE function LIKE '%*%'")
+ fun wipePer()
+
+ @Query("DELETE FROM Function WHERE function LIKE '%/%'")
+ fun wipeDivided()
+
+
+} \ No newline at end of file
diff --git a/app/src/main/java/com/pwc/calculatorv2/data/datasources/FunctionListDataSource.kt b/app/src/main/java/com/pwc/calculatorv2/data/datasources/FunctionListDataSource.kt
new file mode 100644
index 0000000..aaee7b3
--- /dev/null
+++ b/app/src/main/java/com/pwc/calculatorv2/data/datasources/FunctionListDataSource.kt
@@ -0,0 +1,70 @@
+package com.pwc.calculatorv2.data.datasources
+
+import android.content.Context
+import androidx.room.Room
+import com.pwc.calculatorv2.AppDatabase
+import com.pwc.calculatorv2.data.models.Function
+
+class FunctionListDataSource (context: Context){
+ private val db: AppDatabase = Room.databaseBuilder(
+ context.applicationContext,
+ AppDatabase::class.java,
+ "calculator"
+ ).build()
+
+ fun getFunctionList(): List<Function> {
+ return db.functionDao().getAll()
+ }
+
+ fun getPlusFunctionList(): List<Function> {
+ return db.functionDao().getPlus()
+ }
+
+ fun getMinusFunctionList(): List<Function> {
+ return db.functionDao().getMinus()
+ }
+
+ fun getPerFunctionList(): List<Function> {
+ return db.functionDao().getPer()
+ }
+
+ fun getDividedFunctionList(): List<Function> {
+ return db.functionDao().getDivide()
+ }
+
+ fun addFunction(function: Function): List<Function> {
+ db.functionDao().insert(function)
+ return db.functionDao().getAll()
+ }
+
+ fun removeFunction(function: Function): List<Function> {
+ db.functionDao().delete(function)
+ return db.functionDao().getAll()
+ }
+
+ fun wipeFunctionList(): List<Function> {
+ db.functionDao().wipe()
+ return db.functionDao().getAll()
+ }
+
+ fun wipePlusFunctionList(): List<Function> {
+ db.functionDao().wipePlus()
+ return db.functionDao().getAll()
+ }
+
+ fun wipeMinusFunctionList(): List<Function> {
+ db.functionDao().wipeMinus()
+ return db.functionDao().getAll()
+ }
+
+ fun wipePerFunctionList(): List<Function> {
+ db.functionDao().wipePer()
+ return db.functionDao().getAll()
+ }
+
+ fun wipeDividedFunctionList(): List<Function> {
+ db.functionDao().wipeDivided()
+ return db.functionDao().getAll()
+ }
+
+}
diff --git a/app/src/main/java/com/pwc/calculatorv2/data/models/FunctionDTO.kt b/app/src/main/java/com/pwc/calculatorv2/data/models/FunctionDTO.kt
new file mode 100644
index 0000000..b8b73a2
--- /dev/null
+++ b/app/src/main/java/com/pwc/calculatorv2/data/models/FunctionDTO.kt
@@ -0,0 +1,28 @@
+package com.pwc.calculatorv2.data.models
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import androidx.room.TypeConverter
+import androidx.room.TypeConverters
+import java.util.Date
+
+@Entity
+@TypeConverters(DateConverter::class)
+data class Function(
+ @PrimaryKey (autoGenerate = true) var id: Int = 0,
+ @ColumnInfo var function: String = "",
+ @ColumnInfo var date: Date = Date()
+)
+
+class DateConverter {
+ @TypeConverter
+ fun fromDate(date: Date?): Long? {
+ return date?.time
+ }
+
+ @TypeConverter
+ fun toDate(timestamp: Long?): Date? {
+ return timestamp?.let { Date(it) }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/com/pwc/calculatorv2/data/repositories/FunctionListRepository.kt b/app/src/main/java/com/pwc/calculatorv2/data/repositories/FunctionListRepository.kt
new file mode 100644
index 0000000..d3b0682
--- /dev/null
+++ b/app/src/main/java/com/pwc/calculatorv2/data/repositories/FunctionListRepository.kt
@@ -0,0 +1,121 @@
+package com.pwc.calculatorv2.data.repositories
+
+import android.content.Context
+import com.pwc.calculatorv2.data.datasources.FunctionListDataSource
+import com.pwc.calculatorv2.data.responses.FunctionListResponse
+import kotlinx.coroutines.flow.flow
+import com.pwc.calculatorv2.data.models.Function
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.flowOn
+
+class FunctionListRepository (context: Context) {
+ private val dataSource = FunctionListDataSource(context)
+
+ fun getFunctionList() = flow {
+ try {
+ val functionList = dataSource.getFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn(Dispatchers.IO)
+
+ fun getPlusFunctionList() = flow {
+ try {
+ val functionList = dataSource.getPlusFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn(Dispatchers.IO)
+
+ fun getMinusFunctionList() = flow {
+ try {
+ val functionList = dataSource.getMinusFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn(Dispatchers.IO)
+
+ fun getPerFunctionList() = flow {
+ try {
+ val functionList = dataSource.getPerFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn(Dispatchers.IO)
+
+ fun getDividedFunctionList() = flow {
+ try {
+ val functionList = dataSource.getDividedFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn(Dispatchers.IO)
+
+ fun addFunction(function: Function) = flow {
+ try {
+ val functionList = dataSource.addFunction(function)
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn((Dispatchers.IO))
+
+ fun removeFunction(function: Function) = flow {
+ try {
+ val functionList = dataSource.removeFunction(function)
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn((Dispatchers.IO))
+
+ fun wipeFunctionList() = flow {
+ try {
+ val functionList = dataSource.wipeFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn((Dispatchers.IO))
+
+ fun wipePlusFunctionList() = flow {
+ try {
+ val functionList = dataSource.wipePlusFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn((Dispatchers.IO))
+
+ fun wipeMinusFunctionList() = flow {
+ try {
+ val functionList = dataSource.wipeMinusFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn((Dispatchers.IO))
+
+ fun wipePerFunctionList() = flow {
+ try {
+ val functionList = dataSource.wipePerFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn((Dispatchers.IO))
+
+ fun wipeDividedFunctionList() = flow {
+ try {
+ val functionList = dataSource.wipeDividedFunctionList()
+ emit(FunctionListResponse.Success( functionList ))
+ } catch (e: Exception) {
+ emit(FunctionListResponse.Error(e.message ?: "Error"))
+ }
+ }.flowOn((Dispatchers.IO))
+} \ No newline at end of file
diff --git a/app/src/main/java/com/pwc/calculatorv2/data/responses/FunctionListResponse.kt b/app/src/main/java/com/pwc/calculatorv2/data/responses/FunctionListResponse.kt
new file mode 100644
index 0000000..b2a75ca
--- /dev/null
+++ b/app/src/main/java/com/pwc/calculatorv2/data/responses/FunctionListResponse.kt
@@ -0,0 +1,8 @@
+package com.pwc.calculatorv2.data.responses
+
+import com.pwc.calculatorv2.data.models.Function
+
+sealed class FunctionListResponse {
+ data class Success(val functionList: List<Function>) : FunctionListResponse()
+ data class Error(val error: String): FunctionListResponse()
+}
diff --git a/app/src/main/java/com/pwc/calculatorv2/data/viewmodels/CalculatorViewModel.kt b/app/src/main/java/com/pwc/calculatorv2/data/viewmodels/CalculatorViewModel.kt
new file mode 100644
index 0000000..bbb270a
--- /dev/null
+++ b/app/src/main/java/com/pwc/calculatorv2/data/viewmodels/CalculatorViewModel.kt
@@ -0,0 +1,316 @@
+package com.pwc.calculatorv2.data.viewmodels
+
+import android.content.Context
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.pwc.calculatorv2.data.repositories.FunctionListRepository
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import com.pwc.calculatorv2.data.models.Function
+import com.pwc.calculatorv2.data.responses.FunctionListResponse
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+
+class CalculatorViewModel(context: Context, private val repository: FunctionListRepository = FunctionListRepository(context)) : ViewModel() {
+ private val mutableState = MutableStateFlow(CalculatorViewState())
+ val calculatorViewState: StateFlow<CalculatorViewState> = mutableState
+ val index = mutableStateOf(-1)
+
+
+ fun getFunctionList() {
+ mutableState.value = mutableState.value.copy(isLoading = true)
+ repository.getFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ index.value = mutableState.value.functionList?.lastIndex ?: -1
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun getPlusFunctionList() {
+ mutableState.value = mutableState.value.copy(isLoading = true)
+ repository.getPlusFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun getMinusFunctionList() {
+ mutableState.value = mutableState.value.copy(isLoading = true)
+ repository.getMinusFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun getPerFunctionList() {
+ mutableState.value = mutableState.value.copy(isLoading = true)
+ repository.getPerFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun getDivideFunctionList() {
+ mutableState.value = mutableState.value.copy(isLoading = true)
+ repository.getDividedFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ private fun addFunction(function: Function) {
+ repository.addFunction(function)
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ index.value = mutableState.value.functionList?.lastIndex ?: -1
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun removeFunction(function: Function) {
+ repository.removeFunction(function)
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun wipeFunctionList() {
+ repository.wipeFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun wipePlusFunctionList() {
+ repository.wipePlusFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun wipeMinusFunctionList() {
+ repository.wipeMinusFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun wipePerFunctionList() {
+ repository.wipePerFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun wipeDividedFunctionList() {
+ repository.wipeDividedFunctionList()
+ .onEach { response ->
+ when (response) {
+ is FunctionListResponse.Success ->
+ mutableState.value =
+ mutableState.value.copy(functionList = response.functionList)
+ is FunctionListResponse.Error ->
+ mutableState.value =
+ mutableState.value.copy(error = response.error)
+ }
+ }
+ .launchIn(viewModelScope)
+ }
+
+ fun showLast(
+ ):String {
+ var string = ""
+ val functionList = mutableState.value.functionList
+ if (!functionList.isNullOrEmpty()){
+ if (index.value < 0 || index.value > functionList.lastIndex){
+ index.value = functionList.lastIndex
+ }
+ string = functionList[index.value].function
+ index.value = index.value - 1
+ return string
+ }
+ return string
+ }
+
+ fun calculateResult(
+ expression: MutableState<String>,
+ ) {
+ // Calculate the result of the expression
+ val expressionValue = expression.value
+ val result = try {
+ if(expressionValue != "" || expressionValue.contains(" ")){
+ val numericResult = evaluateExpression(expressionValue)
+ numericResult.toString()
+ } else if(!expressionValue.contains(" ")){
+ expressionValue
+ }
+ else
+ {
+ ""
+ }
+ } catch (e: Exception) {
+ "ErrorHello"
+ }
+
+ addFunction(Function(function = expressionValue))
+ expression.value = result
+ }
+
+ private fun evaluateExpression(expression: String): Double {
+ var modifiedExpression = expression
+
+ while (modifiedExpression.contains("(")) {
+ val openingIndex = modifiedExpression.lastIndexOf("(")
+ val closingIndex = modifiedExpression.indexOf(")", openingIndex)
+ val innerExpression = modifiedExpression.substring(openingIndex + 1, closingIndex)
+ val innerResult = evaluateExpression(innerExpression)
+
+ // Replace the inner expression (within parentheses) with its result
+ modifiedExpression =
+ modifiedExpression.replace("($innerExpression)", innerResult.toString())
+// modifiedExpression = modifiedExpression.replaceRange(
+// openingIndex -1,
+// closingIndex,
+// innerResult.toString()
+// )
+
+ }
+
+ val parts = modifiedExpression.split(" ").toMutableList()
+ var operator: String = ""
+ var result: Double = 0.0
+
+
+ while (parts.contains("*")) {
+ multiply(parts)
+ }
+ while (parts.contains("/")) {
+ divide(parts)
+ }
+
+ parts.forEachIndexed { _ , unit ->
+ if (unit.toDoubleOrNull() != null) {
+ val operand = unit.toDouble()
+ when (operator) {
+ "" -> result = operand
+ "+" -> result += operand
+ "-" -> result -= operand
+ }
+ } else {
+ operator = unit.trim()
+ }
+ }
+
+ return result
+ }
+
+
+ private fun divide(parts: MutableList<String>) {
+ val indexOfSymbol = parts.indexOf("/")
+ parts[indexOfSymbol] = (parts[indexOfSymbol - 1].toDouble() / parts[indexOfSymbol + 1].toDouble()).toString()
+ parts.removeAt(indexOfSymbol - 1)
+ parts.removeAt(indexOfSymbol)
+ }
+
+ private fun multiply(parts: MutableList<String>) {
+ val indexOfSymbol = parts.indexOf("*")
+ parts[indexOfSymbol] = (parts[indexOfSymbol - 1].toDouble() * parts[indexOfSymbol + 1].toDouble()).toString()
+ parts.removeAt(indexOfSymbol - 1)
+ parts.removeAt(indexOfSymbol)
+ }
+
+}
+data class CalculatorViewState(
+ val functionList: List<Function>? = null,
+ val error: String? = null,
+ val isLoading: Boolean = false
+)