Unify placeholder parsing for unique parameters (#10072)

* Unify placeholder parsing for unique parameters

* Remove double "remove conditional" call - kudos @SomeTroglodyte
This commit is contained in:
Yair Morgenstern 2023-09-07 09:57:40 +03:00 committed by GitHub
parent e8c740da31
commit 30570747a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 18 additions and 22 deletions

View File

@ -13,7 +13,6 @@ import com.unciv.models.stats.Stats
import com.unciv.models.translations.getConditionals
import com.unciv.models.translations.getPlaceholderParameters
import com.unciv.models.translations.getPlaceholderText
import com.unciv.models.translations.removeConditionals
import kotlin.random.Random
@ -21,7 +20,7 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
/** This is so the heavy regex-based parsing is only activated once per unique, instead of every time it's called
* - for instance, in the city screen, we call every tile unique for every tile, which can lead to ANRs */
val placeholderText = text.getPlaceholderText()
val params = text.removeConditionals().getPlaceholderParameters()
val params = text.getPlaceholderParameters()
val type = UniqueType.values().firstOrNull { it.placeholderText == placeholderText }
val stats: Stats by lazy {

View File

@ -400,9 +400,9 @@ fun String.tr(hideIcons:Boolean = false): String {
}
// Take the terms in the message, WITHOUT square brackets
val termsInMessage = this.getPlaceholderParametersIgnoringLowerLevelBraces()
val termsInMessage = this.getPlaceholderParameters()
// Take the terms from the placeholder
val termsInTranslationPlaceholder = originalEntry.getPlaceholderParametersIgnoringLowerLevelBraces()
val termsInTranslationPlaceholder = originalEntry.getPlaceholderParameters()
if (termsInMessage.size != termsInTranslationPlaceholder.size)
throw Exception("Message $this has a different number of terms than the placeholder $translationEntry!")
@ -438,17 +438,19 @@ fun String.tr(hideIcons:Boolean = false): String {
* For example, a string like 'The city of [New [York]]' will return ['New [York]'],
* allowing us to have nested translations!
*/
fun String.getPlaceholderParametersIgnoringLowerLevelBraces(): List<String> {
fun String.getPlaceholderParameters(): List<String> {
if (!this.contains('[')) return emptyList()
val stringToParse = this.removeConditionals()
val parameters = ArrayList<String>()
var depthOfBraces = 0
var startOfCurrentParameter = -1
for (i in this.indices) {
if (this[i] == '[') {
for (i in stringToParse.indices) {
if (stringToParse[i] == '[') {
if (depthOfBraces == 0) startOfCurrentParameter = i+1
depthOfBraces++
}
if (this[i] == ']' && depthOfBraces > 0) {
if (stringToParse[i] == ']' && depthOfBraces > 0) {
depthOfBraces--
if (depthOfBraces == 0) parameters.add(substring(startOfCurrentParameter,i))
}
@ -458,7 +460,7 @@ fun String.getPlaceholderParametersIgnoringLowerLevelBraces(): List<String> {
fun String.getPlaceholderText(): String {
var stringToReturn = this.removeConditionals()
val placeholderParameters = stringToReturn.getPlaceholderParametersIgnoringLowerLevelBraces()
val placeholderParameters = stringToReturn.getPlaceholderParameters()
for (placeholderParameter in placeholderParameters)
stringToReturn = stringToReturn.replace("[$placeholderParameter]", "[]")
return stringToReturn
@ -474,11 +476,6 @@ fun String.hasPlaceholderParameters(): Boolean {
return squareBraceRegex.containsMatchIn(this.removeConditionals())
}
fun String.getPlaceholderParameters(): List<String> {
if (!this.contains('[')) return emptyList()
return squareBraceRegex.findAll(this.removeConditionals()).map { it.groups[1]!!.value }.toList()
}
/** Substitutes placeholders with [strings], respecting order of appearance. */
fun String.fillPlaceholders(vararg strings: String): String {
val keys = this.getPlaceholderParameters()

View File

@ -11,7 +11,7 @@ import com.unciv.models.stats.Stats
import com.unciv.models.translations.TranslationEntry
import com.unciv.models.translations.TranslationFileWriter
import com.unciv.models.translations.Translations
import com.unciv.models.translations.getPlaceholderParametersIgnoringLowerLevelBraces
import com.unciv.models.translations.getPlaceholderParameters
import com.unciv.models.translations.getPlaceholderText
import com.unciv.models.translations.squareBraceRegex
import com.unciv.models.translations.tr
@ -244,24 +244,24 @@ class TranslationTests {
@Test
fun translationParameterExtractionForNestedBracesWorks() {
Assert.assertEquals(listOf("New [York]"),
"The city of [New [York]]".getPlaceholderParametersIgnoringLowerLevelBraces())
"The city of [New [York]]".getPlaceholderParameters())
// Closing braces without a matching opening brace - 'level 0' - are ignored
Assert.assertEquals(listOf("New [York]"),
"The city of [New [York]]]".getPlaceholderParametersIgnoringLowerLevelBraces())
"The city of [New [York]]]".getPlaceholderParameters())
// Opening braces without a matching closing brace mean that the term is never 'closed'
// so there are no parameters
Assert.assertEquals(listOf<String>(),
"The city of [[New [York]".getPlaceholderParametersIgnoringLowerLevelBraces())
"The city of [[New [York]".getPlaceholderParameters())
// Supernesting
val superNestedString = "The brother of [[my [best friend]] and [[America]'s greatest [Dad]]]"
Assert.assertEquals(listOf("[my [best friend]] and [[America]'s greatest [Dad]]"),
superNestedString.getPlaceholderParametersIgnoringLowerLevelBraces())
superNestedString.getPlaceholderParameters())
Assert.assertEquals(listOf("my [best friend]", "[America]'s greatest [Dad]"),
superNestedString.getPlaceholderParametersIgnoringLowerLevelBraces()[0]
.getPlaceholderParametersIgnoringLowerLevelBraces())
superNestedString.getPlaceholderParameters()[0]
.getPlaceholderParameters())
UncivGame.Current = UncivGame()
UncivGame.Current.settings = GameSettings()
@ -283,7 +283,7 @@ class TranslationTests {
debug("[Dad] and [my [best friend]]".getPlaceholderText())
Assert.assertEquals(listOf("Dad","my [best friend]"),
"[Dad] and [my [best friend]]".getPlaceholderParametersIgnoringLowerLevelBraces())
"[Dad] and [my [best friend]]".getPlaceholderParameters())
Assert.assertEquals("Father and indeed mine own closest ally", "[Dad] and [my [best friend]]".tr())
// Reminder: "The brother of [[my [best friend]] and [[America]'s greatest [Dad]]]"