Isolate nuances marker

This commit is contained in:
Hasinjato 2026-09-16 11:50:11 +03:00
parent 3a0141e34d
commit 08c6fd25c4
3 changed files with 84 additions and 121 deletions

View file

@ -37,68 +37,9 @@ class PTemplate (val template: String, val separatorAfter: String, private val m
}
}
fun markerToList(): List<String> {
if (markers.isEmpty()) {
return emptyList()
}
val mString = markerToString()
return parseMarkers(mString)
if (markers.isEmpty()) return emptyList()
return parseMarkers(markerToString())
}
fun parseMarkers(rawText: String): List<String> {
val tokens = mutableListOf<String>()
if (rawText.isBlank()) return tokens
var remaining = rawText.replace(",", " ")
.replace(Regex("""\b(DC)\b""", RegexOption.IGNORE_CASE), "D.C.")
.replace(Regex("""\b(DS)\b""", RegexOption.IGNORE_CASE), "D.S.")
.replace(Regex("""(D\.?C\.?)\s*(Fin)""", RegexOption.IGNORE_CASE), "D.C.Fin")
.replace(Regex("""(D\.?S\.?)\s*(Fin)""", RegexOption.IGNORE_CASE), "D.S.Fin")
.replace(Regex("""(D\.?C\.?)\s*(al\s*Coda)""", RegexOption.IGNORE_CASE), "D.C.alCoda")
.replace(Regex("""(D\.?S\.?)\s*(al\s*Coda)""", RegexOption.IGNORE_CASE), "D.S.alCoda")
val allStaticMarkers = getAllMarker()
val tempoRegex = Regex("""^(♩\s*=\s*\d+)""", RegexOption.IGNORE_CASE)
val modulaRegex = Regex("""^(D(?:ô|o)?\s*dia\s*(?:C|Db|D|Eb|E|F|Gb|G|Ab|A|Bb|B))""", RegexOption.IGNORE_CASE)
// Lexer
while (remaining.isNotEmpty()) {
remaining = remaining.trimStart()
if (remaining.isEmpty()) break
val tempoMatch = tempoRegex.find(remaining)
if (tempoMatch != null) {
tokens.add(tempoMatch.value)
remaining = remaining.substring(tempoMatch.value.length)
continue
}
val modulaMatch = modulaRegex.find(remaining)
if (modulaMatch != null) {
tokens.add(modulaMatch.value)
remaining = remaining.substring(modulaMatch.value.length)
continue
}
val matchedMarker = allStaticMarkers
.sortedByDescending { it.length }
.find { marker ->
remaining.startsWith(marker, ignoreCase = true) &&
(remaining.length == marker.length ||
!remaining[marker.length].isLetter())
}
if (matchedMarker != null) {
tokens.add(matchedMarker)
remaining = remaining.substring(matchedMarker.length)
} else {
val unknownChunk = remaining.takeWhile { !it.isWhitespace() }
tokens.add(unknownChunk)
remaining = remaining.substring(unknownChunk.length)
}
}
return tokens
}
fun hasKeyChange(): String {
var returnFun = ""
markers.map {
@ -112,3 +53,76 @@ class PTemplate (val template: String, val separatorAfter: String, private val m
}
}
fun parseMarkers(rawText: String): List<String> {
val tokens = mutableListOf<String>()
if (rawText.isBlank()) return tokens
var remaining = rawText.trim()
.replace(",", " ")
.replace(Regex("""\b(DC)\b""", RegexOption.IGNORE_CASE), "D.C.")
.replace(Regex("""\b(DS)\b""", RegexOption.IGNORE_CASE), "D.S.")
.replace(Regex("""(D\.?C\.?)\s*(Fin)""", RegexOption.IGNORE_CASE), "D.C.Fin")
.replace(Regex("""(D\.?S\.?)\s*(Fin)""", RegexOption.IGNORE_CASE), "D.S.Fin")
.replace(Regex("""(D\.?C\.?)\s*(al\s*Coda)""", RegexOption.IGNORE_CASE), "D.C.alCoda")
.replace(Regex("""(D\.?S\.?)\s*(al\s*Coda)""", RegexOption.IGNORE_CASE), "D.S.alCoda")
val allStaticMarkers = getAllMarker().sortedByDescending { it.length }
val tempoRegex = Regex("""^(♩\s*=\s*\d+)""", RegexOption.IGNORE_CASE)
val modulaRegex = Regex("""^(D(?:ô|o)?\s*dia\s*(?:C|Db|D|Eb|E|F|Gb|G|Ab|A|Bb|B))""", RegexOption.IGNORE_CASE)
val measureRegex = Regex("""^\d+\s*/\s*\d+""")
while (remaining.isNotEmpty()) {
remaining = remaining.trimStart()
if (remaining.isEmpty()) break
val tempoMatch = tempoRegex.find(remaining)
if (tempoMatch != null) {
tokens.add(tempoMatch.value)
remaining = remaining.substring(tempoMatch.value.length)
continue
}
val modulaMatch = modulaRegex.find(remaining)
if (modulaMatch != null) {
tokens.add(modulaMatch.value)
remaining = remaining.substring(modulaMatch.value.length)
continue
}
val measureMatch = measureRegex.find(remaining)
if (measureMatch != null) {
tokens.add(measureMatch.value)
remaining = remaining.substring(measureMatch.value.length)
continue
}
var matchedMarker: String? = null
for (marker in allStaticMarkers) {
if (remaining.startsWith(marker, ignoreCase = true)) {
val nextCharIndex = marker.length
val endsWithWordChar = marker.last().isLetterOrDigit()
if (endsWithWordChar && nextCharIndex < remaining.length) {
val nextChar = remaining[nextCharIndex]
if (nextChar.isLetterOrDigit() || nextChar == ':' || nextChar == '=') {
continue
}
}
matchedMarker = marker
break
}
}
if (matchedMarker != null) {
tokens.add(matchedMarker)
remaining = remaining.substring(matchedMarker.length)
} else {
val unknownChunk = remaining.takeWhile { !it.isWhitespace() }
tokens.add(unknownChunk)
remaining = remaining.substring(unknownChunk.length)
}
}
return tokens.distinct()
}

View file

@ -272,7 +272,12 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?, co
private val REGEX_CLEAN_PREFIX = Regex("(\\d+\\.)+")
private val musicForPtSerifBIRegex = Regex("""^(Largh\.|Grave|Largo|Lento|Adagio|And\.|Andantino|Mod\.|Moderato|Alleg\.|All\.|Viv\.|Vivacissimo|Presto|Prestiss\.|accel\.|rit\.|rall\.|riten\.|string\.|allarg\.|a tempo|Tempo I|rubato|meno mosso|più mosso|cres\.|<|decresc\.|dim\.|>|rfz|fp|pf|sub\.p|sub\.f)""",RegexOption.IGNORE_CASE)
private val musicForEmmentRegex = Regex("""^(ppp|pp|mp|mf|fff|ff|p|f|sfz|sf|fz|rfz|fp|pf)\b""",RegexOption.IGNORE_CASE)
private val musicForEmmentRegex = Regex(
"""^(?:[mfp]+|sfz|sf|fz|rfz)$""",
RegexOption.IGNORE_CASE
)
private val blankPrefixRegex =Regex("""z([0-9A-Z])[:]""")
private val noteRegex = Regex("([drmfsltDRFSTw][ia]?|―)[0-9'¹²³⁴₁₂₃₄,]*")
private val inclusionRegex = Regex("^I([0-9]):(.*)")
@ -628,7 +633,7 @@ fun LazyVerticalGridTUO(
tuoList.drop(1).mapIndexedNotNull { globalIndex, oneTUO ->
val rawMarker = oneTUO.pTemplate.markerToString()
val hairPin = oneTUO.hasHairPin()
val markerList = sharedScreenModel.parseMarkers(rawMarker)
val markerList = sharedScreenModel.parseMarkers(rawMarker).toMutableList()
/*val finalMarker = when {
hairPin != null && markerText.isBlank() -> hairPin.toString()
hairPin != null && markerText.isNotBlank() -> "${markerText.trim()}$hairPin"
@ -1271,7 +1276,7 @@ private fun TuoHeaderDecorations(
markerFontFamily = ptSerifBoldItalic
}
musicForEmmentRegex.matches(marker) -> {
musicForEmmentRegex.containsMatchIn(marker) -> {
markerFontSize = MaterialTheme.typography.titleMedium.fontSize.value + 11
markerFontFamily = emmentaler
}

View file

@ -557,64 +557,8 @@ class SharedScreenModel(private val fileRepository: FileRepository) : ScreenMode
return _tuoList.value.drop(1).size - 1
}
fun parseMarkers(rawText: String): MutableList<String> {
val tokens = mutableListOf<String>()
if (rawText.isBlank()) return tokens
fun parseMarkers(rawText: String): List<String> = mg.dot.feufaro.solfa.parseMarkers(rawText)
var remaining = rawText.replace(",", " ")
.replace(Regex("""\b(DC)\b""", RegexOption.IGNORE_CASE), "D.C.")
.replace(Regex("""\b(DS)\b""", RegexOption.IGNORE_CASE), "D.S.")
.replace(Regex("""(D\.?C\.?)\s*(Fin)""", RegexOption.IGNORE_CASE), "D.C.Fin")
.replace(Regex("""(D\.?S\.?)\s*(Fin)""", RegexOption.IGNORE_CASE), "D.S.Fin")
.replace(Regex("""(D\.?C\.?)\s*(al\s*Coda)""", RegexOption.IGNORE_CASE), "D.C.alCoda")
.replace(Regex("""(D\.?S\.?)\s*(al\s*Coda)""", RegexOption.IGNORE_CASE), "D.S.alCoda")
val allStaticMarkers = getAllMarker().sortedByDescending { it.length }
val tempoRegex = Regex("""^(♩\s*=\s*\d+)""", RegexOption.IGNORE_CASE)
val modulaRegex = Regex("""^(D(?:ô|o)?\s*dia\s*(?:C|Db|D|Eb|E|F|Gb|G|Ab|A|Bb|B))""", RegexOption.IGNORE_CASE)
val measureRegex = Regex("""^\d+\s*/\s*\d+""")
// Lexer
while (remaining.isNotEmpty()) {
remaining = remaining.trimStart()
if (remaining.isEmpty()) break
val tempoMatch = tempoRegex.find(remaining)
if (tempoMatch != null) {
tokens.add(tempoMatch.value)
remaining = remaining.substring(tempoMatch.value.length)
continue
}
val modulaMatch = modulaRegex.find(remaining)
if (modulaMatch != null) {
tokens.add(modulaMatch.value)
remaining = remaining.substring(modulaMatch.value.length)
continue
}
val measureMatch = measureRegex.find(remaining)
if (measureMatch != null) {
val cleanMeasure = measureMatch.value.replace(" ", "")
tokens.add(cleanMeasure)
remaining = remaining.substring(measureMatch.value.length)
continue
}
val matchedMarker = allStaticMarkers.find { remaining.startsWith(it, ignoreCase = true) }
if (matchedMarker != null) {
tokens.add(matchedMarker)
remaining = remaining.substring(matchedMarker.length)
} else {
val unknownChunk = remaining.takeWhile { !it.isWhitespace() }
tokens.add(unknownChunk)
remaining = remaining.substring(unknownChunk.length)
}
}
// println("Sortie: ${tokens.joinToString(" | ")}")
return tokens
}
fun updateAndFinalizeMidiData(rawList: List<MidiMarkers>) {
// val timestamps = _tuoTimestamps.value