protected JFreeChart constructChart(Iteration iteration, Integer timeZoneOffset) {
    // get server timezone
    Calendar cal = Calendar.getInstance();
    TimeZone localTimeZone = cal.getTimeZone();

    // server timezone offset in minutes
    int rawOffset = localTimeZone.getRawOffset() / 60000;

    // get offset difference in minutes
    timeDifferenceMinutes = rawOffset - timeZoneOffset.intValue();

    JFreeChart burndown =
        ChartFactory.createTimeSeriesChart(
            "'" + iteration.getName() + "' burndown",
            DATE_AXIS_LABEL,
            EFFORT_AXIS_LABEL,
            getDataset(iteration),
            true,
            true,
            false);

    formatChartAxes(
        burndown,
        new DateTime(iteration.getStartDate().minusMinutes(timeDifferenceMinutes)),
        new DateTime(iteration.getEndDate()).minusMinutes(timeDifferenceMinutes));

    formatChartStyle(burndown);

    return burndown;
  }
 public void calculateProjectMetrics(Product product) {
   if (product != null && product.getProjects() != null && product.getProjects().size() > 0) {
     // ProjectData projectDataMap
     for (Project p : product.getProjects()) {
       ProjectMetrics metrics = new ProjectMetrics();
       metrics.setAssignees(backlogBusiness.getNumberOfAssignedUsers(p));
       if (p.getIterations() != null) {
         metrics.setNumberOfAllIterations(p.getIterations().size());
         int ongoingIters = 0;
         Date current = Calendar.getInstance().getTime();
         for (Iteration iter : p.getIterations()) {
           if (iter.getStartDate().getTime() < current.getTime()
               && iter.getEndDate().getTime() > current.getTime()) {
             ongoingIters++;
           }
         }
         metrics.setNumberOfOngoingIterations(ongoingIters);
       } else {
         metrics.setNumberOfAllIterations(0);
         metrics.setNumberOfOngoingIterations(0);
       }
       p.setMetrics(metrics);
     }
   }
 }
  /** Assembles all the needed <code>TimeSeries</code>. */
  protected TimeSeriesCollection getDataset(Iteration iteration) {
    TimeSeriesCollection chartDataset = new TimeSeriesCollection();

    List<IterationHistoryEntry> iterationEntries =
        iterationHistoryEntryBusiness.getHistoryEntriesForIteration(iteration);

    LocalDate yesterday = new LocalDate().minusDays(1);
    LocalDate today = new LocalDate();
    IterationHistoryEntry yesterdayEntry = getHistoryEntryForDate(iterationEntries, yesterday);
    IterationHistoryEntry todayEntry = getHistoryEntryForDate(iterationEntries, today);
    DateTime iterationStartDate = new DateTime(iteration.getStartDate());
    DateTime iterationEndDate = new DateTime(iteration.getEndDate());

    chartDataset.addSeries(
        getBurndownTimeSeries(
            iterationEntries,
            new LocalDate(iteration.getStartDate()),
            determineEndDate(new LocalDate(iteration.getEndDate()))));

    chartDataset.addSeries(getCurrentDayTimeSeries(yesterdayEntry, todayEntry));

    chartDataset.addSeries(
        getScopingTimeSeries(
            iterationEntries, iterationStartDate.toLocalDate(), iterationEndDate.toLocalDate()));

    chartDataset.addSeries(
        getReferenceVelocityTimeSeries(
            iterationStartDate,
            iterationEndDate,
            new ExactEstimate(todayEntry.getOriginalEstimateSum())));

    TimeSeries predictedVelocity =
        getPredictedVelocityTimeSeries(
            iterationStartDate.toLocalDate(),
            iterationEndDate.toLocalDate(),
            yesterdayEntry,
            todayEntry);
    if (predictedVelocity != null) {
      chartDataset.addSeries(predictedVelocity);
    }

    return chartDataset;
  }
  public List<Backlog> getProjectsAndIterationsInTimeFrame(
      List<Backlog> backlogs, Date startDate, Date endDate) {
    List<Backlog> list = new ArrayList<Backlog>(0);

    for (Backlog blog : backlogs) {
      Project pro = null;
      Iteration it = null;

      // Backlog is Project
      if (blog.getClass().equals(Project.class)) {
        pro = (Project) blog;
        if ((pro.getEndDate().after(startDate) && pro.getEndDate().before(endDate))
            || (pro.getStartDate().after(startDate) && pro.getStartDate().before(endDate))
            || (pro.getStartDate().before(startDate) && pro.getEndDate().after(endDate))
            || (pro.getStartDate().compareTo(startDate) == 0)
            || (pro.getEndDate().compareTo(endDate) == 0)) {
          list.add(blog);
          log.debug("IN timeframe, project");
        } else {
          log.debug("NOT in timeframe");
        }
      }

      // Backlog is Iteration
      if (blog.getClass().equals(Iteration.class)) {
        it = (Iteration) blog;
        if ((it.getEndDate().after(startDate) && it.getEndDate().before(endDate))
            || (it.getStartDate().after(startDate) && it.getStartDate().before(endDate))
            || (it.getStartDate().before(startDate) && it.getEndDate().after(endDate))
            || (it.getStartDate().compareTo(startDate) == 0)
            || (it.getEndDate().compareTo(endDate) == 0)) {
          list.add(blog);
          log.debug("IN timeframe, iteration");
        } else {
          log.debug("NOT in timeframe");
        }
      }
    }
    return list;
  }
  public HashMap<Integer, String> calculateEffortLefts(
      Date from, int weeksAhead, Map<Backlog, List<BacklogItem>> items) {
    GregorianCalendar cal = new GregorianCalendar();
    CalendarUtils cUtils = new CalendarUtils();
    HashMap<Integer, String> effortLefts = new HashMap<Integer, String>();

    Date start = from;
    Date end = cUtils.nextMonday(start);
    cal.setTime(start);
    Integer week = cal.get(GregorianCalendar.WEEK_OF_YEAR);
    for (int i = 1; i <= weeksAhead; i++) {
      // 1. Get Backlogs that hit for the week
      log.debug("Projects searched from :" + start);
      log.debug("Projects searched ending :" + end);
      cal.setTime(start);
      week = cal.get(GregorianCalendar.WEEK_OF_YEAR);
      log.debug("Calculating sums for week" + week);

      // 2. Get projects that hit current week
      List<Backlog> list =
          this.getProjectsAndIterationsInTimeFrame(
              new ArrayList<Backlog>(items.keySet()), start, end);
      log.debug(list.size() + " projects found for given time frame");

      // 3. Calculate effort sum from items in those projects
      AFTime total = new AFTime(0);
      for (Backlog blog : list) {
        Project pro = null;
        Iteration it = null;
        if (blog.getClass().equals(Project.class)) {
          pro = (Project) blog;
          List<BacklogItem> blis = items.get((Backlog) pro);
          if (blis != null) {
            // Dividing for weeks that project hits
            AFTime sum =
                this.backlogBusiness.getEffortLeftResponsibleDividedSum(blis).getEffortHours();
            int projectLength = CalendarUtils.getLengthInDays(pro.getStartDate(), pro.getEndDate());
            log.debug("Week Project length: " + projectLength + " days");
            int weekEndDaysInProject = cUtils.getWeekEndDays(pro.getStartDate(), pro.getEndDate());
            log.debug("Excluding " + weekEndDaysInProject + " days from project as week end days");
            projectLength = projectLength - weekEndDaysInProject;
            if (projectLength == 0) { // TODO Find better way to
              // prevent null divination
              // if project on weekend
              projectLength = 1;
            }
            List<Date> dates =
                cUtils.getProjectDaysList(
                    pro.getStartDate(),
                    pro.getEndDate(),
                    start,
                    new Date(end.getTime() - 86400000L),
                    false);
            int projectDaysOnWeek = 0;
            if (dates != null) {
              projectDaysOnWeek = dates.size();
            }
            log.debug("Week Project length (modified): " + projectLength + " days");
            log.debug("Week Project days:" + projectDaysOnWeek);
            log.debug(
                "Week Project effort per day: " + new AFTime(sum.getTime() / (long) projectLength));
            sum = new AFTime((sum.getTime() / (long) projectLength) * projectDaysOnWeek);
            if (sum != null) {
              total.add(sum);
              log.debug("Week effort sum: " + sum);
            }
          }
        }
        if (blog.getClass().equals(Iteration.class)) {
          it = (Iteration) blog;
          List<BacklogItem> blis = items.get((Backlog) it);
          if (blis != null) {
            // Dividing for weeks that project hits
            AFTime sum =
                this.backlogBusiness.getEffortLeftResponsibleDividedSum(blis).getEffortHours();
            int projectLength = CalendarUtils.getLengthInDays(it.getStartDate(), it.getEndDate());
            log.debug("Week Project length: " + projectLength + " days");
            int weekEndDaysInProject = cUtils.getWeekEndDays(it.getStartDate(), it.getEndDate());
            log.debug("Excluding " + weekEndDaysInProject + " days from project as week end days");
            projectLength = projectLength - weekEndDaysInProject;
            if (projectLength == 0) { // TODO Find better way to
              // prevent null division if
              // project on weekend
              projectLength = 1;
            }
            List<Date> dates =
                cUtils.getProjectDaysList(
                    it.getStartDate(),
                    it.getEndDate(),
                    start,
                    new Date(end.getTime() - 86400000L),
                    false);
            int projectDaysOnWeek = 0;
            if (dates != null) {
              projectDaysOnWeek = dates.size();
            }
            log.debug("Week Project length(modified): " + projectLength + " days");
            log.debug("Week Project days:" + projectDaysOnWeek);
            log.debug(
                "Week Project effort per day: " + new AFTime(sum.getTime() / (long) projectLength));
            sum = new AFTime((sum.getTime() / (long) projectLength) * projectDaysOnWeek);
            if (sum != null) {
              total.add(sum);
              log.debug("Week effort sum: " + sum);
            }
          }
        }
      }

      effortLefts.put(week, total.toString());
      start = cUtils.nextMonday(start);
      end = cUtils.nextMonday(start);
      cal.setTime(start);
      week = cal.get(GregorianCalendar.WEEK_OF_YEAR);
    }

    return effortLefts;
  }