Kotlin if statement fails - android

I have following if statement but it always fails to show correct data
if(!currentItem.address.toString().isNullOrEmpty() && !useraddress.isNullOrEmpty()) {
holder.distanceca.isVisible = true
} else {
holder.distanceca.isVisible = false
}
Explanation
Based on my sample data useraddress is null so it suppose to fall into holder.distanceca.isVisible = false but instead it's returning holder.distanceca.isVisible = true
PS: for my purpose of running holder.distanceca.isVisible = true both currentItem.address and useraddress must have values if any of them is empty or null it should hide the element.
Any idea how to properly make if statement in kotlin?

Solved
Working code
if(!currentItem.address.isNullOrEmpty() && !useraddress.isNullOrEmpty()) {
val geoCoder = Geocoder(context)
// laundry location
val arrs1 = geoCoder.getFromLocationName(currentItem.address, 1)
if (arrs1?.isNotEmpty() == true) {
address = arrs1[0]
}
// customer location
val arrs = geoCoder.getFromLocationName(useraddress, 1)
if (arrs?.isNotEmpty() == true) {
usera = arrs[0]
}
if (arrs1?.isNotEmpty() == true && arrs?.isNotEmpty() == true) {
holder.distanceca.isVisible = true
val locationA = Location(currentItem.name)
locationA.latitude = address?.latitude ?: 0.0
locationA.longitude = address?.longitude ?: 0.0
val locationB = Location("You")
locationB.latitude = usera?.latitude ?: 0.0
locationB.longitude = usera?.longitude ?: 0.0
val distance = DecimalFormat("##.##").format(locationA.distanceTo(locationB) / 1000)
holder.distanceca.text = "${distance} KM"
} else {
holder.distanceca.isVisible = false
}
}
I've add extra if condition to my code and that fixed it somehow (honestly, I am not sure why is that myself :D )
if (arrs1?.isNotEmpty() == true && arrs?.isNotEmpty() == true) {
//
}

Try doing this:
if(!currentItem.address.toString().isNullOrEmpty()) {
useraddress?.let{
if (!it.isNullOrEmpty())
holder.distanceca.isVisible = true
else
holder.distanceca.isVisible = false
}?.let{
holder.distanceca.isVisible = false
}
}

Related

How to show multiple edit text error simultaneously?

I want to validate text input, but how to show multiple edit text error simultaneously??
Here is my code
binding.btnCalculate.setOnClickListener() {
val panjang = binding.etPanjang.text
val lebar = binding.etLebar.text
val tinggi = binding.etTinggi.text
if (TextUtils.isEmpty(binding.etPanjang.text)) {
binding.etPanjang.setError("Field must be filled")
} else if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etLebar.setError("Field must be filled")
} else if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etTinggi.setError("Field must be filled")
} else {
val action = InputFragmentDirections.actionInputFragmentToOutputFragment(
panjang.toString().toInt(),
lebar.toString().toInt(),
tinggi.toString().toInt()
)
findNavController().navigate(
action
)
}
}
Result
I Want all edit text that empty is showing error, not only one edit text
You just need to change if .. else to if only for each condition so each condition can be checked and set error if input is not valid
replace your code with below
binding.btnCalculate.setOnClickListener() {
val panjang = binding.etPanjang.text
val lebar = binding.etLebar.text
val tinggi = binding.etTinggi.text
var isAnyError = false
if (TextUtils.isEmpty(binding.etPanjang.text)) {
binding.etPanjang.setError("Field must be filled")
isAnyError = true
}else{
binding.etPanjang.setError(null)
}
if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etLebar.setError("Field must be filled")
isAnyError = true
}else{
binding.etLebar.setError(null)
}
if (TextUtils.isEmpty(binding.etLebar.text)) {
binding.etTinggi.setError("Field must be filled")
isAnyError = true
}else{
binding.etTinggi.setError(null)
}
if(!isAnyError){
val action = InputFragmentDirections.actionInputFragmentToOutputFragment(
panjang.toString().toInt(),
lebar.toString().toInt(),
tinggi.toString().toInt()
)
findNavController().navigate(
action
)
}
}

Kotlin Big Decimal division returning inaccurate results

