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 notesByVoice = editState.notesByVoice
|
||||||
val originalNotes = editState.originalNotes
|
val originalNotes = editState.originalNotes
|
||||||
|
val templateFragment = editState.templateFragment
|
||||||
|
val pureTemplate = templateFragment.replace(Regex("[()]"), "")
|
||||||
|
|
||||||
for (voiceNum in 0..3) {
|
for (voiceNum in 0..3) {
|
||||||
val linePrefix = "N${voiceNum + 1}:"
|
val linePrefix = "N${voiceNum + 1}:"
|
||||||
|
|
@ -631,10 +633,10 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val isNoteModified = newNot != oldNot
|
val isNoteModified = newNot != oldNot
|
||||||
// println("est-ce? $isNoteModified = $newNot != $oldNot")
|
// println("est-ce? $isNoteModified = $newNot != $oldNot")
|
||||||
|
|
||||||
if (!isNoteModified) {
|
/*if (!isNoteModified) {
|
||||||
// println("Voix $linePrefix : Aucune modification détectée (Note: $oldNot ).")
|
println("Voix $linePrefix : Aucune modification détectée (Note: $oldNot ).")
|
||||||
continue
|
continue
|
||||||
}
|
}*/
|
||||||
|
|
||||||
val newNote = notesByVoice[voiceNum] ?: ""
|
val newNote = notesByVoice[voiceNum] ?: ""
|
||||||
if (newNote.isEmpty()) continue
|
if (newNote.isEmpty()) continue
|
||||||
|
|
@ -733,6 +735,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
currentLogicalIdx++
|
||||||
} else {
|
} else {
|
||||||
// AFFICHAGE NOTE NORMALE
|
// AFFICHAGE NOTE NORMALE
|
||||||
// println(
|
// println(
|
||||||
|
|
@ -797,6 +800,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
var i = 0
|
var i = 0
|
||||||
var currentBlock = StringBuilder()
|
var currentBlock = StringBuilder()
|
||||||
val separators = listOf(':', '|', '!', '/')
|
val separators = listOf(':', '|', '!', '/')
|
||||||
|
var dropNextCloseParenthesis = false
|
||||||
|
|
||||||
while (i <= body.length) {
|
while (i <= body.length) {
|
||||||
if (i < body.length && body[i] == '$' && i + 1 < body.length && body[i + 1] == '{') {
|
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 markerMatch = Regex("""\$\{.*?\}|\$.""").find(rawBlockText)
|
||||||
val existingMarker = markerMatch?.value ?: ""
|
val existingMarker = markerMatch?.value ?: ""
|
||||||
|
|
||||||
|
val leadingCloseParentheses = rawBlockText.takeWhile { it == ')' }
|
||||||
|
val oldCleaned = rawBlockText.substring(leadingCloseParentheses.length)
|
||||||
|
|
||||||
val newTemplate = getGlobalTemplate(editState)
|
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 {
|
||||||
|
if (dropNextCloseParenthesis && rawBlockText.startsWith(")")) {
|
||||||
|
actionTaken = "FIX_ORPHEL_)"
|
||||||
|
dropNextCloseParenthesis = false
|
||||||
|
rawBlockText.substring(1)
|
||||||
} else {
|
} else {
|
||||||
rawBlockText
|
rawBlockText
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockToProcess.contains("((") || blockToProcess.contains("))")) {
|
||||||
|
while (blockToProcess.contains("((") || blockToProcess.contains("))")) {
|
||||||
|
blockToProcess = blockToProcess.replace("((", "(").replace("))", ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
val compactedBlock = StringBuilder()
|
val compactedBlock = StringBuilder()
|
||||||
if (blockToProcess.isNotEmpty()) {
|
if (blockToProcess.isNotEmpty()) {
|
||||||
var k = 0
|
var k = 0
|
||||||
|
|
@ -896,8 +936,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
compactedBlock.append("")
|
compactedBlock.append("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// println(String.format("%-4d | %-25s | %-15s | %-25s",
|
println(String.format("%-4d | %-25s | %-15s | %-25s",
|
||||||
// currentLogicalIdx, rawBlockText, actionTaken, compactedBlock.toString()))
|
currentLogicalIdx, rawBlockText, actionTaken, compactedBlock.toString()))
|
||||||
|
|
||||||
resultBody.append(compactedBlock)
|
resultBody.append(compactedBlock)
|
||||||
if (i < body.length) resultBody.append(body[i])
|
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"
|
val finalResult = "$prefix$resultBody$suffix"
|
||||||
// println("-".repeat(100))
|
println("-".repeat(100))
|
||||||
// println("RÉSULTAT FINAL COMPACTÉ : $finalResult")
|
println("RÉSULTAT FINAL COMPACTÉ : $finalResult")
|
||||||
// println("=".repeat(100))
|
println("=".repeat(100))
|
||||||
|
|
||||||
return finalResult
|
return finalResult
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,10 @@ fun TUODetailDialog(
|
||||||
|
|
||||||
var marker by remember { mutableStateOf(editState.marker) }
|
var marker by remember { mutableStateOf(editState.marker) }
|
||||||
|
|
||||||
LaunchedEffect(notes.values.toList()) {
|
LaunchedEffect(notes.toMap()) {
|
||||||
val tempState = TUOEditState(
|
val tempState = TUOEditState(
|
||||||
tuoIndex = editState.tuoIndex,
|
tuoIndex = editState.tuoIndex,
|
||||||
notesByVoice = notes,
|
notesByVoice = notes.toMap(),
|
||||||
originalNotes = editState.originalNotes,
|
originalNotes = editState.originalNotes,
|
||||||
lyricsByStanza = editState.lyricsByStanza,
|
lyricsByStanza = editState.lyricsByStanza,
|
||||||
originalLyricsByStanza = editState.originalLyricsByStanza,
|
originalLyricsByStanza = editState.originalLyricsByStanza,
|
||||||
|
|
@ -382,7 +382,7 @@ fun validateMusicalInput(input: String, template: String): Boolean {
|
||||||
cleanTemplate.forEachIndexed { index, char ->
|
cleanTemplate.forEachIndexed { index, char ->
|
||||||
when (char) {
|
when (char) {
|
||||||
in 'A'..'Y', in 'a'..'y' -> {
|
in 'A'..'Y', in 'a'..'y' -> {
|
||||||
append("(?:―|di|ri|fi|si|ta|[drmfslt])[¹²³₁₂₃]*")
|
append("(?:―|di|ri|fi|si|ta|[drmfsltz])[¹²³₁₂₃]*")
|
||||||
}
|
}
|
||||||
'z' -> {
|
'z' -> {
|
||||||
append(" ?")
|
append(" ?")
|
||||||
|
|
@ -431,32 +431,83 @@ public fun getGlobalTemplate(editState: TUOEditState): String {
|
||||||
tpl
|
tpl
|
||||||
}
|
}
|
||||||
|
|
||||||
val maxLen = voiceTemplates.maxOfOrNull { it.length } ?: 1
|
val rythmicTemplates = voiceTemplates.map { tpl -> tpl.replace(Regex("[()]"), "") }
|
||||||
// println("Longueur max détectée: $maxLen")
|
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()
|
val result = StringBuilder()
|
||||||
|
|
||||||
for (i in 0 until maxLen) {
|
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
|
val chars = rythmicTemplates.mapNotNull { it.getOrNull(i) }.toSet()
|
||||||
|
val previousChars = if(i>0) rythmicTemplates.mapNotNull { it.getOrNull(i-1) }.toSet() else "".toSet()
|
||||||
if (lastChar == '.' && chars.contains(',')) {
|
val activeChars = rythmicTemplates.mapNotNull { it.getOrNull(i) }
|
||||||
result.append('z')
|
val isAllHyphen = activeChars.isNotEmpty() && activeChars.all { it == '-' }
|
||||||
}
|
|
||||||
|
|
||||||
// println(" Indice $i | Caractères collectés: $chars")
|
|
||||||
|
|
||||||
val combinedChar = when {
|
val combinedChar = when {
|
||||||
chars.contains('D') || chars.contains('-') -> 'D'
|
chars.contains('D') -> 'D'
|
||||||
|
isAllHyphen -> '-'
|
||||||
chars.contains('.') -> '.'
|
chars.contains('.') -> '.'
|
||||||
chars.contains(',') -> ','
|
chars.contains(',') -> ','
|
||||||
chars.contains('(') -> '('
|
previousChars.contains('.') && chars.contains(' ') -> 'z'
|
||||||
chars.contains(')') -> ')'
|
else -> ' '
|
||||||
else -> 'z'
|
|
||||||
}
|
}
|
||||||
|
// 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)
|
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("Template Global Final: '${result.toString()}'")
|
||||||
// println("----------------------------------\n")
|
// println("----------------------------------\n")
|
||||||
|
|
@ -476,7 +527,7 @@ private fun notesToTemplate(notes: String): String {
|
||||||
.replace("si", "S")
|
.replace("si", "S")
|
||||||
.replace("ta", "T")
|
.replace("ta", "T")
|
||||||
|
|
||||||
val noteRegex = Regex("([drmfsltDRFSTz]+|[.,()-])")
|
val noteRegex = Regex("""([drmfsltDRFSTz]+|[.,()\s-])""")
|
||||||
val template = StringBuilder()
|
val template = StringBuilder()
|
||||||
val matches = noteRegex.findAll(cleaned)
|
val matches = noteRegex.findAll(cleaned)
|
||||||
|
|
||||||
|
|
@ -484,6 +535,7 @@ private fun notesToTemplate(notes: String): String {
|
||||||
val value = match.value
|
val value = match.value
|
||||||
when {
|
when {
|
||||||
value.matches(Regex("[.,()-]")) -> template.append(value)
|
value.matches(Regex("[.,()-]")) -> template.append(value)
|
||||||
|
value.trim().isEmpty() -> template.append(" ")
|
||||||
else -> template.append("D")
|
else -> template.append("D")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1262,10 +1262,10 @@ fun EditorActionButtons(isUndoVisible: Boolean, onUndo: () -> Unit, onBuild: ()
|
||||||
|
|
||||||
fun autoFixNote(rawNote: String, template: String): String {
|
fun autoFixNote(rawNote: String, template: String): String {
|
||||||
println("ça on a t $template => $rawNote")
|
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 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(",")) {
|
if (rawNote.contains("•") || rawNote.contains("―") || rawNote.contains(",")) {
|
||||||
val templateNotesCount = template.count { c ->
|
val templateNotesCount = template.count { c ->
|
||||||
|
|
@ -1273,6 +1273,9 @@ fun autoFixNote(rawNote: String, template: String): String {
|
||||||
}
|
}
|
||||||
if (actualNotes.size >= templateNotesCount) return rawNote
|
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()
|
val result = StringBuilder()
|
||||||
var noteIdx = 0
|
var noteIdx = 0
|
||||||
|
|
@ -1289,10 +1292,14 @@ fun autoFixNote(rawNote: String, template: String): String {
|
||||||
|
|
||||||
result.append(noteToAdd)
|
result.append(noteToAdd)
|
||||||
noteIdx++
|
noteIdx++
|
||||||
|
} else {
|
||||||
|
if (rawNote.isEmpty()) {
|
||||||
|
result.append("z")
|
||||||
} else {
|
} else {
|
||||||
result.append("―")
|
result.append("―")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
char == '-' -> {
|
char == '-' -> {
|
||||||
val prev = if (i > 0) template[i - 1] else null
|
val prev = if (i > 0) template[i - 1] else null
|
||||||
val next = if (i < template.lastIndex) template[i + 1] else null
|
val next = if (i < template.lastIndex) template[i + 1] else null
|
||||||
|
|
@ -1307,8 +1314,12 @@ fun autoFixNote(rawNote: String, template: String): String {
|
||||||
val currentText = result.toString()
|
val currentText = result.toString()
|
||||||
if (!currentText.endsWith(",")) result.append(",")
|
if (!currentText.endsWith(",")) result.append(",")
|
||||||
}
|
}
|
||||||
char == '(' -> result.append("(")
|
char == '(' -> {
|
||||||
char == ')' -> result.append(")")
|
if (shouldIncludeParentheses) result.append("(")
|
||||||
|
}
|
||||||
|
char == ')' -> {
|
||||||
|
if (shouldIncludeParentheses) result.append(")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toString()
|
return result.toString()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue