/** * 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.dto; import java.util.Calendar; import java.util.Collection; import java.util.Map; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.fenixedu.academic.domain.ExecutionCourse; import org.fenixedu.academic.domain.Lesson; import org.fenixedu.academic.domain.LessonInstance; import org.fenixedu.academic.domain.Shift; import org.fenixedu.academic.domain.ShiftType; import org.fenixedu.academic.util.DiaSemana; import org.fenixedu.academic.util.HourMinuteSecond; import org.fenixedu.spaces.domain.Space; import org.joda.time.Interval; import org.joda.time.LocalDate; import org.joda.time.Weeks; import org.joda.time.YearMonthDay; public class InfoLessonInstanceAggregation extends InfoShowOccupation { private static final long serialVersionUID = 1L; private final Shift shift; private final int weekDay; private final HourMinuteSecond begin; private final HourMinuteSecond end; private final Space allocatableSpace; private final SortedSet<LocalDate> dates = new TreeSet<LocalDate>(); public InfoLessonInstanceAggregation(final Shift shift, final int weekDay, final HourMinuteSecond begin, final HourMinuteSecond end, final Space allocatableSpace) { this.shift = shift; this.weekDay = weekDay; this.begin = begin; this.end = end; this.allocatableSpace = allocatableSpace; } public InfoLessonInstanceAggregation(final Shift shift, final LessonInstance instance) { this.shift = shift; this.weekDay = instance.getBeginDateTime().getDayOfWeek(); this.begin = instance.getStartTime(); this.end = instance.getEndTime(); this.allocatableSpace = instance.getRoom(); } public InfoLessonInstanceAggregation(final Shift shift, final Lesson lesson, final YearMonthDay yearMonthDay) { this.shift = shift; this.weekDay = yearMonthDay.toDateMidnight().getDayOfWeek(); this.begin = lesson.getBeginHourMinuteSecond(); this.end = lesson.getEndHourMinuteSecond(); this.allocatableSpace = lesson.getSala(); } private void register(final YearMonthDay yearMonthDay) { dates.add(new LocalDate(yearMonthDay.getYear(), yearMonthDay.getMonthOfYear(), yearMonthDay.getDayOfMonth())); } @Override public InfoShift getInfoShift() { return new InfoShift(shift); } @Override public ShiftType getTipo() { return null; } @Override public InfoRoomOccupation getInfoRoomOccupation() { throw new Error("Not implemented."); } @Override public DiaSemana getDiaSemana() { return DiaSemana.fromJodaWeekDay(weekDay); } @Override public Calendar getInicio() { throw new Error("Not implemented."); } @Override public Calendar getFim() { throw new Error("Not implemented."); } @Override public int getLastHourOfDay() { final int hourOfDay = end.getHour(); return end.getMinuteOfHour() > 0 ? hourOfDay + 1 : hourOfDay; } @Override public int getFirstHourOfDay() { return begin.getHour(); } @Override public HourMinuteSecond getBeginHourMinuteSecond() { return begin; } @Override public HourMinuteSecond getEndHourMinuteSecond() { return end; } @Override public Space getAllocatableSpace() { return allocatableSpace; } public Shift getShift() { return shift; } public SortedSet<LocalDate> getDates() { return dates; } public SortedSet<Integer> getWeeks() { final ExecutionCourse executionCourse = shift.getExecutionCourse(); final YearMonthDay firstPossibleLessonDay = executionCourse.getMaxLessonsPeriod().getLeft(); final YearMonthDay lastPossibleLessonDay = executionCourse.getMaxLessonsPeriod().getRight(); return getWeeks(new Interval(firstPossibleLessonDay.toDateTimeAtMidnight(), lastPossibleLessonDay.toDateTimeAtMidnight() .plusDays(1))); } public SortedSet<Integer> getWeeks(final Interval lessonInterval) { final SortedSet<Integer> weeks = new TreeSet<Integer>(); final LocalDate firstPossibleLessonDay = lessonInterval.getStart().toLocalDate(); for (final LocalDate localDate : dates) { final Integer week = Weeks.weeksBetween(firstPossibleLessonDay, localDate).getWeeks() + 1; weeks.add(week); } return weeks; } public boolean availableInAllWeeks() { // TODO: if this is properly implemented it should look for gaps in the schedule. return false; } public static Collection<InfoLessonInstanceAggregation> getAggregations(final Shift shift) { final Map<String, InfoLessonInstanceAggregation> result = new TreeMap<String, InfoLessonInstanceAggregation>(); for (final Lesson lesson : shift.getAssociatedLessonsSet()) { for (final LessonInstance instance : lesson.getLessonInstancesSet()) { final String key = key(instance); if (!result.containsKey(key)) { result.put(key, new InfoLessonInstanceAggregation(shift, instance)); } final InfoLessonInstanceAggregation aggregation = result.get(key); aggregation.register(instance.getDay()); } for (final YearMonthDay yearMonthDay : lesson.getAllLessonDatesWithoutInstanceDates()) { final String key = key(lesson, yearMonthDay); if (!result.containsKey(key)) { result.put(key, new InfoLessonInstanceAggregation(shift, lesson, yearMonthDay)); } final InfoLessonInstanceAggregation aggregation = result.get(key); aggregation.register(yearMonthDay); } } return result.values(); } private static String key(final Lesson lesson, final YearMonthDay yearMonthDay) { final StringBuilder key = new StringBuilder(); key.append(yearMonthDay.toDateMidnight().getDayOfWeek()); key.append('_'); key.append(lesson.getBeginHourMinuteSecond().toString("HH:mm")); key.append('_'); key.append(lesson.getEndHourMinuteSecond().toString("HH:mm")); key.append('_'); key.append(lesson.getSala() == null ? "" : lesson.getSala().getExternalId()); return key.toString(); } private static String key(final LessonInstance instance) { final StringBuilder key = new StringBuilder(); key.append(instance.getBeginDateTime().getDayOfWeek()); key.append('_'); key.append(instance.getStartTime().toString("HH:mm")); key.append('_'); key.append(instance.getEndTime().toString("HH:mm")); key.append('_'); key.append(instance.getRoom() == null ? "" : instance.getRoom().getExternalId()); return key.toString(); } @Override public String getExternalId() { final StringBuilder sb = new StringBuilder(); sb.append(shift.getExternalId()).append(weekDay).append(begin.toString("HH:mm:ss")).append(end.toString("HH:mm:ss")); if (allocatableSpace != null) { sb.append(allocatableSpace.getExternalId()); } return sb.toString(); } public String prettyPrintWeeks() { return prettyPrintWeeks(getWeeks()); } public static String prettyPrintWeeks(SortedSet<Integer> weeks) { final StringBuilder builder = new StringBuilder(); final Integer[] weeksA = weeks.toArray(new Integer[0]); for (int i = 0; i < weeksA.length; i++) { if (i == 0) { builder.append(weeksA[i]); } else if (i == weeksA.length - 1 || (weeksA[i]) + 1 != (weeksA[i + 1])) { final String seperator = (weeksA[i - 1]) + 1 == (weeksA[i]) ? " - " : ", "; builder.append(seperator); builder.append(weeksA[i]); } else if ((weeksA[i - 1]) + 1 != weeksA[i]) { builder.append(", "); builder.append(weeksA[i]); } } return builder.toString(); } }