All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.skillw.pouvoir.util.calculate.FormulaParser.kt Maven / Gradle / Ivy

There is a newer version: 1.6.7-beta-6
Show newest version
package com.skillw.pouvoir.util.calculate

import com.skillw.pouvoir.util.calculate.CalcOperator.Companion.isCalcOperator
import com.skillw.pouvoir.util.calculate.CalcOperator.Companion.toCalcOperator
import taboolib.common.platform.function.warning
import java.util.*

private fun String.toCalcInfix(): ArrayList {
    //将数字与运算符分开,按中缀表达式顺序排列在List中
    val infix = ArrayList()
    with(filter { it != ' ' }) {
        var begin = 0
        forEachIndexed loop@{ index, char ->
            if (!char.isCalcOperator()) return@loop
            val num = substring(begin, index)
            begin = index + 1
            if (num.isNotEmpty()) {
                infix += num.toDouble()
            }
            infix += char.toCalcOperator()
        }
        substring(begin).toDoubleOrNull()?.let {
            infix += it
        }
    }
    return infix
}

private fun Stack.nextNotLessThan(calcOperator: CalcOperator): Boolean {
    return isNotEmpty() && peek() != CalcOperator.LEFT_BRACKET && peek().priority >= calcOperator.priority
}

/**
 * To suffix
 *
 * @return
 */
private fun List.toCalcSuffix(): Queue {
    val suffix = ArrayDeque()
    val operators = Stack()
    forEach {
        if (it is Double) {
            suffix.offerLast(it)
            return@forEach
        }
        with(operators) {
            when (val calcOperator = it as CalcOperator) {
                CalcOperator.LEFT_BRACKET -> push(calcOperator)
                CalcOperator.RIGHT_BRACKET -> {
                    while (isNotEmpty() && peek() != CalcOperator.LEFT_BRACKET) {
                        suffix.offerLast(pop())
                    }
                    if (isNotEmpty())
                        pop()
                }

                else -> {
                    while (nextNotLessThan(calcOperator)) {
                        suffix.offerLast(pop())
                    }
                    push(calcOperator)
                }
            }
        }
    }
    while (!operators.isEmpty()) {
        suffix.offerLast(operators.pop())
    }
    return suffix
}

private fun Queue.calc(): Double {
    val calcStack: Stack = Stack()
    while (isNotEmpty()) {
        val obj = poll()
        if (obj is Double) {
            calcStack.push(obj)
            continue
        }
        val calcOperator = obj as CalcOperator
        val a = if (calcStack.isEmpty()) 0.0 else calcStack.pop()
        val b = if (calcStack.isEmpty()) 0.0 else calcStack.pop()
        calcStack.push(calcOperator.calc(a, b))
    }
    return calcStack.pop()
}

internal fun String.calculateInfix(): Double {
    return runCatching {
        filter { it != ' ' }.toCalcInfix().toCalcSuffix().calc()
    }.getOrElse {
        warning("Wrong calculation formula! $this");
        0.0
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy