Commit 2a7ff936 authored by Agustin's avatar Agustin
Browse files

Merge branch 'feature/Calculos' into develop

parents 06630386 b1dc91f3
Pipeline #15792 passed with stage
in 2 minutes and 24 seconds
import {
Handler, Request, Response, Router,
} from 'express';
import AgeGroupJSON from '../DTOs/AgeGroupJSON';
import CalculatorService from '../Services/CalculatorService';
import CalculatorResponse from '../DTOs/CalculatorResponseDTO';
import logger from '../Logger/logger';
......@@ -9,9 +8,10 @@ import logger from '../Logger/logger';
const router = Router();
const getREP: Handler = async (req: Request, res: Response) => {
const groups: AgeGroupJSON[] = req.body;
const { groups, extraData } = req.body;
try {
const EnergyReq: CalculatorResponse = CalculatorService.calculateEnergeticRequirement(groups);
const EnergyReq:
CalculatorResponse = CalculatorService.calculateEnergeticRequirement(groups, extraData);
return res.status(200).send(EnergyReq);
} catch (error) {
const e = error as Error;
......
type AdultPAL = {
urbanPercentage: number;
activeUrbanPAL: number;
lowUrbanPAL: number;
ruralPercentage: number;
activeRuralPAL: number;
lowRuralPAL: number;
};
export default AdultPAL;
......@@ -2,10 +2,10 @@ import AgeBracket from '../Enum/AgeBracket';
import Sex from '../Enum/Sex';
type AgeGroup = {
edad: AgeBracket;
sexo: Sex;
pesoMediano: number;
cantidad: number;
age: AgeBracket;
sex: Sex;
medianWeight: number;
population: number;
};
export default AgeGroup;
type AgeGroupJSON = {
edad: string;
sexo: string;
pesoMediano: string;
cantidad: string;
age: string; // TODO: check enum
sex: string;
medianWeight: number; // TODO: check if it can be number again
population: number; // TODO: check if it can be number again
};
export default AgeGroupJSON;
......@@ -2,8 +2,8 @@ import EnergeticRequirement from './EnergeticRequirementDTO';
import GroupEnergeticRequirement from './GroupEnergeticRequirementDTO';
type CalculatorResponse = {
requerimientosPorGrupo: GroupEnergeticRequirement[];
requerimientoTotal: EnergeticRequirement;
groupsRequirements: GroupEnergeticRequirement[];
totalRequirement: EnergeticRequirement;
};
export default CalculatorResponse;
type EnergeticRequirement = {
requerimientoEnergeticoPerCapita: number;
requerimientoEnergeticoTotal: number;
poblacionTotal: number;
perCapita: number;
total: number;
totalPopulation: number;
};
export default EnergeticRequirement;
import AdultPAL from './AdultPALDTO';
import IndividualMaternity from './IndividualMaternityDTO';
import MinorPAL from './MinorPALDTO';
import PopulationMaternity from './PopulationMaternityDTO';
type ExtraData = {
minorPAL: MinorPAL | undefined;
adultPAL: AdultPAL | undefined;
maternity18To29: IndividualMaternity | PopulationMaternity | undefined;
maternity30To59: IndividualMaternity | PopulationMaternity | undefined;
};
export default ExtraData;
import AgeGroupJSON from './AgeGroupJSON';
type GroupEnergeticRequirement = {
grupoEtario: AgeGroupJSON;
requerimientoEnergeticoPerCapita: number;
requerimientoEnergeticoTotal: number;
group: AgeGroupJSON;
perCapita: number;
total: number;
};
export default GroupEnergeticRequirement;
type IndividualMaternity = {
pregnantWomen: number;
lactatingWomen: number;
};
export default IndividualMaternity;
type MinorPAL = {
lowPALPrevalence: number;
moderatePALPrevalence: number;
intensePALPrevalence: number;
};
export default MinorPAL;
type PopulationMaternity = {
countryBirthRate: number;
countryPopulation: number;
};
export default PopulationMaternity;
enum ParameterType {
NAF = 'NAF',
PesoPorDefecto = 'Peso por defecto',
EmbarazoYLactancia = 'Embarazo y lactancia',
ConstanteDeEcuacion = 'Constante de ecuacion'
PAL = 'NAF',
DefaultWeight = 'Peso por defecto',
Maternity = 'Embarazo y lactancia',
EquationConstant = 'Constante de ecuacion'
}
export default ParameterType;
enum Sex {
Masculino = 'Masculino',
Femenino = 'Femenino',
Male = 'Masculino',
Female = 'Femenino',
}
export default Sex;
import ParameterType from '../Enum/ParameterType';
class Parameter {
name: string;
value: number;
constructor(name: string, value: number) {
parameterType: ParameterType;
constructor(name: string, value: number, parameterType: ParameterType) {
this.name = name;
this.value = value;
this.parameterType = parameterType;
}
}
......
......@@ -4,15 +4,17 @@ import ParserService from './ParserService';
import AgeGroup from '../DTOs/AgeGroupDTO';
import CalculatorResponse from '../DTOs/CalculatorResponseDTO';
import AgeGroupJSON from '../DTOs/AgeGroupJSON';
import ExtraData from '../DTOs/ExtraDataDTO';
const calculateEnergeticRequirement = (data: AgeGroupJSON[]): CalculatorResponse => {
const parametros = new Map<number[], AgeGroup>();
const ageGroups = ParserService.parseGroups(data);
// eslint-disable-next-line max-len
const calculateEnergeticRequirement = (groups: AgeGroupJSON[], data: ExtraData): CalculatorResponse => {
const parameters = new Map<number[], AgeGroup>();
const ageGroups = ParserService.parseGroups(groups);
ageGroups.forEach((group: AgeGroup) => {
parametros.set(ParameterService.getEquationValues(group.edad, group.sexo), group);
parameters.set(ParameterService.getEquationValues(group.age, group.sex), group);
});
const res: CalculatorResponse = ERCalculator.calculateER(parametros);
const res: CalculatorResponse = ERCalculator.calculateER(parameters, data);
return res;
};
......
......@@ -2,46 +2,231 @@ import AgeGroup from '../DTOs/AgeGroupDTO';
import EnergeticRequirement from '../DTOs/EnergeticRequirementDTO';
import CalculatorResponse from '../DTOs/CalculatorResponseDTO';
import GroupEnergeticRequirement from '../DTOs/GroupEnergeticRequirementDTO';
import ParserService from './ParserService';
import ExtraData from '../DTOs/ExtraDataDTO';
import MinorPAL from '../DTOs/MinorPALDTO';
import AdultPAL from '../DTOs/AdultPALDTO';
import IndividualMaternity from '../DTOs/IndividualMaternityDTO';
import PopulationMaternity from '../DTOs/PopulationMaternityDTO';
import Sex from '../Enum/Sex';
import AgeBracket from '../Enum/AgeBracket';
import ParserService from './ParserService';
// eslint-disable-next-line max-len
const isIndividualMaternity = (obj: IndividualMaternity | PopulationMaternity): obj is IndividualMaternity => {
if ((obj as IndividualMaternity).pregnantWomen) {
return true;
}
return false;
};
// TEE (Total Energetic Expenditure) = GET (Gasto Energetico Total)
const calculateTEE = (group: AgeGroup, params: number[], preval: MinorPAL): number => {
const teeModerate: number = params[0]
+ (params[1] * group.medianWeight)
- params[2] * (group.medianWeight * group.medianWeight);
const teeLow: number = teeModerate - (teeModerate * params[4]) / 100;
const teeIntense: number = teeModerate + (teeModerate * params[5]) / 100;
const ret: number = (teeLow * preval.lowPALPrevalence) / 100
+ (teeModerate * preval.moderatePALPrevalence) / 100
+ (teeIntense * preval.intensePALPrevalence) / 100;
return ret;
};
// BMR (Basal Metabolic Rate) = TMB (Tasa Metabolica Basal)
const calculateBMR = (group: AgeGroup, params: number[]): number => {
const ret: number = params[0] * group.medianWeight + params[1];
return ret;
};
// PAL (Physical Activity Level) = NAF (Nivel de Actividad Fisica)
const calculatePAL = (params: number[], popData: AdultPAL): number => {
const ruralPAL: number = (popData.activeRuralPAL * params[2]) / 100
+ (popData.lowRuralPAL * params[3]) / 100;
const urbanPAL: number = (popData.activeUrbanPAL * params[4]) / 100
+ (popData.lowUrbanPAL * params[5]) / 100;
const ret = (ruralPAL * popData.ruralPercentage) / 100
+ (urbanPAL * popData.urbanPercentage) / 100;
return ret;
};
// eslint-disable-next-line max-len
const calculateERWomenIndividual = (group: AgeGroup, params: number[], popData: IndividualMaternity, req: number): number => {
const percentPregnantWomen = (popData.pregnantWomen * 100) / group.population;
const percentLactatingWomen = (popData.lactatingWomen * 100) / group.population;
const reqPregnantWomen = (percentPregnantWomen * (req + params[6])) / 100;
const reqLactatingWomen = (percentLactatingWomen * (req + params[7])) / 100;
const reqRestOfWomen = ((100 - percentPregnantWomen - percentLactatingWomen) * req) / 100;
return reqPregnantWomen + reqLactatingWomen + reqRestOfWomen;
};
// eslint-disable-next-line max-len
const calculateERWomenPopulation = (group: AgeGroup, params: number[], popData: PopulationMaternity, req: number): number => {
const annualBirths = popData.countryBirthRate * popData.countryPopulation;
const percentPregnantWomen = (annualBirths * 75) / group.population;
const percentLactatingWomen = (annualBirths * 50) / group.population;
const reqPregnantWomen = (percentPregnantWomen * (req + params[6])) / 100;
const reqLactatingWomen = (percentLactatingWomen * (req + params[7])) / 100;
const reqRestOfWomen = ((100 - percentPregnantWomen - percentLactatingWomen) * req) / 100;
return reqPregnantWomen + reqLactatingWomen + reqRestOfWomen;
};
const calculateLessThanAYear = (group: AgeGroup, params: number[]): GroupEnergeticRequirement => {
const requirement = params[0] + (params[1] * group.pesoMediano) + params[2];
const requirement = params[0] + (params[1] * group.medianWeight) + params[2];
const groupRequirement: GroupEnergeticRequirement = {
grupoEtario: ParserService.unparseGroup(group),
requerimientoEnergeticoPerCapita: requirement,
requerimientoEnergeticoTotal: requirement * group.cantidad,
group: ParserService.unparseGroup(group),
perCapita: requirement,
total: requirement * group.population,
};
return groupRequirement;
};
const calculateOneToFiveYears = (group: AgeGroup, params: number[]): GroupEnergeticRequirement => {
const calculate1To5Years = (group: AgeGroup, params: number[]): GroupEnergeticRequirement => {
const requirement = params[0]
+ (params[1] * group.pesoMediano)
+ (params[2] * (group.pesoMediano ** 2))
+ (params[1] * group.medianWeight)
+ (params[2] * (group.medianWeight ** 2))
+ params[3];
const groupRequirement: GroupEnergeticRequirement = {
grupoEtario: ParserService.unparseGroup(group),
requerimientoEnergeticoPerCapita: requirement,
requerimientoEnergeticoTotal: requirement * group.cantidad,
group: ParserService.unparseGroup(group),
perCapita: requirement,
total: requirement * group.population,
};
return groupRequirement;
};
const calculateER = (groupParameters: Map<number[], AgeGroup>): CalculatorResponse => {
// eslint-disable-next-line max-len
const calculate6To17Years = (group: AgeGroup, params: number[], data: ExtraData): GroupEnergeticRequirement => {
let tee: number;
if (typeof (data.minorPAL) === 'undefined') {
throw new Error('Missing data');
} else {
tee = calculateTEE(group, params, data.minorPAL);
}
const requirement = tee + params[3];
const groupRequirement: GroupEnergeticRequirement = {
group: ParserService.unparseGroup(group),
perCapita: requirement,
total: requirement * group.population,
};
return groupRequirement;
};
// eslint-disable-next-line max-len
const calculate18To29Years = (group: AgeGroup, params: number[], data: ExtraData): GroupEnergeticRequirement => {
let bmr: number;
let pal: number;
if (typeof (data.adultPAL) === 'undefined') {
throw new Error('Missing data');
} else {
bmr = calculateBMR(group, params);
pal = calculatePAL(params, data.adultPAL);
}
let requirement: number = bmr * pal;
// If the group's sex is Female, then you have to take into account
// the extra energy required by women that are pregnant or lactating
if (group.sex === Sex.Female) {
if (data.maternity18To29 === undefined) {
throw new Error('Missing data');
} else if (isIndividualMaternity(data.maternity18To29)) {
requirement = calculateERWomenIndividual(group, params, data.maternity18To29, requirement);
} else {
requirement = calculateERWomenPopulation(group, params, data.maternity18To29, requirement);
}
}
const groupRequirement: GroupEnergeticRequirement = {
group: ParserService.unparseGroup(group),
perCapita: requirement,
total: requirement * group.population,
};
return groupRequirement;
};
// eslint-disable-next-line max-len
const calculate30To59Years = (group: AgeGroup, params: number[], data: ExtraData): GroupEnergeticRequirement => {
let bmr: number;
let pal: number;
if (typeof (data.adultPAL) === 'undefined') {
throw new Error('Missing data');
} else {
bmr = calculateBMR(group, params);
pal = calculatePAL(params, data.adultPAL);
}
let requirement: number = bmr * pal;
// If the group's sex is Female, then you have to take into account
// the extra energy required by women that are pregnant or lactating
if (group.sex === Sex.Female) {
if (typeof (data.maternity30To59) === 'undefined') {
throw new Error('Missing data');
} else if (isIndividualMaternity(data.maternity30To59)) {
requirement = calculateERWomenIndividual(group, params, data.maternity30To59, requirement);
} else {
requirement = calculateERWomenPopulation(group, params, data.maternity30To59, requirement);
}
}
const groupRequirement: GroupEnergeticRequirement = {
group: ParserService.unparseGroup(group),
perCapita: requirement,
total: requirement * group.population,
};
return groupRequirement;
};
// eslint-disable-next-line max-len
const calculate60PlusYears = (group: AgeGroup, params: number[], data: ExtraData): GroupEnergeticRequirement => {
let bmr: number;
let pal: number;
if (typeof (data.adultPAL) === 'undefined') {
throw new Error('Missing data');
} else {
bmr = calculateBMR(group, params);
pal = calculatePAL(params, data.adultPAL);
}
const requirement: number = bmr * pal;
const groupRequirement: GroupEnergeticRequirement = {
group: ParserService.unparseGroup(group),
perCapita: requirement,
total: requirement * group.population,
};
return groupRequirement;
};
// eslint-disable-next-line max-len
const calculateER = (groupParameters: Map<number[], AgeGroup>, data: ExtraData): CalculatorResponse => {
let totalOfPeople = 0;
let totalRequirement = 0;
const requirements: GroupEnergeticRequirement[] = [];
groupParameters.forEach((group: AgeGroup, params: number[]) => {
totalOfPeople += group.cantidad;
totalOfPeople += group.population;
let groupRequirement: GroupEnergeticRequirement;
switch (group.edad) {
switch (group.age) {
case AgeBracket.m0:
case AgeBracket.m1:
case AgeBracket.m2:
......@@ -62,26 +247,53 @@ const calculateER = (groupParameters: Map<number[], AgeGroup>): CalculatorRespon
case AgeBracket.a3:
case AgeBracket.a4:
case AgeBracket.a5: {
groupRequirement = calculateOneToFiveYears(group, params);
groupRequirement = calculate1To5Years(group, params);
break;
}
case AgeBracket.a6:
case AgeBracket.a7:
case AgeBracket.a8:
case AgeBracket.a9:
case AgeBracket.a10:
case AgeBracket.a11:
case AgeBracket.a12:
case AgeBracket.a13:
case AgeBracket.a14:
case AgeBracket.a15:
case AgeBracket.a16:
case AgeBracket.a17: {
groupRequirement = calculate6To17Years(group, params, data);
break;
}
case AgeBracket.a18_29: {
groupRequirement = calculate18To29Years(group, params, data);
break;
}
case AgeBracket.a30_59: {
groupRequirement = calculate30To59Years(group, params, data);
break;
}
case AgeBracket.a60: {
groupRequirement = calculate60PlusYears(group, params, data);
break;
}
default: {
throw new Error('Parsing error, attribute edad does not respect format');
}
}
totalRequirement += groupRequirement.requerimientoEnergeticoTotal;
totalRequirement += groupRequirement.total;
requirements.push(groupRequirement);
});
const totalER: EnergeticRequirement = {
requerimientoEnergeticoPerCapita: totalRequirement / totalOfPeople,
requerimientoEnergeticoTotal: totalRequirement,
poblacionTotal: totalOfPeople,
perCapita: totalRequirement / totalOfPeople,
total: totalRequirement,
totalPopulation: totalOfPeople,
};
const result: CalculatorResponse = {
requerimientosPorGrupo: requirements,
requerimientoTotal: totalER,
groupsRequirements: requirements,
totalRequirement: totalER,
};
return result;
......
......@@ -7,177 +7,328 @@ const getEquationValues = (ageBracket: AgeBracket, sex: Sex): number[] => {
let res: number[] = [];
switch (ageBracket) {
case (AgeBracket.m0): {
if (sex === Sex.Masculino) {
if (sex === Sex.Male) {
// -152 + (92.8*MP) + 211
res = [-152, 92.8, 211];
} else if (sex === Sex.Femenino) {
} else if (sex === Sex.Female) {
// -152 + (92.8*MP) + 178
res = [-152, 92.8, 178];
}
break;
}
case (AgeBracket.m1): {
if (sex === Sex.Masculino) {
if (sex === Sex.Male) {
// -152 + (92.8*MP) + 183
res = [-152, 92.8, 183];
} else if (sex === Sex.Femenino) {
} else if (sex === Sex.Female) {
// -152 + (92.8*MP) + 161
res = [-152, 92.8, 161];
}
break;
}
case (AgeBracket.m2): {
if (sex === Sex.Masculino) {
if (sex === Sex.Male) {
// -152 + (92.8*MP) + 139
res = [-152, 92.8, 139];
} else if (sex === Sex.Femenino) {
} else if (sex === Sex.Female) {
// -152 + (92.8*MP) + 134
res = [-152, 92.8, 134];
}
break;
}
case (AgeBracket.m3): {
if (sex === Sex.Masculino) {
if (sex === Sex.Male) {
// -152 + (92.8*MP) + 53
res = [-152, 92.8, 53];
} else if (sex === Sex.Femenino) {
} else if (sex === Sex.Female) {
// -152 + (92.8*MP) + 68
res = [-152, 92.8, 68];
}
break;
}
case (AgeBracket.m4): {
if (sex === Sex.Masculino) {
if (sex === Sex.Male) {
// -152 + (92.8*MP) + 46
res = [-152, 92.8, 46];
} else if (sex === Sex.Femenino) {
} else if (sex === Sex.Female) {
// -152 + (92.8*MP) + 57
res = [-152, 92.8, 57];
}
break;
}
case (AgeBracket.m5): {
if (sex === Sex.Masculino) {
if (sex === Sex.Male) {
// -152 + (92.8*MP) + 36
res = [-152, 92.8, 36];
} else if (sex === Sex.Femenino) {
} else if (sex === Sex.Female) {
// -152 + (92.8*MP) + 47
res = [-152, 92.8, 47];
}
break;
}
case (AgeBracket.m6): {
if (sex === Sex.Masculino) {
if (sex === Sex.Male) {
// -99.4 + (88.6*MP) + 17
res = [-99.4, 88.6, 17];
} else if (sex === Sex.Femenino) {
} else if (sex === Sex.Female) {