/* This program 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 (props, at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package org.opentripplanner.routing.core;
import java.io.Serializable;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.onebusaway.gtfs.model.calendar.ServiceDate;
import org.onebusaway.gtfs.services.calendar.CalendarService;
import org.opentripplanner.routing.graph.Graph;
/**
* Represents a day of transit services.
* Intended for quickly checking whether a service is running during path searches.
*
* @author andrewbyrd
*
*/
public class ServiceDay implements Serializable {
private static final long serialVersionUID = -1206371243806996680L;
protected long midnight;
protected BitSet serviceIdsRunning;
/*
* make a ServiceDay including the given time's day's starting second and a set of
* serviceIds running on that day.
*/
public ServiceDay(Graph graph, long time, CalendarService cs, String agencyId) {
TimeZone timeZone = cs.getTimeZoneForAgencyId(agencyId);
GregorianCalendar calendar = new GregorianCalendar(timeZone);
calendar.setTime(new Date(time * 1000));
ServiceDate sd = new ServiceDate(calendar);
Date d = sd.getAsDate(timeZone);
this.midnight = d.getTime() / 1000;
serviceIdsRunning = new BitSet(cs.getServiceIds().size());
ServiceIdToNumberService service = graph.getService(ServiceIdToNumberService.class);
for (AgencyAndId serviceId : cs.getServiceIdsOnDate(sd)) {
int n = service.getNumber(serviceId);
if (n < 0)
continue;
serviceIdsRunning.set(n);
}
}
/*
* Does the given serviceId run on this ServiceDay?
*/
public boolean serviceIdRunning(int serviceId) {
return this.serviceIdsRunning.get(serviceId);
}
/*
* Return number of seconds after midnight on this ServiceDay
* for the given time.
*
* Note that the parameter and the return value are in seconds since the epoch
*
* Return value may be negative, indicating that the time is
* before this ServiceDay.
*/
public int secondsSinceMidnight(long time) {
return (int) (time - this.midnight);
}
/*
* Return number of seconds since the epoch
* based on the given number of seconds after midnight on this ServiceDay
*
* Input value may be negative, indicating that the time is
* before this ServiceDay.
*/
public long time(int secondsSinceMidnight) {
return this.midnight + secondsSinceMidnight;
}
public String toString() {
return Long.toString(this.midnight) + Arrays.asList(serviceIdsRunning);
}
public boolean equals(Object o) {
if (!(o instanceof ServiceDay)) return false;
ServiceDay other = (ServiceDay) o;
return other.midnight == midnight;
}
@Override
public int hashCode() {
return (int) midnight;
}
// public static ServiceDay universalService(Graph graph) {
// //FIXME: assumes all service is in the same tz
// final String agencyId = graph.getAgencyIds().iterator().next();
// ServiceDay universal = new ServiceDay(graph, 0, graph.getCalendarService(), agencyId);
//
// return universal;
// }
/** Used in RAPTOR graph analysis to board everything. */
public static class UniversalService extends ServiceDay {
private static final long serialVersionUID = 1L;
public UniversalService(Graph graph) {
super(graph, 0, graph.getCalendarService(), graph.getAgencyIds().iterator().next());
}
@Override
public boolean serviceIdRunning(int serviceId) { return true; }
}
}