Rewrote splitLines using Test-Driven Development, words should no longer get lost

This commit is contained in:
Ceikry
2022-08-16 13:37:00 +00:00
committed by Ryan
parent 7690aad9fb
commit 21d334a989
3 changed files with 60 additions and 43 deletions
+31 -35
View File
@@ -1,50 +1,46 @@
package api
import rs09.game.system.SystemLogger
import java.util.*
import kotlin.system.exitProcess
//Number of chars per line. Line is split at the nearest whole word that doesn't exceed this length. This should remain constant once a perfect value is found
const val LINE_SIZE = 52.0
import kotlin.math.ceil
/**
* Automatically split a single continuous string into multiple comma-separated lines.
* Should this not work out for any reason, you should fallback to standard npc and player methods for dialogue.
*/
fun splitLines(message: String): Array<String>{
val chars = message.split("").toTypedArray().size.toDouble()
val words = message.split(" ").toTypedArray()
val lines = Math.ceil(chars / LINE_SIZE).toInt()
fun splitLines(message: String, perLineLimit: Int = 54) : Array<String> {
val lines = Array(ceil(message.length / perLineLimit.toFloat()).toInt()) {""}
if(lines > 4){
SystemLogger.logErr("INVALID NUM LINES. NUM CHARS: $chars")
//short circuit when possible because it's cheaper.
if (lines.size == 1) {
lines[0] = message
return lines
}
val messages = ArrayList<String>()
val tokenQueue = LinkedList(message.split(" "))
var index = 0
val line = StringBuilder()
var accumulator = 0
for (msg in 0 until lines) {
var length = 0
val line = StringBuilder()
while (length <= LINE_SIZE && !(index == words.size)) {
var currentWord = ""
try {
currentWord = words[index] + if (length + words[index].length + 1 <= LINE_SIZE) " " else ""
} catch (e: Exception){
SystemLogger.logWarn("INDEX: $index WORDSIZE: ${words.size}")
for(word in words.indices){
SystemLogger.logErr("Word $word: ${words[word]}")
}
exitProcess(0)
}
length += currentWord.length
if (length <= LINE_SIZE) {
line.append(currentWord)
++index
}
}
messages.add(line.toString())
fun pushLine() {
if (line.isEmpty()) return
lines[index++] = line.toString()
line.clear()
accumulator = 0
}
return messages.toTypedArray()
while (!tokenQueue.isEmpty()) {
val shouldSpace = line.isNotEmpty()
accumulator += tokenQueue.peek().length
if (shouldSpace) accumulator += 1
if (accumulator > perLineLimit) {
pushLine()
continue
}
if (shouldSpace) line.append(" ")
line.append(tokenQueue.pop())
}
pushLine()
return lines
}