/* * Copyright 2011, Nabil Benothman, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This 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 2.1 of * the License, or (at your option) any later version. * * This software 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 this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.ubike.util; import com.ubike.model.Statistic; import com.ubike.model.Trip; import com.ubike.model.UbikeGroup; import com.ubike.model.UserStatistic; import com.ubike.services.StatisticServiceLocal; import com.ubike.services.TripManagerLocal; import com.ubike.services.TripServiceLocal; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Date; import java.util.EnumMap; import java.util.Map; import sun.reflect.generics.reflectiveObjects.NotImplementedException; /** * * @author Benothman */ public class StatisticManager { private TripManagerLocal tml; private TripServiceLocal tripService; private StatisticServiceLocal statisticService; /** * * @param tml an instance of a <code>TripManagerLocal</code> */ public StatisticManager(TripManagerLocal tml) { this.tml = tml; } /** * Update the statistics of the given <code>UbikeEntity</code> with the given * trip data. * * @param entity * @param trip */ public synchronized void updateEntityStatistics(UbikeEntity entity, Trip trip) { System.out.println("StatisticManager -> entity : " + entity.toString()); updateStatistics(getDailyStat(entity, trip.getStartDate()), trip); updateStatistics(getWeeklyStat(entity, trip.getStartDate()), trip); updateStatistics(getMonthlyStat(entity, trip.getStartDate()), trip); updateStatistics(getYearlyStat(entity, trip.getStartDate()), trip); updateStatistics(getGeneralStat(entity), trip); } /** * * @param group * @param trip */ public synchronized void updateGroupRanking(UbikeGroup group, Trip trip) { throw new NotImplementedException(); } /** * Update the given statistics with the given trip data. * * @param stats a collection of statistic * @param trip an instance of a trip. */ public void updateStatistics(List<Statistic> stats, Trip trip) { double avg; for (Statistic o : stats) { switch (o.getMetric()) { case DISTANCE: { o.setMaxValue(Math.max(o.getMaxValue(), trip.getDistance())); o.setMinValue(o.isValid() ? Math.min(o.getMinValue(), trip.getDistance()) : trip.getDistance()); avg = o.getAvgValue() * o.getCount() + trip.getDistance(); avg /= (o.getCount() + 1); o.setAvgValue(getDoubleValue(avg)); o.setTotalValue(trip.getDistance() + o.getTotalValue()); break; } case DURATION: { o.setMaxValue(Math.max(o.getMaxValue(), trip.getDuration())); o.setMinValue(o.isValid() ? Math.min(o.getMinValue(), trip.getDuration()) : trip.getDuration()); avg = o.getAvgValue() * o.getCount() + trip.getDuration(); avg /= (o.getCount() + 1); o.setAvgValue(getDoubleValue(avg)); o.setTotalValue(trip.getDuration() + o.getTotalValue()); break; } case SPEED: { o.setMaxValue(Math.max(o.getMaxValue(), trip.getMaxSpeed())); o.setMinValue(o.isValid() ? Math.min(o.getMinValue(), trip.getAvgSpeed()) : trip.getAvgSpeed()); avg = o.getAvgValue() * o.getCount() + trip.getAvgSpeed(); avg /= (o.getCount() + 1); o.setAvgValue(getDoubleValue(avg)); break; } default: break; } o.setValid(true); o.setCount(o.getCount() + 1); statisticService.update(o); getTml().updateEntity(o); } } /** * * @param entity The owner of the statistics * @param date A date of statistics * @return a collection of an entity statistics for the given date */ public List<Statistic> getDailyStat(UbikeEntity entity, Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); Date start = cal.getTime(); cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 59); cal.set(Calendar.SECOND, 59); Date end = cal.getTime(); List<Statistic> collection = getTml().getEntityStatByIntervalAndType(entity.getId(), StatisticType.DAILY, start, end); // We have to be sure that the collection contains all statistic metrics Map<Metric, Statistic> stats = new EnumMap<Metric, Statistic>(Metric.class); for (Statistic o : collection) { stats.put(o.getMetric(), o); } boolean hasChanged = false; for (Metric m : Metric.values()) { if (stats.get(m) == null) { hasChanged = true; Statistic s = new UserStatistic(); s.setMetric(m); s.setType(StatisticType.DAILY); s.setStartDate(start); s.setEndDate(end); entity.getStatistics().add(s); stats.put(m, s); } } if (hasChanged) { this.getTml().updateEntity(entity); } return new ArrayList<Statistic>(stats.values()); } /** * * @param user * @return */ public List<Statistic> getWeeklyStat(UbikeEntity entity, Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.setFirstDayOfWeek(Calendar.MONDAY); cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); Date start = cal.getTime(); cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); Date end = cal.getTime(); cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); List<Statistic> collection = getTml().getEntityStatByIntervalAndType(entity.getId(), StatisticType.WEEKLY, start, end); // We have to be sure that the collection contains all statistic metrics Map<Metric, Statistic> stats = new EnumMap<Metric, Statistic>(Metric.class); for (Statistic o : collection) { stats.put(o.getMetric(), o); } boolean hasChanged = false; for (Metric m : Metric.values()) { if (stats.get(m) == null) { hasChanged = true; Statistic s = new UserStatistic(); s.setMetric(m); s.setType(StatisticType.WEEKLY); s.setStartDate(start); s.setEndDate(end); entity.getStatistics().add(s); stats.put(m, s); } } if (hasChanged) { this.getTml().updateEntity(entity); } return new ArrayList<Statistic>(stats.values()); } /** * * @param user * @return */ public List<Statistic> getMonthlyStat(UbikeEntity entity, Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.set(Calendar.DAY_OF_MONTH, 1); Date start = cal.getTime(); int month = cal.get(Calendar.MONTH); if (month == Calendar.FEBRUARY) { cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.YEAR) % 4 == 0 ? 29 : 28); } else if (month == Calendar.APRIL || month == Calendar.JUNE || month == Calendar.SEPTEMBER || month == Calendar.NOVEMBER) { cal.set(Calendar.DAY_OF_MONTH, 30); } else { cal.set(Calendar.DAY_OF_MONTH, 31); } Date end = cal.getTime(); // Getting statistics of the current month. List<Statistic> collection = getTml().getEntityStatByIntervalAndType(entity.getId(), StatisticType.MONTHLY, start, end); // We have to be sure that the collection contains all statistic metrics Map<Metric, Statistic> stats = new EnumMap<Metric, Statistic>(Metric.class); for (Statistic o : collection) { stats.put(o.getMetric(), o); } boolean hasChanged = false; for (Metric m : Metric.values()) { if (stats.get(m) == null) { hasChanged = true; Statistic s = new UserStatistic(); s.setMetric(m); s.setType(StatisticType.MONTHLY); s.setStartDate(start); s.setEndDate(end); entity.getStatistics().add(s); stats.put(m, s); } } if (hasChanged) { this.getTml().updateEntity(entity); } return new ArrayList<Statistic>(stats.values()); } /** * * @param user * @return */ public List<Statistic> getYearlyStat(UbikeEntity entity, Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); // configure to 01/01/yyyy 00:00:00 cal.set(cal.get(Calendar.YEAR), Calendar.JANUARY, 1); Date start = cal.getTime(); cal.set(cal.get(Calendar.YEAR), Calendar.DECEMBER, 31); Date end = cal.getTime(); List<Statistic> collection = getTml().getEntityStatByIntervalAndType(entity.getId(), StatisticType.YEARLY, start, end); // We have to be sure that the collection contains all statistic metrics Map<Metric, Statistic> stats = new EnumMap<Metric, Statistic>(Metric.class); for (Statistic o : collection) { stats.put(o.getMetric(), o); } boolean hasChanged = false; for (Metric m : Metric.values()) { if (stats.get(m) == null) { Statistic s = new UserStatistic(); s.setMetric(m); s.setType(StatisticType.YEARLY); s.setStartDate(start); s.setEndDate(end); entity.getStatistics().add(s); stats.put(m, s); } } if (hasChanged) { this.getTml().updateEntity(entity); } return new ArrayList<Statistic>(stats.values()); } /** * * @param user * @return */ public List<Statistic> getGeneralStat(UbikeEntity entity) { Calendar cal = Calendar.getInstance(); // configure to 01/01/yyyy 00:00:00 cal.set(cal.get(Calendar.YEAR), Calendar.JANUARY, 1); Date start = cal.getTime(); cal.set(2020, Calendar.DECEMBER, 31); Date end = cal.getTime(); List<Statistic> collection = getTml().getEntityStatByType(entity.getId(), StatisticType.GENERAL); Map<Metric, Statistic> stats = new EnumMap<Metric, Statistic>(Metric.class); for (Statistic o : collection) { stats.put(o.getMetric(), o); } boolean hasChanged = false; for (Metric m : Metric.values()) { if (stats.get(m) == null) { hasChanged = true; Statistic s = new UserStatistic(); s.setMetric(m); s.setType(StatisticType.GENERAL); s.setStartDate(start); s.setEndDate(end); entity.getStatistics().add(s); stats.put(m, s); } } if (hasChanged) { this.getTml().updateEntity(entity); } return new ArrayList<Statistic>(stats.values()); } /** * * @param value * @return */ private double getDoubleValue(double value) { String tmpTab[] = ("" + value).split("\\."); if (tmpTab[1].length() > 3) { tmpTab[1] = tmpTab[1].substring(0, 3); value = Double.parseDouble(tmpTab[0] + "." + tmpTab[1]); } return value; } /** * @return the tml */ public TripManagerLocal getTml() { return tml; } /** * @param tml the tml to set */ public void setTml(TripManagerLocal tml) { this.tml = tml; } /** * @return the tripService */ public TripServiceLocal getTripService() { return tripService; } /** * @param tripService the tripService to set */ public void setTripService(TripServiceLocal tripService) { this.tripService = tripService; } /** * @return the statisticService */ public StatisticServiceLocal getStatisticService() { return statisticService; } /** * @param statisticService the statisticService to set */ public void setStatisticService(StatisticServiceLocal statisticService) { this.statisticService = statisticService; } }