Skip to content

Commit

Permalink
Merge pull request #20 from enflujo/procesadorv3
Browse files Browse the repository at this point in the history
Procesadorv3
  • Loading branch information
1cgonza authored Oct 16, 2024
2 parents cd81487 + 4ce1025 commit bfd037c
Show file tree
Hide file tree
Showing 17 changed files with 389 additions and 350 deletions.
33 changes: 6 additions & 27 deletions aplicaciones/procesador/fuente/ayudas.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { writeFileSync } from 'fs';
import colores from 'cli-color';
import { emojify } from 'node-emoji';
import slugificar from 'slug';
import type { ElementoLista } from '@/tipos/compartidos';

export const logError = colores.red.bold;
export const logAviso = colores.bold.xterm(214);
Expand Down Expand Up @@ -30,28 +28,6 @@ export const guardarJSON = (json: any, nombre: string) => {
*/
export const limpiarTextoSimple = (texto: string) => texto.trim().replace(/[\n\r\s\t]+/g, ' ');

export function procesarLista(valor: string, lista: ElementoLista[]) {
if (!valor) return;
const slug = valor ? slugificar(`${valor}`) : '';
const existe = lista.find((obj) => obj.slug === slug);
if (!valor || valor === 'No aplica' || valor === 'undefined' || valor === 'Sin Información' || valor === '(s.f)')
return;
const nombre = `${valor}`.trim();

if (!existe) {
const objeto: ElementoLista = {
nombre: nombre,
conteo: 1,
slug: slug,
relaciones: [],
publicaciones: [],
};
lista.push(objeto);
} else {
existe.conteo++;
}
}

export function ordenarListaObjetos(lista: any[], llave: string, descendente = false) {
lista.sort((a, b) => {
if (a[llave] < b[llave]) return descendente ? -1 : 1;
Expand All @@ -61,10 +37,10 @@ export function ordenarListaObjetos(lista: any[], llave: string, descendente = f
}

export const normalizar = (texto: string): string => {
return texto;
/* .toLocaleLowerCase()
return texto
.toLocaleLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, ''); */
.replace(/[\u0300-\u036f]/g, '');
};

export const enMinusculas = (texto: string) => texto === texto.toLowerCase();
Expand All @@ -78,3 +54,6 @@ export function separarPartes(entrada: string, separador?: string) {
export function mensajeExito(mensaje: string) {
console.log(chulo, logAviso(mensaje));
}

export const esNumero = (valor: string | number): boolean => !isNaN(parseInt(`${valor}`));
export const esFecha = (valor: string) => !isNaN(new Date(valor).getTime());
35 changes: 14 additions & 21 deletions aplicaciones/procesador/fuente/procesador.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { alerta, chulo, guardarJSON, logAviso, logNaranjaPulso } from './ayudas'
import { procesarIndicadores, procesarSubindicadores } from './indicadores';
import procesadorColectivos from './procesadorColectivos';
import procesadorPublicaciones from './procesadorPublicaciones';
import type { Errata } from './tipos';

async function inicio() {
/** Extraer diccionario de indicadores */
Expand All @@ -10,33 +11,25 @@ async function inicio() {
const subindicadores = await procesarSubindicadores(indicadores.datos);
const publicaciones = await procesadorPublicaciones(indicadores.datos, subindicadores.datos);

if (indicadores.errata.length) {
guardarJSON(indicadores.datos, `indicadores-produccionAcademica`);
console.log(
alerta,
logNaranjaPulso(
`Procesados indicadores (con ${indicadores.errata.length} errores, ver archivo: errataIndicadores.json)`
)
);
guardarJSON(indicadores.errata, 'errataIndicadores');
} else {
guardarJSON(indicadores.datos, `indicadores-produccionAcademica`);
console.log(chulo, logAviso('Procesados indicadores'));
}
guardar(indicadores.datos, indicadores.errata, 'indicadores-produccionAcademica', 'errataIndicadores');
guardar(subindicadores.datos, subindicadores.errata, 'subIndicadores-produccionAcademica', 'errataSubIndicadores');
guardar(publicaciones.datos, publicaciones.errata, 'publicaciones', 'errataPublicaciones');
}

inicio().catch(console.error);

if (subindicadores.errata.length) {
guardarJSON(subindicadores.datos, `subIndicadores-produccionAcademica`);
function guardar(datos: any, errata: Errata[], nombre: string, nombreErrata = `errata${nombre}`) {
if (errata.length) {
guardarJSON(datos, nombre);
console.log(
alerta,
logNaranjaPulso(
`Procesados subindicadores (con ${subindicadores.errata.length} errores, ver archivo: errataSubIndicadores.json)`
`Procesados ${nombre} (con ${errata.length} error${errata.length > 1 ? 'es' : ''}, ver archivo: ${nombreErrata}.json)`
)
);
guardarJSON(subindicadores.errata, 'errataSubIndicadores');
guardarJSON(errata, nombreErrata);
} else {
guardarJSON(subindicadores.datos, `subIndicadores-produccionAcademica`);
console.log(chulo, logAviso('Procesados subindicadores'));
guardarJSON(datos, nombre);
console.log(chulo, logAviso(`Procesados ${nombre}`));
}
}

inicio().catch(console.error);
171 changes: 97 additions & 74 deletions aplicaciones/procesador/fuente/procesadorPublicaciones.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { getXlsxStream } from 'xlstream';
import slugificar from 'slug';
import { separarPartes, ordenarListaObjetos, guardarJSON, procesarLista, limpiarTextoSimple } from './ayudas';
import { separarPartes, ordenarListaObjetos, guardarJSON, limpiarTextoSimple, esNumero } from './ayudas';
import type {
CamposPA,
DefinicionSimple,
ElementoLista,
ElementoListaIndicadores,
Indicador,
ListasPublicaciones,
Expand Down Expand Up @@ -49,46 +50,44 @@ export default async (

flujo.on('data', async ({ raw }) => {
const fila = raw.arr as FilaProduccionAcademica;
const id = fila[0];
const autores = fila[1]?.includes(';') ? separarPartes(fila[1], ';') : [fila[1]?.trim()];
const resumen = fila[2] ? fila[2].trim() : '';
const años = fila[3] ? fila[3] : '';
const tipos = fila[4] ? fila[4].trim() : '';
const titulo = fila[5] ? fila[5].trim() : '';
const referencia = fila[6] ? fila[6].trim() : '';
const fuente = fila[7] ? fila[7] : '';
const dependencia = fila[8] ? fila[8].trim() : '';
// POR HACER: Procesar indicadores y subindicadores
const indicador = fila[9] ? fila[9].trim() : '';
const subindicador = fila[10] ? fila[10].trim() : '';

const publicacion = procesarFila(raw.arr, numeroFila);
publicaciones.push(publicacion);

// Llenar listas
procesarLista(dependencia, listas.dependencias);
procesarLista(tipos, listas.tipos);
procesarLista(años, listas.años);
procesarLista(subindicador, listas.subindicadores);
procesarListaIndicadores(indicador);

for (let fila in autores) {
procesarLista(autores[fila]!, listas.autores); //¿Qué forma mejor hay de hacer esto sin forzar con '!'?
}
if (publicacion) {
publicaciones.push(publicacion);
// Llenar listas
procesarLista(fila[8], listas.dependencias);
procesarLista(fila[4], listas.tipos);
procesarLista(fila[3], listas.años);
procesarLista(fila[10], listas.subindicadores);
procesarListaIndicadores(fila[9]);

if (fila[1]) {
const autores = fila[1].includes(';') ? separarPartes(fila[1], ';') : [fila[1].trim()];

autores.forEach((autor) => {
if (autor) {
procesarLista(autor, listas.autores);
} else {
errata.push({
fila: numeroFila,
error: `No hay autor en la parte: ${autor} dentro del campo autores ${fila[1]}`,
});
}
});
}

for (const lista in listas) {
ordenarListaObjetos(listas[lista as keyof ListasPublicaciones], 'slug', true);
for (const lista in listas) {
ordenarListaObjetos(listas[lista as keyof ListasPublicaciones], 'slug', true);
}
}

imprimirErratas(autores, años, tipos, titulo, dependencia, numeroFila);
numeroFila++;
});

flujo.on('close', () => {
// Aquí ya terminó de leer toda la tabla
construirRelacionesDePublicaciones(publicaciones);

guardarJSON(publicaciones, 'publicaciones');
guardarJSON(listas, 'listas');
resolver({ datos: publicaciones, errata });
});
Expand All @@ -98,9 +97,23 @@ export default async (
});
});

function procesarFila(fila: FilaProduccionAcademica, numeroFila: number): Publicacion {
const tituloPublicacion = fila[5] ? limpiarTextoSimple(fila[5]) : '';
const autores = fila[1]?.includes(';') ? separarPartes(fila[1], ';') : [fila[1]?.trim()];
function procesarFila(fila: FilaProduccionAcademica, numeroFila: number): Publicacion | undefined {
if (!fila[0] || !esNumero(fila[0])) {
errata.push({ fila: numeroFila, error: `La fila no tiene ID o no es un número` });
return;
}

if (!fila[5]) {
errata.push({
fila: numeroFila,
error: `La fila no tiene titulo de publicación, el valor de la celda es ${fila[5]}`,
});

return;
}

const tituloPublicacion = limpiarTextoSimple(fila[5]);

const subindicador = fila[10] ? fila[10].trim() : '';

if (!subindicador) {
Expand All @@ -115,23 +128,40 @@ export default async (
console.log(`No existe el subindicador ${subindicador} en la lista de subindicadores procesados`);
}

// Convertir autores en tipo DefinicionSimple
const autoresProcesados = autores.map((autor) => {
return { nombre: autor ? autor : '', slug: autor ? slugificar(autor) : '' };
});
const autores: DefinicionSimple[] = [];

const indicador = indicadores.find((obj) => {
return slugificar(fila[9].trim()) === obj.slug;
});
if (fila[1]) {
const partes = fila[1].includes(';') ? separarPartes(fila[1], ';') : [fila[1].trim()];
// Convertir autores en tipo DefinicionSimple
partes.forEach((nombreAutor) => {
autores.push({ nombre: nombreAutor, slug: slugificar(nombreAutor) });
});
}

const indicador = indicadores.find((obj) => slugificar(fila[9].trim()) === obj.slug);

let años: number | undefined;

if (fila[3] && esNumero(fila[3])) {
años = +fila[3];
} else {
// Sólo registrar errata si la celda de fecha no tiene nada o es distinto a las convenciones que se usan para indicar que no hay fecha.
if (fila[3] !== '(s.f)') {
errata.push({
fila: numeroFila,
error: `No hay fecha para la publicación, el valor en la celda es: ${fila[3]}`,
});
}
}

// En la tabla todas las publicaciones parecen tener subindicador pero muchos son el mismo indicador repetido.
// Aquí estoy borrando el campo subindicador si es el mismo indicador y no un subindicador
const respuesta: Publicacion = {
id: +fila[0],
titulo: { nombre: tituloPublicacion, slug: slugificar(tituloPublicacion) },
resumen: fila[2] ? fila[2].trim() : '',
autores: autoresProcesados,
años: { año: +fila[3], valor: fila[3] },
autores,
años,
tipos: { nombre: fila[4].trim(), slug: slugificar(fila[4].trim()) },
referencia: fila[6] ? fila[6].trim() : '',
fuente: fila[7] ? fila[7] : '',
Expand All @@ -156,16 +186,16 @@ export default async (
}

function procesarListaIndicadores(indicador: string) {
const slug = indicador ? slugificar(indicador) : '';
const existe = listas.indicadores.find((obj) => obj.slug === slug);

if (!indicadores.length) {
console.log('No hay indicadores procesados');
}

const slug = indicador ? slugificar(indicador) : '';
const existe = listas.indicadores.find((obj) => obj.slug === slug);
const existeEnIndicadoresProcesados = indicadores.find((obj) => obj.slug === slug);

if (existeEnIndicadoresProcesados) {
const nombre = existeEnIndicadoresProcesados.nombre;
const { nombre } = existeEnIndicadoresProcesados;
if (!existe) {
const objeto: ElementoListaIndicadores = {
nombre: nombre,
Expand All @@ -182,35 +212,6 @@ export default async (
}
};

function imprimirErratas(
autores: (string | undefined)[],
años: string | number | undefined,
tipos: string,
titulo: string,
dependencia: string,
numeroFila: number
) {
// Imprimir datos que faltan
for (const fila in autores) {
if (!autores[fila]) {
console.log('sin autor: ', numeroFila);
}
}

if (!años) {
console.log('sin fecha: ', numeroFila);
}
if (!tipos) {
console.log('sin tipo: ', numeroFila);
}
if (!titulo) {
console.log('sin titulo: ', numeroFila);
}
if (!dependencia) {
console.log('sin dependencia: ', numeroFila);
}
}

// Ver haciendocaminos procesador.ts 240
function construirRelacionesDePublicaciones(publicaciones: Publicacion[]) {
for (const lista in listas) {
Expand Down Expand Up @@ -277,3 +278,25 @@ function construirRelacionesDePublicaciones(publicaciones: Publicacion[]) {
});
});
}

export function procesarLista(valor: string, lista: ElementoLista[]) {
if (!valor) return;
const slug = valor ? slugificar(`${valor}`) : '';
const existe = lista.find((obj) => obj.slug === slug);
if (!valor || valor === 'No aplica' || valor === 'undefined' || valor === 'Sin Información' || valor === '(s.f)')
return;
const nombre = `${valor}`.trim();

if (!existe) {
const objeto: ElementoLista = {
nombre: nombre,
conteo: 1,
slug: slug,
relaciones: [],
publicaciones: [],
};
lista.push(objeto);
} else {
existe.conteo++;
}
}
5 changes: 2 additions & 3 deletions aplicaciones/procesador/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
},
"devDependencies": {
"@types/cli-color": "^2.0.6",
"@types/node": "^22.5.4",
"@types/node": "^22.7.4",
"@types/slug": "^5.0.9",
"nodemon": "^3.1.4",
"nodemon": "^3.1.7",
"rimraf": "^6.0.1",
"slug": "^9.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.5.4",
"xlstream": "^2.5.5"
},
"nodemonConfig": {
Expand Down
1 change: 1 addition & 0 deletions aplicaciones/www/estaticos/datos/errataPublicaciones.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"fila":249,"error":"No hay fecha para la publicación, el valor en la celda es: undefined"}]
2 changes: 1 addition & 1 deletion aplicaciones/www/estaticos/datos/listas.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion aplicaciones/www/estaticos/datos/publicaciones.json

Large diffs are not rendered by default.

Loading

0 comments on commit bfd037c

Please sign in to comment.