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 zcmV<02qpLHp8>_60k9?q3HESK6|@5Y04kF&2N-|bZsRr(eJ{{|5cJSDMWU{j8f9Ty zQrAEd1c^6!F%Zxa9kJ1^BxO4r?7w#?S&nmQ;bv>tlt~T`&&-?|oqpMtg|a4$)4B>( zbYiFqsnR;5)kCO$n<v^xRk*-ahKsr)q54F)`sM7`UrskQdtBD_qXGaG57k_VCeU@B z=A?hb{G@J31v{&nl~}-(J?Ok)1ZO-aM3jYY8iuQvm{w|!5U^t~>eY&-B&yT4B$env z7%8v-`aGu%AJEG57`PI%$F|YZx@-VqNee2TI#5+9(_r>c)eJ8SaC?g!Wy|2}!VeiR zn8Qu5_3o;YrmW`mN}K?+-jjakKQeTLUWI>P`#uK8A=x@3YbtZNXT{u4vU2xW?h6<) zei{vdv^uQ>5WG*KIeTuVdUm>^1-b2|tKg=&#HGwsp(+LDBF?BFS*Ut2tvBS=0&AN| zOAFXFZOe33{cJDiE2d;*h1){RLC6C<REF#NrXwvu7~?_^R$)P=btOQDJHLKba~*&7 zG_OJ7$~F0`rHnvffxf_37;zflCBMQVS6Wtt>NHq<<KX^+k?K2L3`M~g$?Wov#ntQv zHk#&siPJ|?Wed*I#SLL=K<A4C@#6QD@*m`jQyCK-g3=T3|Gy0o@Mpmw(JR3e_&<xz zAx$@U4M_uOWV@Q4K~|7;U!^QS_s@SLWI1S@Ak8wpShFK!YNL^7XegOZV`E}PBQN;@ z&M-GfYut)_rw0igsx~D5-PQ%(4m-#QTAIDkcs6z)O+McY!`=_+u<U%dlx+Bma^zIm z-q9+nH=(K_6P$W_J>7JhcQg|@NY6KHFzMI668ew>W90ZgEaFtqHJRgOs9Jy01yk}2 z)#tHoSjhAs2wpVRY%BJ)$=G)^FHT~6oH#x*#vMQXfMC~gfoS(ss;)}D*5wk^^;;o+ zN6_G9PwoP*DlCvUu~~+spC6n#FozzvH#gs!U$lRc53aBe&RG9&=HLqFz})VnHn@}G zB86&|kB&O{ZjPh{*@|;6x+i}W3WcyC+ZcO>Z)-+uIhsB4A%IZ$+SHEB*zw{ho;XrP z@=X@}AN{<m*I;->N|rfhV$Prx;l+AQRujxY_Faf|;Co1R;*2JS1r+TBC7O+VLz_%o zTXUksay%4GW2cjRPgc6W`eZj9>D_69MGJ|NO{SX%a!hus`^8niu+uZos}2!dM>6ia z)Bk381Kt<pNaN)8NW<yn#r)z(+w*vSf0uMZ`q0}x8*=P4qz^ef`x}#C4HT2=Ne;6W z3vmq!W7V=H=mG!$>jjgL7$|@0J6OKw7(xgNsoJ1ud$-!|;o31nu!1pbJ14F7-FFO4 zS}8YCB|w7@-#_E|y?8vymK;DEp}K-ben<&)Tvejm7WC(jwU<$1EbA)PstyWz216g0 z4__8XrFW(QumlO6DQIJDp9g{A4M=8u)kB9fwbGJV{MFmQ^cq+-Y?6O%5QkwJNG3Wu z5^{YHL)Eq5P%6Hc(Ag29p=B2HH;w4cg(mquILY*G-+Nri9uXVS3VR-)lt`YxY&)gd zrp3BXQNlPmX?$XQCl{Gv{6<L%u9Z=>^^qKmIp3B)59R^mSJG|$cVVI=&~Om0f$ymJ zb16mBD=U77O+E=ruP}diTsq&2s-S<fa#qgf&zTpNS>h#07J5%%6nj~kB$N51jAvo` zk1iLLzz(~rh=#hLPf@;_&|tY3{PRn|(R_%BWt&%Mfm=Y0h!SVdjZ!<e@CAoLB${D? zBQkEq0annq1zknxdGluwaWP5+SB;PHMQ=S=`kN*d)NJ3{@9KZ}6~wl&C_KeNom2Aa zT!P_fQIz)MsiSh$A_Bie3U}AgV(c^~D=OPy6#Ln9nxxqbF~**q?_6>lFm^2*o)W${ zR>|LQ8{V)Z5IZ&i@vx8M{M?U{Fh%tXEg7mC68R4R0RR6000960l#yEw!XOYuw?bwC z@@R>*0TQ(vAxMAXS2cxH-MvF;Frpv&N4O_*4}%J4@8e*jHEO!t$fSV-30FG?JoOEb zJ8!M)PmjR|=f|jlZG;4)Tw?bL*3bdLAmHt6xT3RB)UCuJ6F8_4;+;5t5=|i}N)<El zk6D5>>=vhO<&?8F`?Bw4X#D#c5{&y|%fzmFUk=wcDXRuL`uc$<0JB{ixgP}=Z&z!c zvl}}l0e_NFPunmM$KNOM9U{M{PEvs&YJ<iQPeYnUry<_F^AS7}+p;gD*{7f5v}ucw zc=O%=?&tI0x4Pc8P4b4$E2GyeUt}yn4Mr+mui3B7U3$q9PeM!47>#Q-pl8?B*_RdA z5{$zi&RBG$&?kYUeF=8WUWjbTxrY~Qg<pgU9e>1U<61!>bTzjEUPX<($g&IGA_*x- z@DZ5WnaFlX2{Y1mu89B%92;y=ljr#&=Z9KC*ZL0|qH<K(DjIBf({9{jwuDKXtG8aw zg?-;I`ehs=%%Ahe`|l6&sj1SVSAeWqNhnECgVl;3j^X6HKYtNuO3y(Mz@Z@Hs;_nD zNq_0sw$F`jzv9pvCw=HVi9)MH4^CMMe>ibZ5}~>gp6<h^J}Z<rL-iB&Ka<>Gw~efK z>Uf#MH#M%rblD-25KWwhMVSO!%E`pN@_YI1c5}z7A}jJVyG)DoO@37_i!#ri#y6ex zk2Xz-b~oLp#H%#Bh{W?UJ0|V{RoqNLSQ#5POyk2G#ii90w&sBZbvrM?e2_X`?dm_1 z5eF5s?LEK?3HESK6|@5Y04lS#NlpO@W7V=H=mG!$>jjezOI87vlVwXl0Tq*`OF98c zli^E20(B{qwJ9Z&NlYpNcPf*&Dk+nmOez5mlgUg#0W^~eO+^7NlTb}S0Y{UOO+^8! zlh;i^0h5y$PAeQ2Z&z!c0RR9e0{{RK0000000000000000OUH8Urs#%xs#nvJprPV o+fG0N=|YnoPf7ysM3ZSxN(A;s005IZM;?>aPY?$ENB{r;09QmLasU7T -- GitLab