Skip to content

Commit

Permalink
🔨 Primeros datos de aire (5min)
Browse files Browse the repository at this point in the history
  • Loading branch information
1cgonza committed Sep 16, 2024
1 parent 1ef8af7 commit 23b0397
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 36 deletions.
6 changes: 6 additions & 0 deletions aplicaciones/procesador/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ Archivo: **Calles ZAT 7ma v3.xlsx**

Exporta `puntos.json`

### Aire

Archivo: **Puntos Fijos_5 min.xlsx**

Exporta `aire.json`

## Habitabilidad y sus dominios

### Calles ZAT 7ma
Expand Down
Binary file modified aplicaciones/procesador/datos/Mapa 7ma - Datos.xlsx
Binary file not shown.
12 changes: 11 additions & 1 deletion aplicaciones/procesador/fuente/aplicacion.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import procesarAire from './procesarAire';
import procesarDatosA from './procesarDatosA';
import procesarElementosLinea from './procesarElementosLinea';
import procesarRuido from './procesarRuido';
Expand All @@ -11,6 +12,7 @@ interface Estructuras {
datosA: BaseEstructura;
zat: BaseEstructura & { llaves: string[]; tramos: { [nombre: string]: number[] } };
linea: BaseEstructura;
aire: BaseEstructura;
ruido: BaseEstructura & { llaves: string[] };
}
export const estructuras: Estructuras = {
Expand Down Expand Up @@ -83,6 +85,10 @@ export const estructuras: Estructuras = {
archivo: 'Mapa 7ma - Datos',
nombreHoja: 'Cuatro cuadras',
},
aire: {
archivo: 'Puntos Fijos_5 min',
nombreHoja: 'Sheet1',
},
ruido: {
archivo: 'Ruido_10 sec',
nombreHoja: 'Sheet1',
Expand All @@ -106,9 +112,13 @@ async function inicio(): Promise<void> {
const datosRuido = await procesarRuido();
guardarJSON(datosRuido, 'ruido');

/** Aire */
const datosAire = await procesarAire();
guardarJSON(datosAire, 'aire');

const puntos = await procesarDatosA();
await procesarZat(puntos);
await procesarElementosLinea(puntos);
await procesarElementosLinea(puntos, datosAire);
guardarJSON(puntos, 'puntos');
}

Expand Down
161 changes: 161 additions & 0 deletions aplicaciones/procesador/fuente/procesarAire.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { esFecha, esNumero, guardarJSON, mensajes, redondearDecimal } from './utilidades/ayudas';
import { getXlsxStream } from 'xlstream';
import { estructuras } from './aplicacion';
import type { Errata } from './tipos';
import { Aire, MedicionAire } from '@/tipos/compartidos';

export default async function procesarAire(): Promise<Aire> {
const { aire } = estructuras;
const ruta = `./datos/${aire.archivo}.xlsx`;
const flujo = await getXlsxStream({
filePath: ruta,
sheet: aire.nombreHoja,
withHeader: true,
ignoreEmpty: true,
});

let numeroFila = 2;
let primeraFilaProcesada = false;
const errata: Errata[] = [];
/**
* ID, time, Fecha corta,
* pm25, ebc np_NS,
* DIA, UBICACIÓN,
* MOVIMIENTO, HORA DESDE, HORA HASTA,
* AUTOS, BUS VERDE, BUS AZUL, BUS NARANJA, BUS BLANCO, DUALES, BUS ROJO, BUS AMARILLO, BUS GRIS,
* CAMION PEQUEÑO, CAMION GRANDE, MOTOS, BICICLETAS, TOTAL MIXTOS, TOTAL PESADOS,
* HORA, ID_MEDICIÓN, Lat, Lon
*/
return new Promise((resolver) => {
const datos: Aire = {};

flujo.on('data', async (obj) => {
if (!primeraFilaProcesada) {
// console.log(compararListas(Object.keys(raw.obj), ruido.llaves));
primeraFilaProcesada = true;
}

const [
id,
fechaHora,
fecha,
pm25,
ebc,
npNS,
dia,
ubicacion,
mov,
horaA,
horaB,
autos,
busVerde,
busAzul,
busNaranja,
busBlanco,
duales,
busRojo,
busAmarillo,
busGris,
camionPeq,
comionGrande,
motos,
bici,
totalMixtos,
totalPesados,
hora,
idMed,
lat,
lon,
] = obj.formatted.arr;

/** Iniciar objeto para guardar datos del punto */
if (!datos[ubicacion]) {
datos[ubicacion] = {
promedios: {
pm25: 0,
ebc: 0,
npNs: 0,
},
mediciones: [],
};
}

if (fechaHora && esFecha(fechaHora)) {
const mediciones: MedicionAire = [fechaHora, [null, null, null]];

if (pm25) {
if (esNumero(pm25)) {
mediciones[1][0] = +pm25;
} else {
errata.push({ fila: numeroFila, error: `El valor de pm25 no es un número: ${pm25}` });
}
}

if (ebc) {
if (esNumero(ebc)) {
mediciones[1][1] = +ebc;
} else {
errata.push({ fila: numeroFila, error: `El valor de ebc no es un número: ${ebc}` });
}
}

if (npNS) {
if (esNumero(npNS)) {
mediciones[1][2] = +npNS;
} else {
errata.push({ fila: numeroFila, error: `El valor de np_NS no es un número: ${npNS}` });
}
}

datos[ubicacion].mediciones.push(mediciones);
} else {
errata.push({ fila: numeroFila, error: `Esta fecha no es válida: ${fechaHora}` });
}

numeroFila++;
});

flujo.on('close', () => {
if (errata.length) guardarJSON(errata, 'errataAmbiente');

for (const nombrePunto in datos) {
let sumaPm25 = 0;
let totalMedicionesPm25 = 0;
let sumaEbc = 0;
let totalMedicionesEbc = 0;
let sumaNpNs = 0;
let totalMedicionesNpNs = 0;

datos[nombrePunto].mediciones.forEach((medicion) => {
const [pm25, ebc, npNS] = medicion[1];

if (pm25) {
sumaPm25 += pm25;
totalMedicionesPm25++;
}

if (ebc) {
sumaEbc += ebc;
totalMedicionesEbc++;
}

if (npNS) {
sumaNpNs += npNS;
totalMedicionesNpNs++;
}
});

datos[nombrePunto].promedios.pm25 = redondearDecimal(sumaPm25 / totalMedicionesPm25);
datos[nombrePunto].promedios.ebc = redondearDecimal(sumaEbc / totalMedicionesEbc);
datos[nombrePunto].promedios.npNs = redondearDecimal(sumaNpNs / totalMedicionesNpNs);
}

mensajes.exito(`Datos de Ambiente procesados`);
resolver(datos);
});

flujo.on('error', (error) => {
throw new Error(JSON.stringify(error, null, 2));
});
});
}
15 changes: 11 additions & 4 deletions aplicaciones/procesador/fuente/procesarElementosLinea.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { getXlsxStream } from 'xlstream';
import { estructuras } from './aplicacion';
import slugificar from 'slug';
import type { ElementosPorPunto, Punto } from '@/tipos/compartidos';
import type { Aire, Punto } from '@/tipos/compartidos';
import type { Errata } from './tipos';
import { esNumero, mensajes } from './utilidades/ayudas';

export default async (puntos: Punto[]): Promise<Punto[]> => {
export default async (puntos: Punto[], aire: Aire): Promise<Punto[]> => {
const { linea } = estructuras;
const ruta = `./datos/${linea.archivo}.xlsx`;
const flujo = await getXlsxStream({
Expand All @@ -20,15 +20,14 @@ export default async (puntos: Punto[]): Promise<Punto[]> => {

return new Promise((resolver) => {
const errata: Errata[] = [];
const elementosProcesados: ElementosPorPunto = {};

flujo.on('data', async (obj) => {
if (!primeraFilaProcesada) {
// console.log(compararListas(Object.keys(raw.obj), ruido.llaves));
primeraFilaProcesada = true;
}

const { nombre, latitud, longitud, puntoRuido, ilustracion } = obj.formatted.obj;
const { nombre, latitud, longitud, puntoRuido, ilustracion, idAire } = obj.formatted.obj;

const slug = slugificar(nombre);
const punto = puntos.find((punto) => punto.slug == slug);
Expand All @@ -50,6 +49,14 @@ export default async (puntos: Punto[]): Promise<Punto[]> => {
}
}

if (idAire) {
if (aire[idAire]) {
punto.idAire = idAire;
} else {
errata.push({ fila: numeroFila, error: `El punto ${idAire} no existe en los datos de aire` });
}
}

/** Coordenadas de los puntos */
if (latitud && longitud && esNumero(latitud) && esNumero(longitud)) {
punto.lat = latitud;
Expand Down
1 change: 1 addition & 0 deletions aplicaciones/www/estaticos/datos/aire.json

Large diffs are not rendered by default.

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

Large diffs are not rendered by default.

46 changes: 16 additions & 30 deletions tipos/compartidos.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
export type Medicion = number | null;

export type Ruido = [
/** fecha y hora de la medición de niveles de ruido. */
hora: number | null,
hora: Medicion,
/** Leq-1: contiene los niveles intermedios de ruido en esos 10 segundos de medición. Con este dato la experta menciona se puede comparar con la normativa de un máximo de 80db. En promedio se observó que los niveles de ruido son cercanos a 80db pero no superaron la normativa nacional. */
leq1: number | null,
leq1: Medicion,
/** Lmax: contiene los niveles máximos de ruido captados en esos 10 segundos de medición. */
lmax1: number | null,
lmax1: Medicion,
];

export interface DatosRuido {
Expand Down Expand Up @@ -38,6 +40,7 @@ export interface Punto {
proximidad?: number;
caminabilidad?: number;
idRuido?: string;
idAire?: string;
ilustraciones?: string[];
}

Expand All @@ -52,32 +55,15 @@ export type LlavesDatosPunto =

export type LlavesZats = 'habitabilidad' | 'ambiente' | 'infraestructura' | 'movilidad' | 'proximidad';

export interface ElementosPorPunto {
[
/** indica el número de paradero en el cual se tomó la información. */
punto: number
]: {
ilustraciones?: {
/** Ruta al archivo de la ilustración */
ruta: string;
nombre: string;
descripcion?: string;
}[];
/** Ruta al archivo del podcast */
podcast?: {
ruta: string;
nombre: string;
descripcion?: string;
}[];
perfiles?: {
ruta: string;
nombre: string;
descripcion?: string;
}[];
textos?: {
/** Ruta al archivo de la ilustración */
texto: string;
categoria?: string;
}[];
export type LlavesAire = 'pm25' | 'ebc' | 'npNs';

export type ValoresMedicionAire = [pm25: Medicion, ebc: Medicion, npNs: Medicion];

export type MedicionAire = [fecha: string, ValoresMedicionAire];

export interface Aire {
[nombre: string]: {
promedios: { [llave in LlavesAire]: number };
mediciones: MedicionAire[];
};
}

0 comments on commit 23b0397

Please sign in to comment.