From 7f48695f8e39e7137ebb3cb19bfa55c5de1fba96 Mon Sep 17 00:00:00 2001
From: Renzo Beux <renzobeux@gmail.com>
Date: Mon, 27 Sep 2021 12:35:39 -0300
Subject: [PATCH] feat: sheetParser now returns an ageGroup array

---
 src/Controllers/SheetController.ts |   3 +-
 src/Enum/AgeBracket.ts             |   2 +-
 src/Services/SheetService.ts       | 136 ++++++++++++++++++++++++++---
 src/Services/test.xlsx             | Bin 20421 -> 20459 bytes
 4 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/src/Controllers/SheetController.ts b/src/Controllers/SheetController.ts
index 8658d81..727fc27 100644
--- a/src/Controllers/SheetController.ts
+++ b/src/Controllers/SheetController.ts
@@ -4,13 +4,14 @@ import {
 import { SheetParserResponse } from '../Models/SheetParserResponse';
 import SheetService from '../Services/SheetService';
 import logger from '../Logger/logger';
+import AgeGroupJSON from '../DTOs/AgeGroupJSON';
 
 const router = Router();
 
 const parseSheet: Handler = async (req: Request, res: Response) => {
   const sheet: Buffer = req.body;
   try {
-    const parsedSheet: SheetParserResponse = SheetService.parseSheetService(sheet);
+    const parsedSheet: AgeGroupJSON[] = SheetService.parseSheetService(sheet);
     return res.status(200).send(parsedSheet);
   } catch (error) {
     const e = error as Error;
diff --git a/src/Enum/AgeBracket.ts b/src/Enum/AgeBracket.ts
index f3610df..2017b24 100644
--- a/src/Enum/AgeBracket.ts
+++ b/src/Enum/AgeBracket.ts
@@ -1,6 +1,6 @@
 enum AgeBracket {
   m0 = '0 meses',
-  m1 = '1 mes',
+  m1 = '1 meses',
   m2 = '2 meses',
   m3 = '3 meses',
   m4 = '4 meses',
diff --git a/src/Services/SheetService.ts b/src/Services/SheetService.ts
index e30e75a..31ac0cf 100644
--- a/src/Services/SheetService.ts
+++ b/src/Services/SheetService.ts
@@ -1,8 +1,11 @@
 import * as XLSX from 'xlsx';
 import { SheetNames } from '../Config/Constants';
+import AgeGroupJSON from '../DTOs/AgeGroupJSON';
+import Sex from '../Enum/Sex';
 import {
   SheetParserResponse, Menores, Mayores, MenoresSheet, MayoresSheet,
 } from '../Models/SheetParserResponse';
+import ParameterService from './ParameterService';
 
 /* PRIVATE FUNCTIONS */
 // const ec = (r: number, c: number): string => XLSX.utils.encode_cell({ r, c });
@@ -56,12 +59,30 @@ const parseBabies = (worksheet: XLSX.WorkSheet): Menores[] => {
   });
   return res;
 };
+const getMedianFromArray = (arr: number[]): number => {
+  const arrSort = arr.sort((a, b) => a - b);
+  const len = arr.length;
+  const mid = Math.ceil(len / 2);
+  const median = len % 2 === 0 ? (arrSort[mid] + arrSort[mid - 1]) / 2 : arrSort[mid - 1];
+  return median;
+};
+
+const getLiteralGroup = (age: number): string => {
+  if (age >= 18 && age <= 29) {
+    return '18-29';
+  } if (age >= 30 && age <= 59) {
+    return '30-59';
+  } if (age >= 60) {
+    return '60+';
+  }
+  return `${age}`;
+};
 
 /* EXPORT FUNCTIONS */
 
-const parseSheetService = (data: Buffer): SheetParserResponse => {
+const parseSheetService = (data: Buffer): AgeGroupJSON[] => {
   const workbook: XLSX.WorkBook = XLSX.read(data);
-  let parsed: SheetParserResponse = null;
+  const parsed: SheetParserResponse = null;
   let hombresMenores: Menores[] = [];
   let hombres: Mayores[] = [];
   let mujeresMenores: Menores[] = [];
@@ -92,14 +113,109 @@ const parseSheetService = (data: Buffer): SheetParserResponse => {
         throw new Error(`Sheet name ${name} is not part of the scheme `);
     }
   });
-  parsed = {
-    hombresMenores,
-    hombres,
-    mujeresMenores,
-    mujeres,
-  };
-
-  return parsed;
+
+  const res: AgeGroupJSON[] = [];
+
+  let auxObj: {[key: string]: number[]} = {};
+  // group HombresMenores
+  // Iterate on hombresMenores and put
+  // elemnts on auxObj
+  hombresMenores.forEach((item) => {
+    if (item === null) throw new Error('Item is null');
+    const bridge: string = (item.edad).toString();
+    auxObj[bridge] = auxObj[bridge] ? auxObj[bridge] : [];
+    (auxObj[bridge]).push(item.peso);
+  });
+  // creates AgeGroup and insert into res
+  let auxObjKeys = Object.keys(auxObj);
+  auxObjKeys.forEach((key) => {
+    const toInsert: AgeGroupJSON = {
+      age: `${key} meses`,
+      sex: Sex.Male,
+      medianWeight: getMedianFromArray(auxObj[key]),
+      population: auxObj[key].length,
+    };
+    res.push(toInsert);
+  });
+
+  auxObj = {};
+
+  mujeresMenores.forEach((item) => {
+    if (item === null) throw new Error('Item is null');
+    const bridge: string = (item.edad).toString();
+    auxObj[bridge] = auxObj[bridge] ? auxObj[bridge] : [];
+    (auxObj[bridge]).push(item.peso);
+  });
+
+  // creates AgeGroup for mujeresMenores and insert into res
+  auxObjKeys = Object.keys(auxObj);
+  auxObjKeys.forEach((key) => {
+    const toInsert: AgeGroupJSON = {
+      age: `${key} meses`,
+      sex: Sex.Female,
+      medianWeight: getMedianFromArray(auxObj[key]),
+      population: auxObj[key].length,
+    };
+    res.push(toInsert);
+  });
+
+  auxObj = {};
+  hombres.forEach((item) => {
+    if (item === null) throw new Error('Item is null');
+    const bridge: string = getLiteralGroup(item.edad);
+    auxObj[bridge] = auxObj[bridge] ? auxObj[bridge] : [];
+    let peso;
+    if (!item.peso) {
+      if (!item.talla) { throw new Error('Talla and Peso not defined'); }
+      // ParameterService. TODO:
+      peso = 0;
+    } else {
+      peso = item.peso;
+    }
+    (auxObj[bridge]).push(peso);
+  });
+
+  // creates AgeGroup for hombres and insert into res
+  auxObjKeys = Object.keys(auxObj);
+  auxObjKeys.forEach((key) => {
+    const toInsert: AgeGroupJSON = {
+      age: `${key} años`,
+      sex: Sex.Male,
+      medianWeight: getMedianFromArray(auxObj[key]),
+      population: auxObj[key].length,
+    };
+    res.push(toInsert);
+  });
+
+  auxObj = {};
+  mujeres.forEach((item) => {
+    if (item === null) throw new Error('Item is null');
+    const bridge: string = getLiteralGroup(item.edad);
+    auxObj[bridge] = auxObj[bridge] ? auxObj[bridge] : [];
+    let peso;
+    if (!item.peso) {
+      if (!item.talla) { throw new Error('Talla and Peso not defined'); }
+      // ParameterService. TODO:
+      peso = 0;
+    } else {
+      peso = item.peso;
+    }
+    (auxObj[bridge]).push(peso);
+  });
+
+  // creates AgeGroup for hombres and insert into res
+  auxObjKeys = Object.keys(auxObj);
+  auxObjKeys.forEach((key) => {
+    const toInsert: AgeGroupJSON = {
+      age: `${key} años`,
+      sex: Sex.Female,
+      medianWeight: getMedianFromArray(auxObj[key]),
+      population: auxObj[key].length,
+    };
+    res.push(toInsert);
+  });
+
+  return res;
   // TODO: depends on sheet layout what to do
 };
 
diff --git a/src/Services/test.xlsx b/src/Services/test.xlsx
index 3edb2bfeb00af26dd42279a2a4ebbdd2beb50724..caa1d8a9c0b7b1c761755a5f9885356dd2df8a4d 100644
GIT binary patch
delta 2334
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
E0KAz<g8%>k

delta 2266
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

-- 
GitLab