Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Procesadorv2 #17

Merged
merged 8 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file not shown.
3 changes: 2 additions & 1 deletion aplicaciones/procesador/fuente/autores.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import slugificar from 'slug';
import type { DefinicionSimple, ElementoLista } from '@/tipos/compartidos';

//import { separarPartes } from './ayudas.js';
import { DefinicionSimple, ElementoLista } from 'tipos.js';

export function procesarNombresAutores(
apellidoNombreSinProcesar: string,
Expand Down
11 changes: 10 additions & 1 deletion aplicaciones/procesador/fuente/ayudas.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { writeFileSync } from 'fs';
import colores from 'cli-color';
import { emojify } from 'node-emoji';
import { ElementoLista } from 'tipos';
import slugificar from 'slug';
import type { ElementoLista } from '@/tipos/compartidos';

export const logError = colores.red.bold;
export const logAviso = colores.bold.xterm(214);
Expand All @@ -16,11 +16,20 @@ export const cadena = emojify(':link:');
export const conector = emojify(':electric_plug:');
export const gorila = emojify(':gorilla:');
export const chulo = emojify(':white_check_mark:');
export const alerta = emojify(':warning:');

export const guardarJSON = (json: any, nombre: string) => {
writeFileSync(`../www/estaticos/datos/${nombre}.json`, JSON.stringify(json));
};

/**
* Limpia un texto para borrar espacio al principio y final, le quita cortes de línea como `\n`.
*
* @param texto Texto que se quiere limpiar
* @returns texto procesado
*/
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}`) : '';
Expand Down
111 changes: 59 additions & 52 deletions aplicaciones/procesador/fuente/indicadores.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,58 @@
import slugificar from 'slug';
import { Indicador, Subindicador } from 'tipos.js';
import { getXlsxStream } from 'xlstream';
import type { Indicador, Subindicador } from '@/tipos/compartidos';
import type { Errata } from './tipos';
import { limpiarTextoSimple } from './ayudas';

type FilaIdicador = [id: string, nombre: string, descripcion: string, subindicadores?: Subindicador[]];
type FilaSubindicador = [id: string, nombre: string, idIndicadorMadre: string];

let datosEmpiezanEnFila = 0;
let filasProcesadas = 0;
let conteoFilas = -datosEmpiezanEnFila;
let totalFilas = Infinity;
let filasPreprocesadas = false;
const archivo = './datos/base_produccion_ academica_anonimizado_V25_090924.xlsx';

export async function procesarIndicadores(archivo: string, hoja: string, lista: Indicador[]): Promise<Indicador[]> {
export async function procesarIndicadores(): Promise<{ datos: Indicador[]; errata: Errata[] }> {
const flujo = await getXlsxStream({
filePath: archivo,
sheet: hoja,
sheet: 'Diccionario de Indicadores',
withHeader: true,
ignoreEmpty: true,
});

return new Promise((resolver) => {
let numeroFila = 1;
let contadorIds = 1;
const lista: Indicador[] = [];
const errata: Errata[] = [];

flujo.on('data', async ({ raw }) => {
const fila = raw.arr as FilaIdicador;
const nombre = fila[1].trim();
const slug = slugificar(nombre);

const existe = lista.find((elemento) => elemento.slug === slug);

if (!existe) {
const respuesta: Indicador = {
id: +fila[0], // revisar si es número
nombre: nombre,
slug: slug,
descripcion: fila[2] ? fila[2].trim() : 'no hay descripción',
};

lista.push(respuesta);
} else {
console.log(`En fila ${numeroFila} hay indicador con nombre ${nombre} que ya existe con ID ${existe.id}`);
const [nombre, definicion] = raw.arr as FilaIdicador;

if (nombre) {
const nombreProcesado = limpiarTextoSimple(nombre);
const slug = slugificar(nombreProcesado);
const existe = lista.find((elemento) => elemento.slug === slug);

if (!existe) {
lista.push({
id: contadorIds,
nombre: nombreProcesado,
slug,
definicion: definicion ? definicion.trim() : '',
});

contadorIds++;
} else {
errata.push({
fila: numeroFila,
error: `Hay indicador con nombre ${nombre} que ya existe con ID ${existe.id}`,
});
}
}

numeroFila++;
});

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

if (!filasPreprocesadas && totalFilas === filasProcesadas) {
filasPreprocesadas = true;
// construirRelacionesDePublicaciones();
}

resolver(lista);
resolver({ datos: lista, errata });
});

flujo.on('error', (error) => {
Expand All @@ -64,20 +62,20 @@ export async function procesarIndicadores(archivo: string, hoja: string, lista:
}

export async function procesarSubindicadores(
archivo: string,
hoja: string,
lista: Subindicador[],
listaIndicadores: Indicador[]
): Promise<Subindicador[]> {
indicadores: Indicador[]
): Promise<{ datos: Subindicador[]; errata: Errata[] }> {
const flujo = await getXlsxStream({
filePath: archivo,
sheet: hoja,
sheet: 'Contenidos P.A',
withHeader: true,
ignoreEmpty: true,
});

return new Promise((resolver) => {
let numeroFila = 1;
let contadorIds = 1;
const lista: Subindicador[] = [];
const errata: Errata[] = [];

flujo.on('data', async ({ raw }) => {
const fila = raw.arr as FilaSubindicador;
Expand All @@ -87,13 +85,13 @@ export async function procesarSubindicadores(
const slug = slugificar(nombre);

if (!fila[0] || !fila[0].length) {
console.log(`En la fila ${numeroFila} no hay indicador`);
errata.push({ fila: numeroFila, error: 'No hay indicador' });
return;
}

const indicadorMadre = slugificar(fila[0].trim());

const existeIndicador = listaIndicadores.find((obj) => {
const existeIndicador = indicadores.find((obj) => {
return obj.slug === indicadorMadre;
});

Expand All @@ -111,27 +109,36 @@ export async function procesarSubindicadores(

lista.push(respuesta);
} else {
console.log(
`El subindicador ${nombre} con indicador ${existeIndicador.nombre} en fila ${numeroFila} ya existe con nombre ${existeSubIndicador.nombre} e indicador ${listaIndicadores.find((obj) => obj.id === existeSubIndicador.indicadorMadre)?.nombre}`
);
errata.push({
fila: numeroFila,
error: `El subindicador ${nombre} con indicador ${existeIndicador.nombre} en fila ${numeroFila} ya existe con nombre ${existeSubIndicador.nombre} e indicador ${indicadores.find((obj) => obj.id === existeSubIndicador.indicadorMadre)?.nombre}`,
});
}
} else {
console.log(`No se puede encontrar el indicador ${indicadorMadre}`);
errata.push({ fila: numeroFila, error: `No se puede encontrar el indicador ${indicadorMadre}` });
}
}

numeroFila++;
});

flujo.on('close', () => {
// Aquí ya terminó de leer toda la tabla
totalFilas = conteoFilas;
lista.forEach((subI) => {
const indicadorId = subI.indicadorMadre;
const indicadorI = indicadores.findIndex((obj) => obj.id === indicadorId);

if (!filasPreprocesadas && totalFilas === filasProcesadas) {
filasPreprocesadas = true;
}
if (indicadorI >= 0) {
if (!indicadores[indicadorI].subindicadores) {
indicadores[indicadorI].subindicadores = [];
}

indicadores[indicadorI].subindicadores?.push(subI.id);
} else {
errata.push({ fila: 0, error: `No existe el indicador con ID ${subI.indicadorMadre}!` });
}
});

resolver(lista);
resolver({ datos: lista, errata });
});

flujo.on('error', (error) => {
Expand Down
37 changes: 35 additions & 2 deletions aplicaciones/procesador/fuente/procesador.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
import { alerta, chulo, guardarJSON, logAviso, logNaranjaPulso } from './ayudas';
import { procesarIndicadores, procesarSubindicadores } from './indicadores';
import procesadorColectivos from './procesadorColectivos';
import procesadorPublicaciones from './procesadorPublicaciones';

async function inicio() {
await procesadorPublicaciones();
// await procesadorColectivos();
/** Extraer diccionario de indicadores */
const indicadores = await procesarIndicadores();
/** Extraer subindicadores y crear relaciones con indicadores */
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'));
}

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

inicio().catch(console.error);
18 changes: 7 additions & 11 deletions aplicaciones/procesador/fuente/procesadorColectivos.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { getXlsxStream } from 'xlstream';
import slugificar from 'slug';
//import { emojify } from 'node-emoji';
import { separarPartes, ordenarListaObjetos, guardarJSON, logAviso, chulo, procesarLista } from './ayudas';
import {
ElementoLista,
ListasColectivos,
DefinicionSimple,
import { ordenarListaObjetos, guardarJSON, logAviso, chulo, procesarLista } from './ayudas';
import type {
CamposColectivos,
Colectivo,
DefinicionSimple,
ElementoListaIndicadores,
Indicador,
ListasColectivos,
Subindicador,
ElementoListaIndicadores,
CamposColectivos,
} from './tipos';
import { procesarIndicadores, procesarSubindicadores } from './indicadores';
} from '@/tipos/compartidos';

const archivoColectivos = './datos/base_colectivos_y_ambitos_anonimizado20240902.xlsx';
const hojaCol = 'Diccionario Indicadores';
Expand Down Expand Up @@ -66,8 +64,6 @@ const listas: ListasColectivos = {
};

export default async () => {
indicadoresProcesados = await procesarIndicadores(archivoColectivos, hojaCol, indicadoresCol);

/* subindicadoresProcesados = await procesarSubindicadores(
archivoColectivos,
hojaSubindicadoresCol,
Expand Down
Loading