Skip to content

Commit

Permalink
Merge pull request #54 from you-apps/autoFunctionNames
Browse files Browse the repository at this point in the history
feat(graphing): automatically select distinct function names, e.g. f(x), g(x), ...
  • Loading branch information
Bnyro authored Oct 9, 2024
2 parents b2b4fd3 + f02a3d0 commit 2fd50d8
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 149 deletions.
1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions .idea/runConfigurations.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ object Defaults {
)
val defaultVarNameChars: Set<Char> =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$".toCharArray().toSet()
val defaultFuncNameChars: List<Char> = "fghijklmnopqrstuvw".toList()

fun getDefaultGenericFunctions(): Map<String, EvalFunctionBlock> {
return mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,5 @@ class EvalConfiguration(
this.varNameChars = Defaults.defaultVarNameChars
this.genericConstants = Defaults.defaultGenericConstants.toMutableMap()
this.genericFunctions = Defaults.getDefaultGenericFunctions().toMutableMap()

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ package net.youapps.calcyou.data.graphing

import androidx.compose.ui.graphics.Color

class Function(
data class Function(
val expression: String,
val color: Color,
val name: String,
val function: (Float) -> Float?
) {

companion object {
fun create(expression: String, color: Color): Function {
fun create(expression: String, color: Color, functionName: String): Function {
val compiled: CompiledExpression = Evaluator.compile(expression)
return Function(
expression, color
expression, color, functionName
) { value ->
compiled.execute("x" to value.toDouble())?.toFloat()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,22 @@ import net.youapps.calcyou.viewmodels.GraphViewModel
@Composable
fun AddNewFunctionDialog(
graphViewModel: GraphViewModel,
functionName: String,
initialExpression: String,
initialColor: Color,
onDismissRequest: () -> Unit
) {
Dialog(onDismissRequest) {
DialogContent(
onConfirm = { expression, color ->
graphViewModel.addFunction(expression, color)
graphViewModel.addFunction(expression, color, functionName)
onDismissRequest()
},
onCancel = onDismissRequest,
checkExpression = graphViewModel::checkExpression,
isError = graphViewModel.isError,
errorMessage = graphViewModel.errorText,
functionName = functionName,
initialExpression = initialExpression,
initialColor = initialColor
)
Expand All @@ -67,6 +69,7 @@ private fun DialogContent(
checkExpression: (String) -> Unit,
isError: Boolean,
errorMessage: String,
functionName: String,
initialExpression: String = "",
initialColor: Color = rainbowColors.first(),
) {
Expand All @@ -92,7 +95,7 @@ private fun DialogContent(
isError = isError,
prefix = {
Text(
text = "f(x) = ", style = TextStyle(
text = "${functionName}(x) = ", style = TextStyle(
fontFamily = FontFamily.Serif,
fontWeight = FontWeight.Medium,
fontSize = MaterialTheme.typography.bodyLarge.fontSize,
Expand Down Expand Up @@ -149,6 +152,7 @@ private fun DialogContentPreview() {
onCancel = {},
checkExpression = {},
isError = true,
errorMessage = "Invalid token at index 0"
errorMessage = "Invalid token at index 0",
functionName = "f"
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Clear
import androidx.compose.material3.BottomSheetScaffold
Expand All @@ -26,13 +29,17 @@ import androidx.compose.runtime.remember
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.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import net.youapps.calcyou.R
import net.youapps.calcyou.data.graphing.Defaults
import net.youapps.calcyou.data.graphing.Function
import net.youapps.calcyou.ui.components.AddNewFunctionDialog
import net.youapps.calcyou.viewmodels.GraphViewModel
Expand Down Expand Up @@ -68,8 +75,11 @@ fun GraphingScreen(graphViewModel: GraphViewModel = viewModel()) {
})
Button(
modifier = Modifier.align(Alignment.CenterHorizontally),
onClick = { showAddFunctionDialog = true }) {
Text(text = "Add Function")
onClick = {
graphViewModel.updateSelectedFunction(-1)
showAddFunctionDialog = true
}) {
Text(text = stringResource(R.string.add_new_function))
}
}
}) {
Expand All @@ -82,6 +92,7 @@ fun GraphingScreen(graphViewModel: GraphViewModel = viewModel()) {
graphViewModel.updateSelectedFunction(-1)
showAddFunctionDialog = false
},
functionName = remember(graphViewModel.selectedFunctionIndex) { graphViewModel.functionName },
initialColor =
remember(graphViewModel.selectedFunctionIndex) { graphViewModel.functionColor },
initialExpression =
Expand All @@ -97,32 +108,43 @@ fun FunctionList(
onClickFunction: (Int) -> Unit,
onClickRemove: (Int) -> Unit
) {
Column(modifier = modifier) {
functions.forEachIndexed { index, function ->
LazyColumn(modifier = modifier) {
itemsIndexed(
functions,
key = { index, function -> "$index-${function.hashCode()}" }) { index, function ->
FunctionRow(
functionName = function.name,
text = function.expression,
color = function.color,
onClick = { onClickFunction(index) },
onClickRemove = {
onClickRemove(index)
})
}
)
Divider(Modifier.fillMaxWidth())
}
}
}

@Composable
fun FunctionRow(text: String, color: Color, onClick: () -> Unit, onClickRemove: () -> Unit) {
fun FunctionRow(
functionName: String,
text: String,
color: Color,
onClick: () -> Unit,
onClickRemove: () -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp)
.clickable { onClick.invoke() },
.clip(RoundedCornerShape(8.dp))
.clickable { onClick.invoke() }
.padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {

Text(
text = "f(x) = ", style = TextStyle(
text = "${functionName}(x) = ", style = TextStyle(
fontFamily = FontFamily.Serif,
fontWeight = FontWeight.Bold,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
Expand Down
32 changes: 27 additions & 5 deletions app/src/main/java/net/youapps/calcyou/viewmodels/GraphViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.AndroidViewModel
import net.youapps.calcyou.R
import net.youapps.calcyou.data.graphing.Defaults
import net.youapps.calcyou.data.graphing.Evaluator
import net.youapps.calcyou.data.graphing.Function
import net.youapps.calcyou.data.graphing.Window
import net.youapps.calcyou.ui.components.rainbowColors
import java.text.ParseException
import kotlin.random.Random

class GraphViewModel(private val application: Application) : AndroidViewModel(application) {
val context: Context
private val context: Context
get() = application.applicationContext
var window by mutableStateOf(Window(), neverEqualPolicy())
val functions = mutableStateListOf<Function>()
Expand All @@ -30,17 +32,22 @@ class GraphViewModel(private val application: Application) : AndroidViewModel(ap

var selectedFunctionIndex by mutableIntStateOf(-1)
private set
var functionColor by mutableStateOf(Color.Red)
var functionName by mutableStateOf(Defaults.defaultFuncNameChars.first().toString())

var functionColor by mutableStateOf(rainbowColors.first())

var expression by mutableStateOf("")

fun updateSelectedFunction(index: Int) {
selectedFunctionIndex = index
if (index == -1) {
expression = ""
functionName = getFuncName(functions.size)
functionColor = getFuncColor(functions.size)
return
}
val function = functions[index]
functionName = function.name
functionColor = function.color
expression = function.expression
}
Expand All @@ -64,16 +71,31 @@ class GraphViewModel(private val application: Application) : AndroidViewModel(ap
}
}

fun addFunction(expression: String, color: Color) {
fun addFunction(expression: String, color: Color, functionName: String) {
if (selectedFunctionIndex != -1) {
functions[selectedFunctionIndex] = Function.create(expression, color)
functions[selectedFunctionIndex] = Function.create(expression, color, functionName)
updateSelectedFunction(-1)
return
}
functions.add(Function.create(expression, color))
functions.add(Function.create(expression, color, functionName))
}

fun removeFunction(index: Int) {
functions.removeAt(index)

// update the other functions following the delete one with new function names and colors
for (i in index until functions.size) {
functions[index] = functions[index].copy(name = getFuncName(i), color = getFuncColor(i))
}
}

private fun getFuncName(index: Int): String {
return Defaults.defaultFuncNameChars[
index % Defaults.defaultFuncNameChars.size
].toString()
}

private fun getFuncColor(index: Int): Color {
return rainbowColors[index % rainbowColors.size]
}
}
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 3 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#Sat Nov 04 16:04:48 IST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 2fd50d8

Please sign in to comment.