// Path: gtfs-validation-lib/src/main/java/com/conveyal/gtfs/model/Statistic.java
// public class Statistic {
// 	private String agencyId;
// 	private Integer routeCount;
// 	private Integer tripCount;
// 	private Integer stopCount;
// 	private Integer stopTimeCount;
// 	private Date calendarServiceStart;
// 	private Date calendarServiceEnd;
// 	private Date calendarStartDate;
// 	private Date calendarEndDate;
// 	private Rectangle2D bounds;
// 		
// 	public String getAgencyId() {
// 		return agencyId;
// 	}
// 	public void setAgencyId(String agencyId) {
// 		this.agencyId = agencyId;
// 	}
// 	public Integer getRouteCount() {
// 		return routeCount;
// 	}
// 	public void setRouteCount(Integer routeCount) {
// 		this.routeCount = routeCount;
// 	}
// 	public Integer getTripCount() {
// 		return tripCount;
// 	}
// 	public void setTripCount(Integer tripCount) {
// 		this.tripCount = tripCount;
// 	}
// 	public Integer getStopCount() {
// 		return stopCount;
// 	}
// 	public void setStopCount(Integer stopCount) {
// 		this.stopCount = stopCount;
// 	}
// 	public Integer getStopTimeCount() {
// 		return stopTimeCount;
// 	}
// 	public void setStopTimeCount(Integer stopTimeCount) {
// 		this.stopTimeCount = stopTimeCount;
// 	}
// 	public Date getCalendarStartDate() {
// 		return calendarStartDate;
// 	}
// 	public void setCalendarStartDate(Date calendarStartDate) {
// 		this.calendarStartDate = calendarStartDate;
// 	}
// 	public Date getCalendarEndDate() {
// 		return calendarEndDate;
// 	}
// 	public void setCalendarEndDate(Date calendarEndDate) {
// 		this.calendarEndDate = calendarEndDate;
// 	}
// 	public Date getCalendarServiceStart() {
// 		return calendarServiceStart;
// 	}
// 	public void setCalendarServiceStart(Date calendarServiceStart) {
// 		this.calendarServiceStart = calendarServiceStart;
// 	}
// 	public Date getCalendarServiceEnd() {
// 		return calendarServiceEnd;
// 	}
// 	public void setCalendarServiceEnd(Date calendarServiceEnd) {
// 		this.calendarServiceEnd = calendarServiceEnd;
// 	}
//         public Rectangle2D getBounds() {
//             return bounds;
//         }
//         public void setBounds(Rectangle2D bounds) {
//             this.bounds = bounds;
//         }	
// }
// 
// Path: gtfs-validation-lib/src/main/java/com/conveyal/gtfs/service/StatisticsService.java
// public interface StatisticsService {
// 
// 	Integer getAgencyCount();
// 
// 	Integer getRouteCount();
// 
// 	Integer getTripCount();
// 
// 	Integer getStopCount();
// 
// 	Integer getStopTimesCount();
// 	/*
// 	 * As Calendar Dates are optional per the GTFS spec, this returns an Optional<Date>.
// 	 * To retrieve a Date Object from this use the method, getCalendarDateStart().get()
// 	 */
// 	Optional<Date> getCalendarDateStart();
// 	
// 	Optional<Date> getCalendarDateEnd();
// 
// 	Date getCalendarServiceRangeStart();
// 
// 	Date getCalendarServiceRangeEnd();
// 	
// 	Integer getNumberOfDays();
// 
// 	Integer getRouteCount(String agencyId);
// 
// 	Integer getTripCount(String agencyId);
// 
// 	Integer getStopCount(String agencyId);
// 
// 	Integer getStopTimesCount(String agencyId);
// 
// 	Date getCalendarDateStart(String agencyId);
// 		
// 	Date getCalendarDateEnd(String agencyId);
// 	
// 	Date getCalendarServiceRangeStart(String agencyId);
// 
// 	Date getCalendarServiceRangeEnd(String agencyId);
// 	
// 	Rectangle2D getBounds ();
// 
// 	Statistic getStatistic(String agencyId);
// }


