BusSchedule.java
package org.opentrafficsim.road.gtu.lane.tactical.pt;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.djunits.value.vdouble.scalar.Duration;
import org.djunits.value.vdouble.scalar.Time;
import org.djutils.exceptions.Throw;
import org.opentrafficsim.core.gtu.GtuType;
import org.opentrafficsim.core.network.NetworkException;
import org.opentrafficsim.core.network.Node;
import org.opentrafficsim.core.network.route.Route;
/**
* <p>
* Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
* BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
* </p>
* @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
* @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
* @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
*/
public class BusSchedule extends Route
{
/** */
private static final long serialVersionUID = 20170124L;
/** Line of the bus schedule. */
private final String line;
/** List of bus stops. */
private final Map<String, BusStopInfo> schedule = new LinkedHashMap<>();
/** Map of actual departures stored per bus stop. */
private final Map<String, Time> actualDeparturesBusStop = new LinkedHashMap<>();
/** Map of actual departures stored per conflict. */
private final Map<String, Time> actualDeparturesConflict = new LinkedHashMap<>();
/**
* @param id String; id
* @param gtuType GtuType; the GtuType for which this is a route
* @param nodes List<Node>; nodes
* @param line String; line of the bus schedule
* @throws NetworkException if intermediate nodes are missing in the route.
*/
public BusSchedule(final String id, final GtuType gtuType, final List<Node> nodes, final String line)
throws NetworkException
{
super(id, gtuType, nodes);
this.line = line;
}
/**
* @param id String; id
* @param gtuType GtuType; the GtuType for which this is a route
* @param line String; line of the bus schedule
*/
public BusSchedule(final String id, final GtuType gtuType, final String line)
{
super(id, gtuType);
this.line = line;
}
/**
* Adds a stop to the schedule.
* @param busStopId String; bus stop id
* @param departureTime Time; departure time
* @param dwellTime Duration; dwell time
* @param forceSchedule boolean; whether to wait until departure time
*/
public final void addBusStop(final String busStopId, final Time departureTime, final Duration dwellTime,
final boolean forceSchedule)
{
Throw.whenNull(busStopId, "Bus stop id may not be null.");
Throw.whenNull(departureTime, "Departure time may not be null.");
Throw.whenNull(dwellTime, "Dwell time may not be null.");
this.schedule.put(busStopId, new BusStopInfo(departureTime, dwellTime, forceSchedule));
}
/**
* Whether the bus of this line should stop for this bus stop. False if not the correct line, or already stopped.
* @param busStopId String; id of bus stop
* @param time Time; time to check
* @return whether the bus of this line should stop for this bus stop
*/
public final boolean isLineStop(final String busStopId, final Time time)
{
return this.schedule.containsKey(busStopId) && (!this.actualDeparturesConflict.containsKey(busStopId)
|| time.lt(this.actualDeparturesConflict.get(busStopId)));
}
/**
* Returns departure time for the given bus stop.
* @param busStopId String; id of bus stop
* @return departure time for the given bus stop
*/
public final Time getDepartureTime(final String busStopId)
{
checkStop(busStopId);
return this.schedule.get(busStopId).getDepartureTime();
}
/**
* Returns dwell time for the given bus stop.
* @param busStopId String; id of bus stop
* @return dwell time for the given bus stop
*/
public final Duration getDwellTime(final String busStopId)
{
checkStop(busStopId);
return this.schedule.get(busStopId).getDwellTime();
}
/**
* Returns whether the departure time is enforced.
* @param busStopId String; id of bus stop
* @return whether the departure time is enforced
*/
public final boolean isForceSchedule(final String busStopId)
{
checkStop(busStopId);
return this.schedule.get(busStopId).isForceSchedule();
}
/**
* Throws exception when the bus stop is not part of this schedule.
* @param busStopId String; id of bus stop
* @throws IllegalArgumentException if the bus stop is not part of this schedule
*/
private void checkStop(final String busStopId)
{
Throw.when(!this.schedule.containsKey(busStopId), IllegalArgumentException.class, "Bus stop %s is not for schedule %s.",
busStopId, this);
}
/**
* Set actual departure time.
* @param busStopId String; bus stop id
* @param conflictIds Set<String>; conflicts downstream of the bus stop
* @param time Time; actual departure time
*/
public final void setActualDeparture(final String busStopId, final Set<String> conflictIds, final Time time)
{
this.actualDeparturesBusStop.put(busStopId, time);
for (String conflictId : conflictIds)
{
this.actualDeparturesConflict.put(conflictId, time);
}
}
/**
* Return the actual departure time.
* @param busStopId String; bus stop id
* @return actual departure time, {@code null} if not given
*/
public final Time getActualDepartureBusStop(final String busStopId)
{
return this.actualDeparturesBusStop.get(busStopId);
}
/**
* Return the actual departure time.
* @param conflictId String; conflict id
* @return actual departure time, {@code null} if not given
*/
public final Time getActualDepartureConflict(final String conflictId)
{
return this.actualDeparturesConflict.get(conflictId);
}
/**
* @return line.
*/
public final String getLine()
{
return this.line;
}
/** {@inheritDoc} */
@Override
public final String toString()
{
return "BusSchedule [id=" + getId() + ", line=" + this.line + "]";
}
/**
* Class to contain info regarding a stop in the schedule.
* <p>
* Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* <br>
* BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
* </p>
* @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
* @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
* @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
*/
private class BusStopInfo
{
/** Departure time. */
private final Time departureTime;
/** Dwell time. */
private final Duration dwellTime;
/** Whether to wait until departure time. */
private final boolean forceSchedule;
/**
* @param departureTime Time; departure time
* @param dwellTime Duration; dwell time
* @param forceSchedule boolean; whether to wait until departure time
*/
BusStopInfo(final Time departureTime, final Duration dwellTime, final boolean forceSchedule)
{
this.departureTime = departureTime;
this.dwellTime = dwellTime;
this.forceSchedule = forceSchedule;
}
/**
* @return departureTime.
*/
public final Time getDepartureTime()
{
return this.departureTime;
}
/**
* @return dwellTime.
*/
public final Duration getDwellTime()
{
return this.dwellTime;
}
/**
* @return forceSchedule.
*/
public final boolean isForceSchedule()
{
return this.forceSchedule;
}
/** {@inheritDoc} */
@Override
public String toString()
{
return "BusStopInfo [departureTime=" + this.departureTime + ", dwellTime=" + this.dwellTime + ", forceSchedule="
+ this.forceSchedule + "]";
}
}
}