/** * Copyright © 2002 Instituto Superior Técnico * * This file is part of FenixEdu Academic. * * FenixEdu Academic is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FenixEdu Academic is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>. */ package org.fenixedu.academic.service.services.administrativeOffice.enrolment; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.fenixedu.academic.domain.ExecutionSemester; import org.fenixedu.academic.domain.log.CurriculumLineLog; import org.fenixedu.academic.domain.log.EnrolmentLog; import org.fenixedu.academic.domain.student.Registration; import org.fenixedu.academic.util.EnrolmentAction; import org.joda.time.DateTime; import org.joda.time.Interval; import com.google.gson.JsonArray; import com.google.gson.JsonObject; public class MultiSemesterEnrolmentReporter { private final int hoursToReport; private final int semesterToReport; public MultiSemesterEnrolmentReporter(final int hoursToReportFromStart, final int semesterToReport) { this.hoursToReport = hoursToReportFromStart; this.semesterToReport = semesterToReport; } public void report(final int year, final int month, final int day, final int hour) { final DateTime enrolmentStartTime = new DateTime(year, month, day, hour, 0, 0, 0); final ExecutionSemester semester = ExecutionSemester.readByDateTime(enrolmentStartTime); final DateTime endTimeToReport = enrolmentStartTime.plusHours(hoursToReport); if (semester.getSemester().intValue() == semesterToReport) { semester.getCurriculumLineLogsSet().stream() .filter(l -> l instanceof EnrolmentLog) .filter(l -> !l.getDateDateTime().isBefore(enrolmentStartTime) && !l.getDateDateTime().isAfter(endTimeToReport)) .sorted((l1, l2) -> l1.getDateDateTime().compareTo(l2.getDateDateTime())) .forEach(l -> process(semester, enrolmentStartTime, l)); semester.getAssociatedExecutionCoursesSet().stream() .flatMap(ec -> ec.getCourseLoadsSet().stream()) .flatMap(cl -> cl.getShiftsSet().stream()) .flatMap(s -> s.getShiftEnrolmentsSet().stream()) .map(se -> se.getCreatedOn()) .filter(dt -> !dt.isBefore(enrolmentStartTime) && !dt.isAfter(endTimeToReport)) .map(dt -> new Interval(enrolmentStartTime, dt).toDuration().getStandardSeconds()) .forEach(seconds -> add(semester, seconds, new int[] { 0, 0, 1 })); } } public JsonArray getStats() { return getStats("registrations", "enrolments", "shifts"); } private final Map<ExecutionSemester, Set<Registration>> registrationsBySemester = new HashMap<>(); private SortedMap<ExecutionSemester, SortedMap<Long, int[]>> stats = new TreeMap<>(); protected void process(final ExecutionSemester semester, final DateTime enrolmentStartTime, final CurriculumLineLog log) { final Long seconds = new Interval(enrolmentStartTime, log.getDateDateTime()).toDuration().getStandardSeconds(); int regCount = countRegistration(semester, log.getStudent()) ? 1 : 0; int enrolCount = log.getAction().equals(EnrolmentAction.ENROL) ? 1 : -1; add(semester, seconds, new int[] { regCount, enrolCount, 0 }); } private boolean countRegistration(final ExecutionSemester semester, final Registration registration) { final Set<Registration> registrations = getRegistrations(semester); if (registrations.contains(registration)) { return false; } registrations.add(registration); return true; } private Set<Registration> getRegistrations(final ExecutionSemester semester) { if (!registrationsBySemester.containsKey(semester)) { registrationsBySemester.put(semester, new HashSet<Registration>()); } return registrationsBySemester.get(semester); } public void add(final ExecutionSemester semester, final Long seconds, final int[] counts) { final SortedMap<Long, int[]> values = get(stats, semester); if (!values.containsKey(seconds)) { values.put(seconds, new int[counts.length]); } int[] ia = values.get(seconds); for (int i = 0; i < counts.length; ia[i] += counts[i++]); } private static SortedMap<Long, int[]> get(final SortedMap<ExecutionSemester, SortedMap<Long, int[]>> map, final ExecutionSemester semester) { if (!map.containsKey(semester)) { map.put(semester, new TreeMap<Long, int[]>()); } return map.get(semester); } private JsonArray getStats(String... labels) { final JsonArray result = new JsonArray(); for (final Entry<ExecutionSemester, SortedMap<Long, int[]>> e : stats.entrySet()) { final String semester = e.getKey().getQualifiedName(); int[] accumulatedValues = new int[labels.length]; for (final Entry<Long, int[]> v : e.getValue().entrySet()) { final Long second = v.getKey(); final int[] values = v.getValue(); final JsonObject obj = new JsonObject(); obj.addProperty("label", semester); obj.addProperty("second", second); for (int i = 0; i < labels.length; i++) { int a = accumulatedValues[i] += values[i]; obj.addProperty(labels[i], a); } result.add(obj); } } return result; } }