import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.time.Duration;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Date;
import java.util.Optional;
import java.util.TimeZone;
import org.onebusaway.gtfs.impl.GtfsRelationalDaoImpl;
import org.onebusaway.gtfs.impl.calendar.CalendarServiceDataFactoryImpl;
import org.onebusaway.gtfs.model.Agency;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.Route;
import org.onebusaway.gtfs.model.ServiceCalendar;
import org.onebusaway.gtfs.model.ServiceCalendarDate;
import org.onebusaway.gtfs.model.Stop;
import org.onebusaway.gtfs.model.StopTime;
import org.onebusaway.gtfs.model.Trip;
import org.onebusaway.gtfs.services.calendar.CalendarService;
import com.conveyal.gtfs.model.Statistic;
import com.conveyal.gtfs.service.StatisticsService;
			if (agencyId.equals(serviceCalendarDate.getServiceId().getAgencyId())) {
				if (endDate == null
						|| serviceCalendarDate.getDate().getAsDate().after(endDate))
					endDate = serviceCalendarDate.getDate().getAsDate();
			}
		}

		return endDate;
	}
  
  /**
   * Get the bounding box of this GTFS feed.
   * We use a Rectangle2D rather than a Geotools envelope because GTFS is always in WGS 84.
   * Note that stops do not have agencies in GTFS.
   */
  public Rectangle2D getBounds () {
      Rectangle2D ret = null;
      
      for (Stop stop : gtfsDao.getAllStops()) {
          if (ret == null) {
              ret = new Rectangle2D.Double(stop.getLon(), stop.getLat(), 0, 0);
          }
          else {
              ret.add(new Point2D.Double(stop.getLon(), stop.getLat()));
          }
      }
  
      return ret;
  }

// Path: gtfs-validation-lib/src/main/java/com/conveyal/gtfs/model/Statistic.java
// public class Statistic {
// 	private String agencyId;
// 	private Integer routeCount;
// 	private Integer tripCount;
// 	private Integer stopCount;
// 	private Integer stopTimeCount;
// 	private Date calendarServiceStart;
// 	private Date calendarServiceEnd;
// 	private Date calendarStartDate;
// 	private Date calendarEndDate;
// 	private Rectangle2D bounds;
// 		
// 	public String getAgencyId() {
// 		return agencyId;
// 	}
// 	public void setAgencyId(String agencyId) {
// 		this.agencyId = agencyId;
// 	}
// 	public Integer getRouteCount() {
// 		return routeCount;
// 	}
// 	public void setRouteCount(Integer routeCount) {
// 		this.routeCount = routeCount;
// 	}
// 	public Integer getTripCount() {
// 		return tripCount;
// 	}
// 	public void setTripCount(Integer tripCount) {
// 		this.tripCount = tripCount;
// 	}
// 	public Integer getStopCount() {
// 		return stopCount;
// 	}
// 	public void setStopCount(Integer stopCount) {
// 		this.stopCount = stopCount;
// 	}
// 	public Integer getStopTimeCount() {
// 		return stopTimeCount;
// 	}
// 	public void setStopTimeCount(Integer stopTimeCount) {
// 		this.stopTimeCount = stopTimeCount;
// 	}
// 	public Date getCalendarStartDate() {
// 		return calendarStartDate;
// 	}
// 	public void setCalendarStartDate(Date calendarStartDate) {
// 		this.calendarStartDate = calendarStartDate;
// 	}
// 	public Date getCalendarEndDate() {
// 		return calendarEndDate;
// 	}
// 	public void setCalendarEndDate(Date calendarEndDate) {
// 		this.calendarEndDate = calendarEndDate;
// 	}
// 	public Date getCalendarServiceStart() {
// 		return calendarServiceStart;
// 	}
// 	public void setCalendarServiceStart(Date calendarServiceStart) {
// 		this.calendarServiceStart = calendarServiceStart;
// 	}
// 	public Date getCalendarServiceEnd() {
// 		return calendarServiceEnd;
// 	}
// 	public void setCalendarServiceEnd(Date calendarServiceEnd) {
// 		this.calendarServiceEnd = calendarServiceEnd;
// 	}
//         public Rectangle2D getBounds() {
//             return bounds;
//         }
//         public void setBounds(Rectangle2D bounds) {
//             this.bounds = bounds;
//         }	
// }
// 
// Path: gtfs-validation-lib/src/main/java/com/conveyal/gtfs/service/StatisticsService.java
// public interface StatisticsService {
// 
// 	Integer getAgencyCount();
// 
// 	Integer getRouteCount();
// 
// 	Integer getTripCount();
// 
// 	Integer getStopCount();
// 
// 	Integer getStopTimesCount();
// 	/*
// 	 * As Calendar Dates are optional per the GTFS spec, this returns an Optional<Date>.
// 	 * To retrieve a Date Object from this use the method, getCalendarDateStart().get()
// 	 */
// 	Optional<Date> getCalendarDateStart();
// 	
// 	Optional<Date> getCalendarDateEnd();
// 
// 	Date getCalendarServiceRangeStart();
// 
// 	Date getCalendarServiceRangeEnd();
// 	
// 	Integer getNumberOfDays();
// 
// 	Integer getRouteCount(String agencyId);
// 
// 	Integer getTripCount(String agencyId);
// 
// 	Integer getStopCount(String agencyId);
// 
// 	Integer getStopTimesCount(String agencyId);
// 
// 	Date getCalendarDateStart(String agencyId);
// 		
// 	Date getCalendarDateEnd(String agencyId);
// 	
// 	Date getCalendarServiceRangeStart(String agencyId);
// 
// 	Date getCalendarServiceRangeEnd(String agencyId);
// 	
// 	Rectangle2D getBounds ();
// 
// 	Statistic getStatistic(String agencyId);
// }


