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
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.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)
}
enum class SiPrefix(
val power: Int,
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"
}
}