I am building a calculator with Kotlin and android studio (my first project). All equations were working properly until recent tweaks with decimal format. Now large division operations returns inaccurate results.
For example 99,999,999 / 9% (0.09) = 1.11111110000E9
But 9% / 99,999,999 = 0 when it should = 9.0000000009E-10
Is this because the current DecimalFormat cannot return the negative exponent?
EDIT: after more testing I've found that changing division method to
doubleNum = doubleNum.divide(numBigDecimal, 10, BigDecimal.ROUND_HALF_UP).stripTrailingZeros()
running the same equation will return 9E-10 before formatting. After decimal format the result shows as "." only with no digits
// enum class and class properties
enum class LogicTypes {
None,Add,Subtract,Multiply,Divide
}
class MainActivity : AppCompatActivity() {
private var logicActive = false
private var currentLogic = LogicTypes.None
private var currentNum = BigDecimal.ZERO
private var displayNum = ""
private var memoryNum = BigDecimal.ZERO
// add num function - buttons 0-9 send indices to num arg
fun addNum(num: BigDecimal) {
val inputNum = num.toString()
if (displayNum == "0" && inputNum == "0") {
return
}
if (displayNum.contains(".")) {
val stringForm = displayNum.substring(displayNum.indexOf('.'), displayNum.length)
if (stringForm.length > 10) {
clearCalc()
Toast.makeText(this, "Only 10 digits after decimal point allowed.", Toast.LENGTH_SHORT).show()
return
}
}
if (displayNum.length >= 15 && !displayNum.contains(".")) {
clearCalc()
Toast.makeText(this, "Maximum of 15 digits allowed.", Toast.LENGTH_SHORT).show()
return
}
if (inputNum == "0" && currentNum.toDouble() == 0.0 && displayNum.contains(".")) {
if (displayNum.length > 11) {
clearCalc()
Toast.makeText(this, "Only 10 digits after decimal point allowed.", Toast.LENGTH_SHORT).show()
return
}
displayNum = "$displayNum$inputNum"
textView.text = displayNum
return
}
if (logicActive) {
logicActive = false
displayNum = "0"
}
displayNum = "$displayNum$inputNum"
updateDisplayNum()
}
// set currentNum and send to numFormat function to update textView
fun updateDisplayNum() {
if (currentNum.toString().length > 15) {
clearCalc()
Toast.makeText(this, "Maximum of 15 digits allowed.", Toast.LENGTH_SHORT).show()
return
}
val numBigDecimal = displayNum.toBigDecimal()
if(currentLogic == LogicTypes.None) {
if(displayNum.contains("-") && currentNum == BigDecimal.ZERO) {
textView.text = displayNum
return
} else {
currentNum = numBigDecimal
}
}
numFormat()
}
// format decimal and integers and update textview with exponent
fun numFormat() {
val numBigDecimal = displayNum.toBigDecimal()
if(displayNum.contains(".")) {
val stringForm = displayNum.substring(displayNum.indexOf('.'), displayNum.length)
var numFormat = "#,##0."
if(stringForm.length > 1) {
for (num in stringForm.indices-1) {
numFormat += "0"
}
}
if (displayNum.length > 16 || stringForm.length > 9) {
// stringform length > 9 works for division result - anything higher returns trailing zeros.
// anything under 11 for stringform condition results in inaccurate input -
// adding decimal through addNum() will return Exponential notation before logic
// I only want E notation on result only- have yet to test other equations -
// this can also make it impossible to take the result and conduct another logic operation as the result appends E0
// and thus the trailing digits after decimal is greater than 10
numFormat = "0.0000000000E0"
}
val df = DecimalFormat(numFormat)
textView.text = df.format(numBigDecimal)
return
}
var df = DecimalFormat("#,###")
if (displayNum.length > 15) {
df = DecimalFormat("0.0000000000E0")
}
textView.text = df.format(numBigDecimal)
}
// change logic to enum mode when button operator pressed
fun changeLogic(mode: LogicTypes) {
currentLogic = mode
logicActive = true
}
// calculate function
fun calculate() {
if (logicActive || currentLogic == LogicTypes.Divide && displayNum.toBigDecimal() == BigDecimal.ZERO
|| currentNum == BigDecimal.ZERO) {
Log.i(LOG_TAG, "caught the zero")
return
}
val numBigDecimal = displayNum.toBigDecimal()
var doubleNum = currentNum
val currentNumString = doubleNum.stripTrailingZeros().toPlainString()
val numBigDecimalString = numBigDecimal.stripTrailingZeros().toPlainString()
val addMsg = getString(R.string.calc_message, currentNumString, "+", numBigDecimalString)
val subMsg = getString(R.string.calc_message, currentNumString, "-", numBigDecimalString)
val multiMsg = getString(R.string.calc_message, currentNumString, "*", numBigDecimalString)
val divMsg = getString(R.string.calc_message, currentNumString, "/", numBigDecimalString)
when(currentLogic) {
LogicTypes.Add -> {
hintView.text = addMsg
doubleNum += numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.Subtract -> {
hintView.text = subMsg
doubleNum -= numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.Multiply -> {
hintView.text = multiMsg
doubleNum *= numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.Divide -> {
hintView.text = divMsg
doubleNum /= numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.None -> return
}
currentLogic = LogicTypes.None
displayNum = doubleNum.toString()
updateDisplayNum()
logicActive = true
}
Ok the issue was that I was using this in the calculate function.
displayNum = doubleNum.toString()
Changing to .toPlainString() gives correct notations. There are still issues with formatting but I'll see if I can work those out on my own
EDIT: I solved the formatting issue in the numFormat by creating a boolean property, setting it to true in the calculation function, and passing it to the numFormat condition:
if (displayNum.length > 16 || stringForm.length > 9 && resultActive) {
numFormat = "0.0000000000E0"
resultActive = false
}
This way the format only applies to calculated numbers
I also passed it to the addNum function for calculations made after the first calculation
if(resultActive) {
resultActive = false
}

Do we have better way to simplify this code?

viewModel.sectionTypeId, specialSectionId, specialSectionId -> These values are commonly used both cases
if (data.section_type == "customized") {
viewModel.sectionTypeId = data.id ?: 0
viewModel.specialSectionId = data.id ?: 0
viewModel.specialSectionName = data.name ?: ""
} else {
viewModel.specialSectionId = 0
viewModel.specialSectionName = ""
viewModel.sectionTypeId = 0
}
You could do this:
viewModel.apply {
val customized = data.section_type == "customized"
sectionTypeId = if(customized) data.id ?: 0 else 0
specialSectionId = if(customized) data.id ?: 0 else 0
specialSectionName = if(customized) data.name ?: "" else ""
}
Since there is no ternary operator in kotlin, you can use if expressions and assign repeated code to values like this:
viewModel.apply {
val customized = data.section_type == "customized"
val iD = if(customized) data.id ?: 0 else 0
sectionTypeId = iD
specialSectionId = iD
specialSectionName = if(customized) data.name ?: "" else ""
}

Generate the same maze with a seed

Im followed a tutorial to create a maze with Recursive Backtracking and it works great.
Im trying to create a game where people get on the same maze, and if someone wins, it creates a new maze and everyones current maze gets updated.
So what i was thinking is to have a seed to create the same maze and pass that seed to all the players so they can have the same maze.
Is there a way to modify it so i can give the maze a seed and it creates always the same maze?
This is what i have now:
It uses a Cell class (posx,posy)
class Cell(var col:Int = 0, var row: Int = 0){
var topWall = true
var leftWall = true
var bottomWall = true
var rightWall = true
var visited = false
}
fun createMaze(){
var stack = Stack<Cell>()
var current:Cell
var next:Cell?
for(x in 0 until COLS){
for(y in 0 until ROWS){
cells[x][y] = Cell(x,y)
}
}
player = cells[0][0]
exit = cells [COLS-1][ROWS-1]
current = cells[0][0]
current.visited = true
do{
next = getNeighbour(current)
if(next != null) {
removeWall(current, next)
stack.push(current)
current = next
current.visited = true
}else{
current = stack.pop()
}
}while (!stack.empty())
}
fun getNeighbour(cell:Cell): Cell? {
var vecinos: ArrayList<Cell> = ArrayList()
//vecino izquierda
if(cell.col > 0) {
if (!cells[cell.col - 1][cell.row].visited) {
vecinos.add(cells[cell.col - 1][cell.row])
}
}
//vecino derecha
if(cell.col < COLS - 1) {
if (!cells[cell.col + 1][cell.row].visited) {
vecinos.add(cells[cell.col + 1][cell.row])
}
}
//vecino arriba
if(cell.row > 0) {
if (!cells[cell.col][cell.row - 1].visited) {
vecinos.add(cells[cell.col ][cell.row - 1])
}
}
//vecino abajo
if(cell.row < ROWS - 1) {
if (!cells[cell.col][cell.row + 1].visited) {
vecinos.add(cells[cell.col][cell.row + 1])
}
}
if (vecinos.size > 0) {
var index = random.nextInt(vecinos.size)
return vecinos[index]
}else {
return null
}
}
fun removeWall(current:Cell,next:Cell){
if (current.col == next.col && current.row == next.row +1){
current.topWall = false
next.bottomWall = false
}
if (current.col == next.col && current.row == next.row -1){
current.bottomWall = false
next.topWall = false
}
if (current.col == next.col + 1 && current.row == next.row){
current.leftWall = false
next.rightWall = false
}
if (current.col == next.col - 1 && current.row == next.row){
current.rightWall = false
next.leftWall = false
}
}
If you want to pass a seed to create the maze, then you have to make sure that all of the players are using the same random number generator. Which means you have to supply your own random number generator implementation.
The application would seed the random number generator with the value you pass, and then it should deterministically generate the same sequence of random numbers for each client.
Note also that you can't ever change the random number generator implementation unless you can prove that the new implementation will generate exactly the same sequence of numbers that the original did.

Android - Make function false/not run

I have a setOnClickListener on two buttons that just runs the code in two functions.
I want to create a safe call so when I click the buttons the app doesn't crash. I thought I would have to make them false or something, but apparently it doesn't work.
How should I do it?
Thanks
if (weightView.text.isEmpty() && percentageView.text.isEmpty()) {
calculation() == false
lbsCalculation() == false
} else {
calculation()
lbsCalculation()
}
These are my two clickListeners
calculateBtn.setOnClickListener{
calculation()
}
lbsCalculationBtn.setOnClickListener{
lbsCalculation()
}
Functions:
fun calculation () {
var weightValue = weightView.text.toString().toInt()
var percentageValue = percentageView.text.toString().toInt()
var result = (weightValue * percentageValue) / 100.toDouble()
var resultFormat = "%.1f KG".format(result)
resultView.text = resultFormat.toString()
}
fun lbsCalculation() {
var weightValue = weightView.text.toString().toInt()
var percentageValue = percentageView.text.toString().toInt()
var result = ((weightValue * percentageValue) / 100) * 2.2.toDouble()
var resultFormat = "%.1f LBS".format(result)
resultView.text = resultFormat.toString()
}
=================
Picture
Do it inside your method. Something like this:
public class calculation(String weightView, String percentageView){
//you make a condition that should do something if strings are empty
if(weightView && percentageView == null)
//DO WHAT YOU WANT
}else{
//Show an alert or something that your EditText is empty.
}
and should call it in like this:
calculateBtn.setOnClickListener{
calculation(weightView.getText.toString(),percentageView.getText.toString())
}
======EDIT=======
Your function should look like this:
fun calculation(weightValue: String,percentageValue: String)
{
if(weightValue == null && percentageValue == null ){
var myWeightValue = weightValue.toInt();
var myPercentageValue = percentageValue.toInt();
var result = (myWeightValue * myPercentageValue) / 100
var resultFormat = "%.1f KG".format(result)
resultView.text = resultFormat
}
else {
**SHOW A MESSAGE LIKE A TOAST OR ALERTDIALOG TO LET THE USER KNOW THAT WEIGHT AND PERCENTAGE IS REQUIRED**
}
}
fun lbsCalculation() {
var weightValue = weightView.text.toString().toInt()
var percentageValue = percentageView.text.toString().toInt()
var result = ((weightValue * percentageValue) / 100) * 2.2
var resultFormat = "%.1f LBS".format(result)
resultView.text = resultFormat
}
Your onClick should look like this:
calculateBtn.setOnClickListener{
calculation(weightView.text,percentageView.text)
}

Categories

Resources