package moe.nea.ledger import net.minecraft.event.ClickEvent import net.minecraft.event.HoverEvent import net.minecraft.util.ChatComponentText import net.minecraft.util.ChatStyle import net.minecraft.util.EnumChatFormatting import net.minecraft.util.IChatComponent import java.time.Instant import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatterBuilder import java.time.temporal.ChronoField import java.util.regex.Matcher import java.util.regex.Pattern // language=regexp val SHORT_NUMBER_PATTERN = "[0-9]+(?:,[0-9]+)*(?:\\.[0-9]+)?[kKmMbB]?" // language=regexp val ROMAN_NUMBER_PATTERN = "[IVXLCDM]+" val romanNumbers = mapOf( 'I' to 1, 'V' to 5, 'X' to 10, 'L' to 50, 'C' to 100, 'D' to 500, 'M' to 1000 ) fun parseRomanNumber(string: String): Int { var smallestSeenSoFar = Int.MAX_VALUE var lastSeenOfSmallest = 0 var amount = 0 for (c in string) { val cV = romanNumbers[c]!! if (cV == smallestSeenSoFar) { lastSeenOfSmallest++ amount += cV } else if (cV < smallestSeenSoFar) { smallestSeenSoFar = cV amount += cV lastSeenOfSmallest = 1 } else { amount -= lastSeenOfSmallest * smallestSeenSoFar * 2 smallestSeenSoFar = cV amount += cV lastSeenOfSmallest = 1 } } return amount } val siScalars = mapOf( 'k' to 1_000.0, 'K' to 1_000.0, 'm' to 1_000_000.0, 'M' to 1_000_000.0, 'b' to 1_000_000_000.0, 'B' to 1_000_000_000.0, ) fun parseShortNumber(string: String): Double { var k = string.replace(",", "") val scalar = k.last() var scalarMultiplier = siScalars[scalar] if (scalarMultiplier == null) { scalarMultiplier = 1.0 } else { k = k.dropLast(1) } return k.toDouble() * scalarMultiplier } fun Pattern.matches(string: String): Boolean = matcher(string).matches() inline fun Pattern.useMatcher(string: String, block: Matcher.() -> T): T? = matcher(string).takeIf { it.matches() }?.let(block) fun String.ifDropLast(suffix: String, block: (String) -> T): T? { if (endsWith(suffix)) { return block(dropLast(suffix.length)) } return null } fun String.unformattedString(): String = replace("ยง.".toRegex(), "") val timeFormat: DateTimeFormatter = DateTimeFormatterBuilder() .appendValue(ChronoField.DAY_OF_MONTH, 2) .appendLiteral(".") .appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendLiteral(".") .appendValue(ChronoField.YEAR, 4) .appendLiteral(" ") .appendValue(ChronoField.HOUR_OF_DAY, 2) .appendLiteral(":") .appendValue(ChronoField.MINUTE_OF_HOUR, 2) .appendLiteral(":") .appendValue(ChronoField.SECOND_OF_MINUTE, 2) .toFormatter() fun Instant.formatChat(): IChatComponent { val text = ChatComponentText( LocalDateTime.ofInstant(this, ZoneId.systemDefault()).format(timeFormat) ) text.setChatStyle( ChatStyle() .setChatClickEvent( ClickEvent(ClickEvent.Action.OPEN_URL, "https://time.is/${this.epochSecond}")) .setChatHoverEvent( HoverEvent(HoverEvent.Action.SHOW_TEXT, ChatComponentText("Click to show on time.is"))) .setColor(EnumChatFormatting.AQUA)) return text }