Move to formatting.kt

This commit is contained in:
DBotThePony 2023-01-15 20:10:26 +07:00
parent 45f22762c6
commit 2889d70648
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 395 additions and 368 deletions

View File

@ -0,0 +1,395 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.isNegative
import ru.dbotthepony.mc.otm.core.math.isZero
import java.math.BigDecimal
import java.math.BigInteger
fun BigInteger.formatReadableNumber(): String {
if (isZero) {
return "0"
}
val strValue = toString()
val absLength = strValue.length - (if (isNegative) 1 else 0)
val remainder = absLength % 3
var groups = absLength / 3
if (remainder == 0) {
groups--
}
val buffer = CharArray((if (remainder == 0) 3 else remainder) + groups * 4 + if (isNegative) 1 else 0)
var c = 0
var index = buffer.size - 1
for (i in strValue.length - 1 downTo (if (isNegative) 1 else 0)) {
c++
if (c == 4) {
buffer[index] = ' '
index--
c = 1
}
buffer[index] = strValue[i]
index--
}
if (isNegative) {
buffer[index] = '-'
}
return String(buffer)
}
fun BigDecimal.determineSiPrefix(): SiPrefix? {
if (isZero) {
return null
}
var num = this
if (isNegative) {
num = -this
}
var prev: SiPrefix? = null
if (num >= BigDecimal.ONE) {
for (value in SiPrefix.MULTIPLIES) {
if (value.decimal <= num) {
prev = value
} else {
break
}
}
} else {
for (value in SiPrefix.DECIMALS) {
if (value.decimal >= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun BigDecimal.formatSiTranslatable(): Component {
if (isZero) {
return TextComponent("0.00")
} else if (this == BigDecimal.ONE) {
return TextComponent("1.00")
}
return TextComponent("1.00")
}
fun BigInteger.determineSiPrefix(): SiPrefix? {
if (isZero) {
return null
}
var num = this
if (isNegative) {
num = -this
}
var prev: SiPrefix? = null
if (num >= BigInteger.ONE) {
for (value in SiPrefix.MULTIPLIES) {
if (value.integer!! <= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun BigInteger.formatSi(decimalPlaces: Int = 2): String {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return toString() // + "." + "0".repeat(decimalPlaces)
val isNegative = isNegative
val arr = (if (isNegative) -this else this).divideAndRemainder(prefix.integer)
val divided = arr[0].toString()
val remainder = arr[1].toString()
if (decimalPlaces == 0) {
if (isNegative) {
return "-" + divided + prefix.symbol
} else {
return divided + prefix.symbol
}
}
@Suppress("NAME_SHADOWING")
val decimalPlaces = decimalPlaces.coerceAtMost(prefix.power)
val add = (if (isNegative) 1 else 0)
val buffer = CharArray(divided.length + 2 + decimalPlaces + add)
buffer[buffer.size - 1] = prefix.symbol
if (isNegative) {
buffer[0] = '-'
}
for (i in divided.indices) {
buffer[add + i] = divided[i]
}
buffer[add + divided.length] = '.'
for (i in 0 until decimalPlaces) {
buffer[add + i + divided.length + 1] = prefix.paddedIndex(remainder, i)
}
return String(buffer)
}
fun BigInteger.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString(decimalPlaces)) else if (suffix is Component) TextComponent(
toString(decimalPlaces) + suffix.string
) else TextComponent(toString(decimalPlaces) + suffix)
val isNegative = isNegative
val arr = (if (isNegative) -this else this).divideAndRemainder(prefix.integer)
val divided = arr[0].toString()
val remainder = arr[1].toString()
if (decimalPlaces == 0) {
if (isNegative) {
return TranslatableComponent(prefix.formatLocaleKey, "-$divided", suffix)
} else {
return TranslatableComponent(prefix.formatLocaleKey, divided + prefix.symbol, suffix)
}
}
@Suppress("NAME_SHADOWING")
val decimalPlaces = decimalPlaces.coerceAtMost(prefix.power)
val add = (if (isNegative) 1 else 0)
val buffer = CharArray(divided.length + 1 + decimalPlaces + add)
if (isNegative) {
buffer[0] = '-'
}
for (i in divided.indices) {
buffer[add + i] = divided[i]
}
buffer[add + divided.length] = '.'
for (i in 0 until decimalPlaces) {
buffer[add + i + divided.length + 1] = prefix.paddedIndex(remainder, i)
}
return TranslatableComponent(prefix.formatLocaleKey, String(buffer), suffix)
}
fun Decimal.determineSiPrefix(): SiPrefix? {
if (isZero) {
return null
}
var num = this
if (isNegative) {
num = -this
}
var prev: SiPrefix? = null
if (num >= Decimal.ONE) {
for (value in SiPrefix.MULTIPLIES) {
if (value.impreciseFraction <= num) {
prev = value
} else {
break
}
}
} else {
for (value in SiPrefix.DECIMALS_IMPRECISE) {
if (value.impreciseFraction >= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun Int.determineSiPrefix(): SiPrefix? {
if (this == 0) {
return null
}
var num = this
if (this < 0) {
num = -this
}
var prev: SiPrefix? = null
if (num >= 1) {
for (value in SiPrefix.MULTIPLIES) {
if (value.int != null && value.int <= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun Double.determineSiPrefix(): SiPrefix? {
if (this == 0.0) {
return null
}
var num = this
if (this < 0) {
num = -this
}
var prev: SiPrefix? = null
if (num >= 1) {
for (value in SiPrefix.MULTIPLIES) {
if (value.double <= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun Decimal.formatSi(decimalPlaces: Int = 2): String {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return toString(decimalPlaces)
return (this / prefix.impreciseFraction).toString(decimalPlaces) + prefix.symbol
}
fun Int.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString()) else if (suffix is Component) TextComponent(
toString() + " " + suffix.string
) else TextComponent(toString() + " " + suffix)
return TranslatableComponent(
prefix.formatLocaleKey,
"%.${decimalPlaces}f".format(this.toFloat() / prefix.int!!.toFloat()),
suffix
)
}
fun Double.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent("%.${decimalPlaces}f".format(this)) else if (suffix is Component) TextComponent(
"%.${decimalPlaces}f".format(this) + " " + suffix.string
) else TextComponent("%.${decimalPlaces}f".format(this) + " " + suffix)
return TranslatableComponent(prefix.formatLocaleKey, "%.${decimalPlaces}f".format(this / prefix.double), suffix)
}
fun Decimal.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString(decimalPlaces)) else if (suffix is Component) TextComponent(
toString(decimalPlaces) + " " + suffix.string
) else TextComponent(toString(decimalPlaces) + " " + suffix)
return TranslatableComponent(
prefix.formatLocaleKey,
(this / prefix.impreciseFraction).toString(decimalPlaces),
suffix
)
}
val POWER_NAME = TranslatableComponent("otm.gui.power.name")
val MATTER_NAME = TranslatableComponent("otm.gui.matter.name")
fun Int.formatPower(decimalPlaces: Int = 2) = formatSiComponent(POWER_NAME, decimalPlaces)
fun Decimal.formatPower(decimalPlaces: Int = 2) = formatSiComponent(POWER_NAME, decimalPlaces)
fun Decimal.formatMatter(decimalPlaces: Int = 2) = formatSiComponent(MATTER_NAME, decimalPlaces)
fun Decimal.formatMatterFull(decimalPlaces: Int = 2) = TranslatableComponent(
"otm.gui.matter.format", formatSiComponent(
MATTER_NAME, decimalPlaces
)
)
fun BigInteger.formatPower(decimalPlaces: Int = 2) = formatSiComponent(POWER_NAME, decimalPlaces)
fun BigInteger.formatMatter(decimalPlaces: Int = 2) = formatSiComponent(MATTER_NAME, decimalPlaces)
fun BigInteger.formatMatterFull(decimalPlaces: Int = 2) = TranslatableComponent(
"otm.gui.matter.format", formatSiComponent(
MATTER_NAME, decimalPlaces
)
)
fun formatPowerLevel(a: Decimal, b: Decimal, decimalPlaces: Int = 2) =
TranslatableComponent("otm.gui.level", a.formatPower(decimalPlaces), b.formatPower(decimalPlaces))
fun formatMatterLevel(a: Decimal, b: Decimal, decimalPlaces: Int = 2) =
TranslatableComponent("otm.gui.level", a.formatMatter(decimalPlaces), b.formatMatter(decimalPlaces))
private fun padded(num: Int): String {
if (num in 0 .. 9) {
return "0$num"
}
return num.toString()
}
fun formatTickDuration(ticks: Int, longFormat: Boolean = false): String {
@Suppress("name_shadowing")
var leftTicks = ticks
// val mTicks = leftTicks % 20
leftTicks /= 20
val seconds = padded(leftTicks % 60)
leftTicks /= 60
if (longFormat) {
if (ticks <= 0) {
return "00:00:00"
} else if (ticks <= 20) {
return ".00000${padded(ticks)}"
}
val minutes = padded(leftTicks % 60)
leftTicks /= 60
val hours = padded(leftTicks)
return "$hours:$minutes:$seconds"
} else {
if (ticks <= 0) {
return "00:00"
} else if (ticks <= 20) {
return ".00${padded(ticks)}"
}
val minutes = leftTicks
if (minutes > 99) {
return "**:**"
}
return "${padded(minutes)}:$seconds"
}
}

View File

@ -1,54 +1,10 @@
package ru.dbotthepony.mc.otm.core.util package ru.dbotthepony.mc.otm.core.util
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.isNegative
import ru.dbotthepony.mc.otm.core.math.isZero
import java.math.BigDecimal import java.math.BigDecimal
import java.math.BigInteger import java.math.BigInteger
fun BigInteger.formatReadableNumber(): String {
if (isZero) {
return "0"
}
val strValue = toString()
val absLength = strValue.length - (if (isNegative) 1 else 0)
val remainder = absLength % 3
var groups = absLength / 3
if (remainder == 0) {
groups--
}
val buffer = CharArray((if (remainder == 0) 3 else remainder) + groups * 4 + if (isNegative) 1 else 0)
var c = 0
var index = buffer.size - 1
for (i in strValue.length - 1 downTo (if (isNegative) 1 else 0)) {
c++
if (c == 4) {
buffer[index] = ' '
index--
c = 1
}
buffer[index] = strValue[i]
index--
}
if (isNegative) {
buffer[index] = '-'
}
return String(buffer)
}
enum class SiPrefix( enum class SiPrefix(
val power: Int, val power: Int,
fractional: Boolean, fractional: Boolean,
@ -133,327 +89,3 @@ enum class SiPrefix(
} }
} }
fun BigDecimal.determineSiPrefix(): SiPrefix? {
if (isZero) {
return null
}
var num = this
if (isNegative) {
num = -this
}
var prev: SiPrefix? = null
if (num >= BigDecimal.ONE) {
for (value in SiPrefix.MULTIPLIES) {
if (value.decimal <= num) {
prev = value
} else {
break
}
}
} else {
for (value in SiPrefix.DECIMALS) {
if (value.decimal >= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun BigDecimal.formatSiTranslatable(): Component {
if (isZero) {
return TextComponent("0.00")
} else if (this == BigDecimal.ONE) {
return TextComponent("1.00")
}
return TextComponent("1.00")
}
fun BigInteger.determineSiPrefix(): SiPrefix? {
if (isZero) {
return null
}
var num = this
if (isNegative) {
num = -this
}
var prev: SiPrefix? = null
if (num >= BigInteger.ONE) {
for (value in SiPrefix.MULTIPLIES) {
if (value.integer!! <= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun BigInteger.formatSi(decimalPlaces: Int = 2): String {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return toString() // + "." + "0".repeat(decimalPlaces)
val isNegative = isNegative
val arr = (if (isNegative) -this else this).divideAndRemainder(prefix.integer)
val divided = arr[0].toString()
val remainder = arr[1].toString()
if (decimalPlaces == 0) {
if (isNegative) {
return "-" + divided + prefix.symbol
} else {
return divided + prefix.symbol
}
}
@Suppress("NAME_SHADOWING")
val decimalPlaces = decimalPlaces.coerceAtMost(prefix.power)
val add = (if (isNegative) 1 else 0)
val buffer = CharArray(divided.length + 2 + decimalPlaces + add)
buffer[buffer.size - 1] = prefix.symbol
if (isNegative) {
buffer[0] = '-'
}
for (i in divided.indices) {
buffer[add + i] = divided[i]
}
buffer[add + divided.length] = '.'
for (i in 0 until decimalPlaces) {
buffer[add + i + divided.length + 1] = prefix.paddedIndex(remainder, i)
}
return String(buffer)
}
fun BigInteger.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString(decimalPlaces)) else if (suffix is Component) TextComponent(toString(decimalPlaces) + suffix.string) else TextComponent(toString(decimalPlaces) + suffix)
val isNegative = isNegative
val arr = (if (isNegative) -this else this).divideAndRemainder(prefix.integer)
val divided = arr[0].toString()
val remainder = arr[1].toString()
if (decimalPlaces == 0) {
if (isNegative) {
return TranslatableComponent(prefix.formatLocaleKey, "-$divided", suffix)
} else {
return TranslatableComponent(prefix.formatLocaleKey, divided + prefix.symbol, suffix)
}
}
@Suppress("NAME_SHADOWING")
val decimalPlaces = decimalPlaces.coerceAtMost(prefix.power)
val add = (if (isNegative) 1 else 0)
val buffer = CharArray(divided.length + 1 + decimalPlaces + add)
if (isNegative) {
buffer[0] = '-'
}
for (i in divided.indices) {
buffer[add + i] = divided[i]
}
buffer[add + divided.length] = '.'
for (i in 0 until decimalPlaces) {
buffer[add + i + divided.length + 1] = prefix.paddedIndex(remainder, i)
}
return TranslatableComponent(prefix.formatLocaleKey, String(buffer), suffix)
}
fun Decimal.determineSiPrefix(): SiPrefix? {
if (isZero) {
return null
}
var num = this
if (isNegative) {
num = -this
}
var prev: SiPrefix? = null
if (num >= Decimal.ONE) {
for (value in SiPrefix.MULTIPLIES) {
if (value.impreciseFraction <= num) {
prev = value
} else {
break
}
}
} else {
for (value in SiPrefix.DECIMALS_IMPRECISE) {
if (value.impreciseFraction >= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun Int.determineSiPrefix(): SiPrefix? {
if (this == 0) {
return null
}
var num = this
if (this < 0) {
num = -this
}
var prev: SiPrefix? = null
if (num >= 1) {
for (value in SiPrefix.MULTIPLIES) {
if (value.int != null && value.int <= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun Double.determineSiPrefix(): SiPrefix? {
if (this == 0.0) {
return null
}
var num = this
if (this < 0) {
num = -this
}
var prev: SiPrefix? = null
if (num >= 1) {
for (value in SiPrefix.MULTIPLIES) {
if (value.double <= num) {
prev = value
} else {
break
}
}
}
return prev
}
fun Decimal.formatSi(decimalPlaces: Int = 2): String {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return toString(decimalPlaces)
return (this / prefix.impreciseFraction).toString(decimalPlaces) + prefix.symbol
}
fun Int.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString()) else if (suffix is Component) TextComponent(toString() + " " + suffix.string) else TextComponent(toString() + " " + suffix)
return TranslatableComponent(prefix.formatLocaleKey, "%.${decimalPlaces}f".format(this.toFloat() / prefix.int!!.toFloat()), suffix)
}
fun Double.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent("%.${decimalPlaces}f".format(this)) else if (suffix is Component) TextComponent("%.${decimalPlaces}f".format(this) + " " + suffix.string) else TextComponent("%.${decimalPlaces}f".format(this) + " " + suffix)
return TranslatableComponent(prefix.formatLocaleKey, "%.${decimalPlaces}f".format(this / prefix.double), suffix)
}
fun Decimal.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString(decimalPlaces)) else if (suffix is Component) TextComponent(toString(decimalPlaces) + " " + suffix.string) else TextComponent(toString(decimalPlaces) + " " + suffix)
return TranslatableComponent(prefix.formatLocaleKey, (this / prefix.impreciseFraction).toString(decimalPlaces), suffix)
}
val POWER_NAME = TranslatableComponent("otm.gui.power.name")
val MATTER_NAME = TranslatableComponent("otm.gui.matter.name")
fun Int.formatPower(decimalPlaces: Int = 2) = formatSiComponent(POWER_NAME, decimalPlaces)
fun Decimal.formatPower(decimalPlaces: Int = 2) = formatSiComponent(POWER_NAME, decimalPlaces)
fun Decimal.formatMatter(decimalPlaces: Int = 2) = formatSiComponent(MATTER_NAME, decimalPlaces)
fun Decimal.formatMatterFull(decimalPlaces: Int = 2) = TranslatableComponent("otm.gui.matter.format", formatSiComponent(
MATTER_NAME, decimalPlaces))
fun BigInteger.formatPower(decimalPlaces: Int = 2) = formatSiComponent(POWER_NAME, decimalPlaces)
fun BigInteger.formatMatter(decimalPlaces: Int = 2) = formatSiComponent(MATTER_NAME, decimalPlaces)
fun BigInteger.formatMatterFull(decimalPlaces: Int = 2) = TranslatableComponent("otm.gui.matter.format", formatSiComponent(
MATTER_NAME, decimalPlaces))
fun formatPowerLevel(a: Decimal, b: Decimal, decimalPlaces: Int = 2) = TranslatableComponent("otm.gui.level", a.formatPower(decimalPlaces), b.formatPower(decimalPlaces))
fun formatMatterLevel(a: Decimal, b: Decimal, decimalPlaces: Int = 2) = TranslatableComponent("otm.gui.level", a.formatMatter(decimalPlaces), b.formatMatter(decimalPlaces))
private fun padded(num: Int): String {
if (num in 0 .. 9) {
return "0$num"
}
return num.toString()
}
fun formatTickDuration(ticks: Int, longFormat: Boolean = false): String {
@Suppress("name_shadowing")
var leftTicks = ticks
// val mTicks = leftTicks % 20
leftTicks /= 20
val seconds = padded(leftTicks % 60)
leftTicks /= 60
if (longFormat) {
if (ticks <= 0) {
return "00:00:00"
} else if (ticks <= 20) {
return ".00000${padded(ticks)}"
}
val minutes = padded(leftTicks % 60)
leftTicks /= 60
val hours = padded(leftTicks)
return "$hours:$minutes:$seconds"
} else {
if (ticks <= 0) {
return "00:00"
} else if (ticks <= 20) {
return ".00${padded(ticks)}"
}
val minutes = leftTicks
if (minutes > 99) {
return "**:**"
}
return "${padded(minutes)}:$seconds"
}
}