// Path: gtfs-validation-lib/src/main/java/com/conveyal/gtfs/service/impl/GtfsStatisticsService.java
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.time.Duration;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Date;
import java.util.Optional;
import java.util.TimeZone;
import org.onebusaway.gtfs.impl.GtfsRelationalDaoImpl;
import org.onebusaway.gtfs.impl.calendar.CalendarServiceDataFactoryImpl;
import org.onebusaway.gtfs.model.Agency;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.Route;
import org.onebusaway.gtfs.model.ServiceCalendar;
import org.onebusaway.gtfs.model.ServiceCalendarDate;
import org.onebusaway.gtfs.model.Stop;
import org.onebusaway.gtfs.model.StopTime;
import org.onebusaway.gtfs.model.Trip;
import org.onebusaway.gtfs.services.calendar.CalendarService;
import com.conveyal.gtfs.model.Statistic;
import com.conveyal.gtfs.service.StatisticsService;

			if (agencyId.equals(serviceCalendarDate.getServiceId().getAgencyId())) {
				if (endDate == null
						|| serviceCalendarDate.getDate().getAsDate().after(endDate))
					endDate = serviceCalendarDate.getDate().getAsDate();
			}
		}

		return endDate;
	}
  
  /**
   * Get the bounding box of this GTFS feed.
   * We use a Rectangle2D rather than a Geotools envelope because GTFS is always in WGS 84.
   * Note that stops do not have agencies in GTFS.
   */
  public Rectangle2D getBounds () {
      Rectangle2D ret = null;
      
      for (Stop stop : gtfsDao.getAllStops()) {
          if (ret == null) {
              ret = new Rectangle2D.Double(stop.getLon(), stop.getLat(), 0, 0);
          }
          else {
              ret.add(new Point2D.Double(stop.getLon(), stop.getLat()));
          }
      }
  
      return ret;
  }

	public Statistic getStatistic(String agencyId) {