You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
senzapaura_es/scripts/db/escansion.mjs

79 lines
2.6 KiB

/**
* Comprueba que la escansión de un verso cuadre.
*
* Vive aparte del sembrador porque es la única garantía de que el taller no
* enseñe una cuenta falsa, y eso hay que poder probarlo sin una base de datos
* delante. Un ejemplo mal escandido es peor que ningún ejemplo: quien aprende
* a contar sílabas con él aprende mal.
*
* La ley del acento final, que es de donde sale todo esto: un verso se mide
* hasta su última sílaba tónica más una. Si acaba en palabra llana —lo
* normal— la cuenta es la que se ve; si acaba en aguda suma una, y si acaba en
* esdrújula resta una. Por eso «yo respondo con el son» tiene siete casillas y
* es un octosílabo.
*/
/**
* @param {{ silabas: string[], tonicas: number[], medida: number, texto?: string }} linea
* @returns {string | null} qué falla, o `null` si cuadra.
*/
export function fallosDeEscansion(linea) {
const casillas = linea.silabas.length;
if (casillas === 0) return 'no tiene sílabas';
if (linea.tonicas.length === 0) return 'no tiene ninguna sílaba tónica';
if (linea.tonicas.some((t) => !Number.isInteger(t) || t < 1 || t > casillas)) {
return `una tónica cae fuera de las ${casillas} sílabas`;
}
if ([...linea.tonicas].sort((a, b) => a - b).join() !== linea.tonicas.join()) {
return 'las tónicas no van en orden';
}
const ultima = linea.tonicas.at(-1);
const porElAcento = {
[casillas]: casillas + 1, // aguda
[casillas - 1]: casillas, // llana
[casillas - 2]: casillas - 1 // esdrújula
};
// Con la tónica más atrás no hay verso: en castellano no hay palabras
// sobresdrújulas al final de verso que se cuenten así.
if (!(ultima in porElAcento)) {
return `la última tónica está en ${ultima} y hay ${casillas} sílabas: demasiado atrás`;
}
if (porElAcento[ultima] !== linea.medida) {
return (
`${casillas} casillas con la última tónica en ${ultima} ` +
`miden ${porElAcento[ultima]}, no ${linea.medida}`
);
}
return null;
}
/**
* Recorre la semilla entera y devuelve todo lo que no cuadra, con su sitio.
*
* @param {{ generos: Record<string, {titulo: string, lineas: object[]}[]> }} semilla
* @returns {string[]}
*/
export function revisarSemilla(semilla) {
const problemas = [];
for (const [genero, ejemplos] of Object.entries(semilla.generos)) {
for (const ejemplo of ejemplos) {
for (const [i, linea] of ejemplo.lineas.entries()) {
const fallo = fallosDeEscansion(linea);
if (fallo) {
problemas.push(
`${genero} · «${ejemplo.titulo}» · verso ${i + 1}: ${fallo} — «${linea.texto}»`
);
}
}
}
}
return problemas;
}

Powered by TurnKey Linux.