Bug Fix! Auto Update Template struct when Editing notes - template with note format
This commit is contained in:
parent
2f536ba45b
commit
dc86d9ddc4
3 changed files with 137 additions and 34 deletions
|
|
@ -612,6 +612,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
) {
|
||||
val notesByVoice = editState.notesByVoice
|
||||
val originalNotes = editState.originalNotes
|
||||
val templateFragment = editState.templateFragment
|
||||
val pureTemplate = templateFragment.replace(Regex("[()]"), "")
|
||||
|
||||
for (voiceNum in 0..3) {
|
||||
val linePrefix = "N${voiceNum + 1}:"
|
||||
|
|
@ -631,10 +633,10 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
val isNoteModified = newNot != oldNot
|
||||
// println("est-ce? $isNoteModified = $newNot != $oldNot")
|
||||
|
||||
if (!isNoteModified) {
|
||||
// println("Voix $linePrefix : Aucune modification détectée (Note: $oldNot ).")
|
||||
/*if (!isNoteModified) {
|
||||
println("Voix $linePrefix : Aucune modification détectée (Note: $oldNot ).")
|
||||
continue
|
||||
}
|
||||
}*/
|
||||
|
||||
val newNote = notesByVoice[voiceNum] ?: ""
|
||||
if (newNote.isEmpty()) continue
|
||||
|
|
@ -733,6 +735,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
i++
|
||||
}
|
||||
currentLogicalIdx++
|
||||
} else {
|
||||
// AFFICHAGE NOTE NORMALE
|
||||
// println(
|
||||
|
|
@ -797,6 +800,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
var i = 0
|
||||
var currentBlock = StringBuilder()
|
||||
val separators = listOf(':', '|', '!', '/')
|
||||
var dropNextCloseParenthesis = false
|
||||
|
||||
while (i <= body.length) {
|
||||
if (i < body.length && body[i] == '$' && i + 1 < body.length && body[i + 1] == '{') {
|
||||
|
|
@ -833,12 +837,48 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
val markerMatch = Regex("""\$\{.*?\}|\$.""").find(rawBlockText)
|
||||
val existingMarker = markerMatch?.value ?: ""
|
||||
|
||||
val leadingCloseParentheses = rawBlockText.takeWhile { it == ')' }
|
||||
val oldCleaned = rawBlockText.substring(leadingCloseParentheses.length)
|
||||
|
||||
val newTemplate = getGlobalTemplate(editState)
|
||||
newMarkerValue + existingMarker + newTemplate
|
||||
val oldHadOpen = oldCleaned.contains("(")
|
||||
val newHasOpen = newTemplate.contains("(")
|
||||
|
||||
|
||||
if (oldHadOpen && !newHasOpen) {
|
||||
dropNextCloseParenthesis = true
|
||||
}
|
||||
var adjustedTemplate = newTemplate
|
||||
if (newTemplate.endsWith(")")) {
|
||||
val remainingText = body.substring(i).trimStart { it in separators }
|
||||
if (remainingText.startsWith(")")) {
|
||||
adjustedTemplate = newTemplate.dropLast(1)
|
||||
}
|
||||
}
|
||||
|
||||
val rawProcessed = leadingCloseParentheses + newMarkerValue + existingMarker + adjustedTemplate
|
||||
|
||||
var cleanedProcessed = rawProcessed
|
||||
while (cleanedProcessed.contains("((") || cleanedProcessed.contains("))")) {
|
||||
cleanedProcessed = cleanedProcessed.replace("((", "(").replace("))", ")")
|
||||
}
|
||||
|
||||
cleanedProcessed
|
||||
} else {
|
||||
rawBlockText
|
||||
if (dropNextCloseParenthesis && rawBlockText.startsWith(")")) {
|
||||
actionTaken = "FIX_ORPHEL_)"
|
||||
dropNextCloseParenthesis = false
|
||||
rawBlockText.substring(1)
|
||||
} else {
|
||||
rawBlockText
|
||||
}
|
||||
}
|
||||
|
||||
if (blockToProcess.contains("((") || blockToProcess.contains("))")) {
|
||||
while (blockToProcess.contains("((") || blockToProcess.contains("))")) {
|
||||
blockToProcess = blockToProcess.replace("((", "(").replace("))", ")")
|
||||
}
|
||||
}
|
||||
val compactedBlock = StringBuilder()
|
||||
if (blockToProcess.isNotEmpty()) {
|
||||
var k = 0
|
||||
|
|
@ -896,8 +936,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
compactedBlock.append("")
|
||||
}
|
||||
|
||||
// println(String.format("%-4d | %-25s | %-15s | %-25s",
|
||||
// currentLogicalIdx, rawBlockText, actionTaken, compactedBlock.toString()))
|
||||
println(String.format("%-4d | %-25s | %-15s | %-25s",
|
||||
currentLogicalIdx, rawBlockText, actionTaken, compactedBlock.toString()))
|
||||
|
||||
resultBody.append(compactedBlock)
|
||||
if (i < body.length) resultBody.append(body[i])
|
||||
|
|
@ -911,9 +951,9 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
|
||||
val finalResult = "$prefix$resultBody$suffix"
|
||||
// println("-".repeat(100))
|
||||
// println("RÉSULTAT FINAL COMPACTÉ : $finalResult")
|
||||
// println("=".repeat(100))
|
||||
println("-".repeat(100))
|
||||
println("RÉSULTAT FINAL COMPACTÉ : $finalResult")
|
||||
println("=".repeat(100))
|
||||
|
||||
return finalResult
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ fun TUODetailDialog(
|
|||
|
||||
var marker by remember { mutableStateOf(editState.marker) }
|
||||
|
||||
LaunchedEffect(notes.values.toList()) {
|
||||
LaunchedEffect(notes.toMap()) {
|
||||
val tempState = TUOEditState(
|
||||
tuoIndex = editState.tuoIndex,
|
||||
notesByVoice = notes,
|
||||
notesByVoice = notes.toMap(),
|
||||
originalNotes = editState.originalNotes,
|
||||
lyricsByStanza = editState.lyricsByStanza,
|
||||
originalLyricsByStanza = editState.originalLyricsByStanza,
|
||||
|
|
@ -382,7 +382,7 @@ fun validateMusicalInput(input: String, template: String): Boolean {
|
|||
cleanTemplate.forEachIndexed { index, char ->
|
||||
when (char) {
|
||||
in 'A'..'Y', in 'a'..'y' -> {
|
||||
append("(?:―|di|ri|fi|si|ta|[drmfslt])[¹²³₁₂₃]*")
|
||||
append("(?:―|di|ri|fi|si|ta|[drmfsltz])[¹²³₁₂₃]*")
|
||||
}
|
||||
'z' -> {
|
||||
append(" ?")
|
||||
|
|
@ -431,33 +431,84 @@ public fun getGlobalTemplate(editState: TUOEditState): String {
|
|||
tpl
|
||||
}
|
||||
|
||||
val maxLen = voiceTemplates.maxOfOrNull { it.length } ?: 1
|
||||
// println("Longueur max détectée: $maxLen")
|
||||
val rythmicTemplates = voiceTemplates.map { tpl -> tpl.replace(Regex("[()]"), "") }
|
||||
val maxLen = rythmicTemplates.maxOfOrNull { it.length } ?: 1
|
||||
// println("Longueur rythmique max détectée: $maxLen")
|
||||
|
||||
val openBefore = BooleanArray(maxLen)
|
||||
val closeBefore = BooleanArray(maxLen)
|
||||
val openAfter = BooleanArray(maxLen)
|
||||
val closeAfter = BooleanArray(maxLen)
|
||||
|
||||
var openAtTheEnd = false
|
||||
var closeAtTheEnd = false
|
||||
|
||||
voiceTemplates.forEach { tpl ->
|
||||
var rythmicIdx = 0
|
||||
for (i in tpl.indices) {
|
||||
val char = tpl[i]
|
||||
if (char == '(' || char == ')') {
|
||||
val textAfter = tpl.substring(i + 1)
|
||||
val hasRythmicAfter = textAfter.any { it != '(' && it != ')' }
|
||||
|
||||
if (hasRythmicAfter) {
|
||||
if (rythmicIdx < maxLen) {
|
||||
if (char == '(') openBefore[rythmicIdx] = true
|
||||
if (char == ')') closeBefore[rythmicIdx] = true
|
||||
}
|
||||
} else {
|
||||
if (rythmicIdx > 0) {
|
||||
if (char == '(') openAfter[rythmicIdx - 1] = true
|
||||
if (char == ')') closeAfter[rythmicIdx - 1] = true
|
||||
} else {
|
||||
if (char == '(') openAtTheEnd = true
|
||||
if (char == ')') closeAtTheEnd = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rythmicIdx++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val result = StringBuilder()
|
||||
|
||||
for (i in 0 until maxLen) {
|
||||
val chars = voiceTemplates.mapNotNull { it.getOrNull(i) }.toSet()
|
||||
if (openBefore[i]) result.append('(')
|
||||
if (closeBefore[i]) result.append(')')
|
||||
|
||||
val lastChar = if (result.isNotEmpty()) result.last() else null
|
||||
|
||||
if (lastChar == '.' && chars.contains(',')) {
|
||||
result.append('z')
|
||||
}
|
||||
|
||||
// println(" Indice $i | Caractères collectés: $chars")
|
||||
val chars = rythmicTemplates.mapNotNull { it.getOrNull(i) }.toSet()
|
||||
val previousChars = if(i>0) rythmicTemplates.mapNotNull { it.getOrNull(i-1) }.toSet() else "".toSet()
|
||||
val activeChars = rythmicTemplates.mapNotNull { it.getOrNull(i) }
|
||||
val isAllHyphen = activeChars.isNotEmpty() && activeChars.all { it == '-' }
|
||||
|
||||
val combinedChar = when {
|
||||
chars.contains('D') || chars.contains('-') -> 'D'
|
||||
chars.contains('D') -> 'D'
|
||||
isAllHyphen -> '-'
|
||||
chars.contains('.') -> '.'
|
||||
chars.contains(',') -> ','
|
||||
chars.contains('(') -> '('
|
||||
chars.contains(')') -> ')'
|
||||
else -> 'z'
|
||||
previousChars.contains('.') && chars.contains(' ') -> 'z'
|
||||
else -> ' '
|
||||
}
|
||||
result.append(combinedChar)
|
||||
// Supprimer espace avant une virgule
|
||||
if (combinedChar == ',' && result.isNotEmpty() && result.last() == ' ') {
|
||||
result.deleteCharAt(result.length - 1)
|
||||
}
|
||||
println("Pour $i = ${chars.toString()} on a > ${combinedChar.toString()}")
|
||||
|
||||
val lastChar = if (result.isNotEmpty()) result.last() else null
|
||||
if (!((combinedChar == '.' && lastChar == '.') || (combinedChar == ',' && lastChar == ','))) {
|
||||
result.append(combinedChar)
|
||||
}
|
||||
println("all = ${result.toString()}")
|
||||
|
||||
if (openAfter[i]) result.append('(')
|
||||
if (closeAfter[i]) result.append(')')
|
||||
}
|
||||
|
||||
if (openAtTheEnd) result.append('(')
|
||||
if (closeAtTheEnd) result.append(')')
|
||||
|
||||
// println("Template Global Final: '${result.toString()}'")
|
||||
// println("----------------------------------\n")
|
||||
return result.toString()
|
||||
|
|
@ -476,7 +527,7 @@ private fun notesToTemplate(notes: String): String {
|
|||
.replace("si", "S")
|
||||
.replace("ta", "T")
|
||||
|
||||
val noteRegex = Regex("([drmfsltDRFSTz]+|[.,()-])")
|
||||
val noteRegex = Regex("""([drmfsltDRFSTz]+|[.,()\s-])""")
|
||||
val template = StringBuilder()
|
||||
val matches = noteRegex.findAll(cleaned)
|
||||
|
||||
|
|
@ -484,6 +535,7 @@ private fun notesToTemplate(notes: String): String {
|
|||
val value = match.value
|
||||
when {
|
||||
value.matches(Regex("[.,()-]")) -> template.append(value)
|
||||
value.trim().isEmpty() -> template.append(" ")
|
||||
else -> template.append("D")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1262,10 +1262,10 @@ fun EditorActionButtons(isUndoVisible: Boolean, onUndo: () -> Unit, onBuild: ()
|
|||
|
||||
fun autoFixNote(rawNote: String, template: String): String {
|
||||
println("ça on a t $template => $rawNote")
|
||||
if (rawNote.isEmpty() || rawNote == "_") return rawNote
|
||||
if (rawNote == "_") return rawNote
|
||||
|
||||
val noteRegex = Regex("([drmfsltDRFSTw][ia]?|―)[0-9'¹²³⁴₁₂₃₄,]*")
|
||||
val actualNotes = noteRegex.findAll(rawNote).map { it.value }.toList()
|
||||
val actualNotes = if (rawNote.isEmpty()) emptyList() else noteRegex.findAll(rawNote).map { it.value }.toList()
|
||||
|
||||
if (rawNote.contains("•") || rawNote.contains("―") || rawNote.contains(",")) {
|
||||
val templateNotesCount = template.count { c ->
|
||||
|
|
@ -1273,6 +1273,9 @@ fun autoFixNote(rawNote: String, template: String): String {
|
|||
}
|
||||
if (actualNotes.size >= templateNotesCount) return rawNote
|
||||
}
|
||||
val requiredNotesCount = template.count { it in 'A'..'Y' || it in 'a'..'y' }
|
||||
|
||||
val shouldIncludeParentheses = actualNotes.size >= requiredNotesCount
|
||||
|
||||
val result = StringBuilder()
|
||||
var noteIdx = 0
|
||||
|
|
@ -1290,7 +1293,11 @@ fun autoFixNote(rawNote: String, template: String): String {
|
|||
result.append(noteToAdd)
|
||||
noteIdx++
|
||||
} else {
|
||||
result.append("―")
|
||||
if (rawNote.isEmpty()) {
|
||||
result.append("z")
|
||||
} else {
|
||||
result.append("―")
|
||||
}
|
||||
}
|
||||
}
|
||||
char == '-' -> {
|
||||
|
|
@ -1307,8 +1314,12 @@ fun autoFixNote(rawNote: String, template: String): String {
|
|||
val currentText = result.toString()
|
||||
if (!currentText.endsWith(",")) result.append(",")
|
||||
}
|
||||
char == '(' -> result.append("(")
|
||||
char == ')' -> result.append(")")
|
||||
char == '(' -> {
|
||||
if (shouldIncludeParentheses) result.append("(")
|
||||
}
|
||||
char == ')' -> {
|
||||
if (shouldIncludeParentheses) result.append(")")
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toString()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue