Sanitize character set in ISO exports

This commit is contained in:
Claude Brisson
2024-08-20 15:33:37 +02:00
parent bae30c7465
commit 773b9b7b1e

View File

@@ -2,16 +2,13 @@ package org.jeudego.pairgoth.api
import com.republicate.kson.Json
import com.republicate.kson.toJsonArray
import org.jeudego.pairgoth.api.PairingHandler.dispatchEvent
import org.jeudego.pairgoth.model.Criterion
import org.jeudego.pairgoth.model.Criterion.*
import org.jeudego.pairgoth.model.Game.Result.*
import org.jeudego.pairgoth.model.ID
import org.jeudego.pairgoth.model.PairingType
import org.jeudego.pairgoth.model.Tournament
import org.jeudego.pairgoth.model.adjustedTime
import org.jeudego.pairgoth.model.displayRank
import org.jeudego.pairgoth.model.getID
import java.io.PrintWriter
import java.time.format.DateTimeFormatter
import javax.servlet.http.HttpServletRequest
@@ -23,6 +20,9 @@ import org.jeudego.pairgoth.server.WebappManager
import java.io.OutputStreamWriter
import java.nio.charset.StandardCharsets
import java.text.DecimalFormat
import java.text.Normalizer
import java.util.*
import kotlin.collections.ArrayList
object StandingsHandler: PairgothApiHandler {
override fun get(request: HttpServletRequest, response: HttpServletResponse): Json? {
@@ -31,7 +31,7 @@ object StandingsHandler: PairgothApiHandler {
val includePreliminary = request.getParameter("include_preliminary")?.let { it.toBoolean() } ?: false
val sortedPairables = tournament.getSortedPairables(round, includePreliminary)
tournament.populateResultsArray(sortedPairables, round)
tournament.populateFrozenStandings(sortedPairables, round)
val acceptHeader = request.getHeader("Accept") as String?
val accept = acceptHeader?.substringBefore(";")
@@ -123,13 +123,18 @@ ${
"${
player.getString("num")!!.padStart(4, ' ')
} ${
"${player.getString("name")} ${player.getString("firstname") ?: ""}".padEnd(30, ' ').take(30)
"${
player.getString("name")?.toSnake(true)
} ${
player.getString("firstname")?.toSnake() ?: ""
}".padEnd(30, ' ').take(30)
} ${
displayRank(player.getInt("rank")!!).uppercase().padStart(3, ' ')
} ${
player.getString("country")?.uppercase() ?: ""
} ${
(player.getString("club") ?: "").padStart(4).take(4)
(player.getString("club") ?: "").toSnake().padStart(4).take(4)
} ${
criteria.joinToString(" ") { numFormat.format(player.getDouble(it.name)!!).let { if (it.contains('.')) it else "$it " }.padStart(7, ' ') }
} ${
@@ -143,6 +148,24 @@ ${
writer.println(ret)
}
private fun String.toSnake(upper: Boolean = false): String {
val sanitized = sanitizeISO()
val parts = sanitized.trim().split(Regex("(?:\\s|\\xA0)+"))
val snake = parts.joinToString("_") { part ->
if (upper) part.uppercase(Locale.ROOT)
else part.capitalize()
}
return snake
}
private fun String.sanitizeISO(): String {
val ret = Normalizer.normalize(this, Normalizer.Form.NFD)
return ret.replace(Regex("\\p{M}"), "")
// some non accented letters give problems in ISO, there may be other
.replace('Ð', 'D')
.replace('ø', 'o')
}
private fun exportToFFGFormat(tournament: Tournament<*>, lines: List<Json.Object>, writer: PrintWriter) {
val version = WebappManager.properties.getProperty("version")!!
val ret =
@@ -171,14 +194,14 @@ ${
"${
player.getString("num")!!.padStart(4, ' ')
} ${
"${player.getString("name")} ${player.getString("firstname") ?: ""}".padEnd(24, ' ').take(24)
"${player.getString("name")?.toSnake(true)} ${player.getString("firstname")?.toSnake() ?: ""}".padEnd(24, ' ').take(24)
} ${
displayRank(player.getInt("rank")!!).uppercase().padStart(3, ' ')
} ${
player.getString("ffg") ?: " "
} ${
if (player.getString("country") == "FR")
(player.getString("club") ?: "").padEnd(4).take(4)
(player.getString("club") ?: "").toSnake().padEnd(4).take(4)
else
(player.getString("country") ?: "").padEnd(4).take(4)
} ${