Skip to content
Snippets Groups Projects
Commit 943702db authored by Vytor Calixto's avatar Vytor Calixto :space_invader:
Browse files

Refactor classroom count code

New requirements not implemented yet
parent fc1f4277
No related branches found
No related tags found
No related merge requests found
Pipeline #
......@@ -127,16 +127,6 @@ rqf.addField({
type: 'integer',
field: 'ano_censo'
}
}).addValue({
name: 'period',
table: '@',
tableField: 'turma_turno_id',
resultField: 'period_id',
where: {
relation: '=',
type: 'integer',
field: 'turma_turno_id'
}
}).addValue({
name: 'school_year',
table: '@',
......@@ -158,22 +148,34 @@ rqf.addField({
field: 'localizacao_id'
}
}).addValue({
name: 'education_level_short',
name: 'period',
table: '@',
tableField: 'etapa_resumida',
resultField: 'education_level_short_id',
tableField: 'turma_turno_id',
resultField: 'period_id',
where: {
relation: '=',
type: 'integer',
field: 'etapa_resumida'
field: 'turma_turno_id'
}
});
classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
let classSize = JSON.parse(req.body.class_size) || null;
let integralTime = JSON.parse(req.body.integral_time) || null;
console.log(classSize, integralTime);
if(classSize == null || integralTime == null) {
res.statusCode = 400;
return res.json({err: {message: "There was an error processing class_size or integral_time. Check your JSON sintax and be sure you're sending both paramenters."}});
}
req.classSize = classSize;
req.integralTime = integralTime;
req.dims.state = true;
req.dims.city = true;
req.dims.period = true;
req.dims.education_level_short = true;
req.dims.school_year = true;
req.dims.location = true;
req.sql.field('COUNT(*)', 'total')
......@@ -187,6 +189,28 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
next();
}, rqf.build(), query, id2str.transform(), (req, res, next) => {
req.enrollment = req.result;
// Gera a relação etapa de ensino X ano escolar
req.educationSchoolYear = {};
for(let i = 10; i < 80; ++i) {
if(id2str.schoolYear(i) !== id2str.schoolYear(99)) {
let educationLevelId = Math.floor(i/10);
let classSize = req.classSize.find((el) => {return el.id === educationLevelId});
let integralTime = req.integralTime.find((el) => {return el.id === educationLevelId});
let numberStudentClass = (typeof classSize !== 'undefined') ? classSize.numberStudentClass : null;
let offerGoal = (typeof integralTime !== 'undefined') ? integralTime.offerGoal : null;
req.educationSchoolYear[i] = {
id: educationLevelId,
name: id2str.educationLevelShort(educationLevelId),
numberStudentClass,
offerGoal
};
}
}
req.resetSql();
next();
}, rqf.parse(), (req, res, next) => {
......@@ -205,128 +229,173 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
next();
}, rqf.build(), query, id2str.transform(), (req, res, next) => {
let classSize = JSON.parse(req.body.class_size) || null;
let integralTime = JSON.parse(req.body.integral_time) || null;
console.log(classSize, integralTime);
if(classSize == null || integralTime == null) {
res.statusCode = 400;
return res.json({err: {message: "There was an error processing class_size or integral_time. Check your JSON sintax and be sure you're sending both paramenters."}});
}
req.classroom = req.result;
let classroom = [];
// req.result = [{classroom: req.classroom, enrollment: req.enrollment}]; return next();
req.classroom.forEach((c) => {
let cityObjects = req.classroom.filter((value) => {
return (c.city_id == value.city_id && c.year == value.year);
});
// Cria estrutura de resposta requisitada:
let i = 0;
let j = 0;
let result = [];
let hashSet = new Set();
while (i < req.classroom.length) {
let classroom = req.classroom[i];
// Cria hash única para cada cidade, dado um ano
let hash = '' + classroom.year + classroom.city_id;
// Estrutura do objeto do resultado final
let obj = {
state_id: c.state_id,
state_name: c.state_name,
city_id: c.city_id,
city_name: c.city_name,
year: c.year,
year: classroom.year,
name: classroom.name,
state_id: classroom.state_id,
state_name: classroom.state_name,
city_id: classroom.city_id,
city_name: classroom.city_name,
locations: []
};
cityObjects.forEach((co) => {
obj.locations.push({
location_id: co.location_id,
location_name: co.location_name,
total_classroom: co.total
});
});
if(classroom.findIndex((el) => {return (el.city_id === obj.city_id && el.year === obj.year)}) === -1) {
classroom.push(obj);
let currentClassroomObj = null;
if( !hashSet.has(hash) ) {
hashSet.add(hash);
result.push(obj);
currentClassroomObj = obj;
} else { // Se a hash já existe, já temos a cidade nos resultados. Como está ordenado, é o último valor nos resultados
currentClassroomObj = result[result.length - 1];
}
});
let result = [];
// Para cada resultado
classroom.forEach((c) => {
let r = c;
// Para cada localização
c.locations.forEach((location, index) => {
function filterEnrollment(e) {
return (e.city_id == c.city_id && e.year == c.year && e.location_id == location.location_id);
// Inserimos a localidade no array de locations da sala
let location = {
location_id: classroom.location_id,
location_name: classroom.location_name,
total_classroom: parseInt(classroom.total, 10),
total_classroom_be_built: 0,
education_level: []
};
currentClassroomObj.locations.push(location);
// Partimos para as etapas de ensino/anos escolares
let enrollmentMatch = true;
j = 0;
let educationLevelSet = new Set();
while(enrollmentMatch && j < req.enrollment.length) {
let enrollment = req.enrollment[j];
if(typeof enrollment === 'undefined') {
enrollmentMatch = false;
continue;
}
if(enrollment.city_id != classroom.city_id) { // Se as cidades não são iguais, já passamos do range
enrollmentMatch = false;
continue;
}
let fEnrollments = req.enrollment.filter(filterEnrollment);
let educationLevels = [];
fEnrollments.forEach((fe) => {
let obj = {education_level_short_id: fe.education_level_short_id, education_level_short_name: fe.education_level_short_name};
if(enrollment.year != classroom.year || enrollment.location_id != classroom.location_id) { // Se ano ou localização são diferentes, passa para o próximo
++j;
continue;
}
if(educationLevels.findIndex((el) => {return el.education_level_short_id === obj.education_level_short_id}) === -1 ) {
educationLevels.push(obj);
}
});
// Remove se o período é nulo (não dá pra usar no cálculo)
if(enrollment.period_id == null) {
req.enrollment.splice(j, 1);
continue;
}
let education_level = [];
// Para cada etapa de ensino
educationLevels.forEach((eduLevel) => {
function filterEducationLevel(e) {
return (e.city_id == c.city_id && e.year == c.year && e.location_id == location.location_id && e.education_level_short_id == eduLevel.education_level_short_id);
// Temos uma matrícula com cidade, ano e localidades certos
// "Consome" a matrícula (remove do vetor de matrículas)
req.enrollment.splice(j, 1);
// Cria a etapa de ensino adequada
let enrollmentEducationLevel = req.educationSchoolYear[enrollment.school_year_id];
// Se não há um número de alunos por turna para a etapa de ensino, ignoramos a entrada
if(enrollmentEducationLevel.numberStudentClass == null) continue;
let educationLevel = null;
if(!educationLevelSet.has(enrollmentEducationLevel.id)) {
educationLevelSet.add(enrollmentEducationLevel.id);
educationLevel = {
education_level_short_id: enrollmentEducationLevel.id,
education_level_short_name: enrollmentEducationLevel.name,
enrollment: {
total_enrollment_day: 0,
total_enrollment_night: 0,
full_period_classes: 0,
day_classes: 0,
night_classes: 0,
total_classrooms_needed: 0
}
};
// location.education_level.push(educationLevel);
// Para manter a orde da etapa de ensino
if (location.education_level.length == 0) {
location.education_level.push(educationLevel);
} else {
let k = location.education_level.length - 1;
let el = location.education_level[k];
while (k >= 0) {
if(educationLevel.education_level_short_id < el.education_level_short_id) {
--k;
if(k>=0) el = location.education_level[k];
} else break;
}
k++;
location.education_level.splice(k, 0, educationLevel);
}
} else {
let k = 0;
let el = location.education_level[k];
while(k < location.education_level.length) {
if(el.education_level_short_id != enrollmentEducationLevel.id) {
++k;
if(k<location.education_level.length) el = location.education_level[k];
} else break;
}
if(k >= location.education_level.length) --k;
educationLevel = location.education_level[k];
}
let fEducationLevel = fEnrollments.filter(filterEducationLevel);
let dayEnrollments = 0;
let nightEnrollments = 0;
// Para cada matrícula na etapa de ensino
fEducationLevel.forEach((fEduLevel) => {
if(fEduLevel.period_id < 3) dayEnrollments+= fEduLevel.total;
else if(fEduLevel.period_id === 3) nightEnrollments+= fEduLevel.total;
});
let size = classSize.find((el) => {
return el.id === eduLevel.education_level_short_id;
}) || undefined;
let fullPeriodTime = integralTime.find((el) => {
return el.id === eduLevel.education_level_short_id;
}) || undefined;
if(typeof size === 'undefined' || typeof fullPeriodTime === 'undefined') return;
size = size.numberStudentClass;
fullPeriodTime = fullPeriodTime.offerGoal;
let fullPeriodClasses = Math.ceil((dayEnrollments * (fullPeriodTime / 100))/size);
let dayClasses = Math.ceil((dayEnrollments/size) - fullPeriodClasses);
let nightClasses = Math.ceil(nightEnrollments/size);
let totalClassroomsNeeded = fullPeriodClasses + dayClasses;
if(nightClasses > dayClasses) totalClassroomsNeeded+= (nightClasses - dayClasses);
let obj = {
total_enrollment_day : dayEnrollments,
total_enrollment_night: nightEnrollments,
full_period_classes: fullPeriodClasses,
day_classes: dayClasses,
night_classes: nightClasses,
total_classrooms_needed: totalClassroomsNeeded
};
// Soma os totais de matrícula da etapa de ensino
educationLevel.enrollment.total_enrollment_day += (enrollment.period_id < 3 && enrollment.period_id != null) ? enrollment.total : 0;
educationLevel.enrollment.total_enrollment_night += (enrollment.period_id == 3) ? enrollment.total : 0;
let educationLevelIndex = education_level.findIndex((el) => {return el.education_level_short_id === eduLevel.education_level_short_id});
// Calcula o número de turmas parcial
// Turmas de período integral
educationLevel.enrollment.full_period_classes = Math.ceil((educationLevel.enrollment.total_enrollment_day * (enrollmentEducationLevel.offerGoal/100)) / enrollmentEducationLevel.numberStudentClass);
if(educationLevelIndex === -1) {
educationLevelIndex = education_level.length;
education_level.push(eduLevel);
}
// Turmas diurnas
educationLevel.enrollment.day_classes = Math.ceil((educationLevel.enrollment.total_enrollment_day / enrollmentEducationLevel.numberStudentClass) - educationLevel.enrollment.full_period_classes);
education_level[educationLevelIndex].enrollment = obj;
// education_level[educationLevelIndex].enrollments = fEducationLevel;
});
// Turmas noturnas
educationLevel.enrollment.night_classes = Math.ceil((educationLevel.enrollment.total_enrollment_night / enrollmentEducationLevel.numberStudentClass));
r.locations[index].education_level = education_level;
});
// Total de salas
educationLevel.enrollment.total_classrooms_needed = (educationLevel.enrollment.full_period_classes + educationLevel.enrollment.day_classes);
if(educationLevel.enrollment.night_classes > educationLevel.enrollment.day_classes) educationLevel.enrollment.total_classrooms_needed += (educationLevel.enrollment.night_classes - educationLevel.enrollment.day_classes);
}
// Calculamos o total classroom be built para o município usando reduce
location.total_classroom_be_built = location.education_level.reduce((total, atual) => {
return total + atual.enrollment.total_classrooms_needed;
}, 0) - location.total_classroom;
if(location.total_classroom_be_built < 0) location.total_classroom_be_built = 0;
++i;
}
// TODO: agregar por estado e brasil
if(req.query['state']) {
console.log('ESTADO!!!!');
} else if(!req.query['city']) {
console.log('BRASIL!!!');
}
result.push(r);
});
console.log('FEITO');
req.result = result;
next();
}, response('classroom_count'));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment