1   package org.opentrafficsim.road.network.sampling.indicator;
2   
3   import java.util.HashMap;
4   import java.util.List;
5   import java.util.Map;
6   
7   import org.djunits.unit.DurationUnit;
8   import org.djunits.value.ValueException;
9   import org.djunits.value.vdouble.scalar.Duration;
10  import org.djunits.value.vdouble.scalar.Time;
11  import org.djunits.value.vfloat.vector.FloatSpeedVector;
12  import org.djutils.exceptions.Throw;
13  import org.opentrafficsim.kpi.interfaces.GtuDataInterface;
14  import org.opentrafficsim.kpi.sampling.Query;
15  import org.opentrafficsim.kpi.sampling.SamplingException;
16  import org.opentrafficsim.kpi.sampling.Trajectory;
17  import org.opentrafficsim.kpi.sampling.TrajectoryGroup;
18  import org.opentrafficsim.kpi.sampling.indicator.AbstractIndicator;
19  import org.opentrafficsim.road.network.sampling.data.ReferenceSpeed;
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  public class TotalDelayReference extends AbstractIndicator<Duration>
33  {
34  
35      
36      private static final ReferenceSpeed REF_SPEED_TYPE = new ReferenceSpeed();
37  
38      
39      @Override
40      protected final <G extends GtuDataInterface> Duration calculate(final Query<G> query, final Time startTime,
41              final Time endTime, final List<TrajectoryGroup<G>> trajectoryGroups)
42      {
43          Map<String, Duration> gtuTimes = new HashMap<>();
44          Map<String, Duration> gtuRefTimes = new HashMap<>();
45          for (TrajectoryGroup<? extends GtuDataInterface> trajectoryGroup : trajectoryGroups)
46          {
47              try
48              {
49                  for (Trajectory<?> trajectory : trajectoryGroup.getTrajectories())
50                  {
51                      Duration sumTime;
52                      Duration sumRefTime;
53                      if (gtuTimes.containsKey(trajectory.getGtuId()))
54                      {
55                          sumTime = gtuTimes.get(trajectory.getGtuId());
56                          sumRefTime = gtuRefTimes.get(trajectory.getGtuId());
57                      }
58                      else
59                      {
60                          sumTime = Duration.ZERO;
61                          sumRefTime = Duration.ZERO;
62                      }
63                      Throw.when(!trajectory.contains(REF_SPEED_TYPE), UnsupportedOperationException.class,
64                              "TotalDelayReference can only work with trajectories that have %s extended data.",
65                              REF_SPEED_TYPE.getId());
66                      FloatSpeedVector refSpeed = trajectory.getExtendedData(REF_SPEED_TYPE);
67                      float[] x = trajectory.getX();
68                      try
69                      {
70                          for (int i = 1; i < refSpeed.size(); i++)
71                          {
72                              double refV;
73                              if (!Double.isNaN(refSpeed.get(i).si))
74                              {
75                                  refV = refSpeed.get(i - 1).si;
76                              }
77                              else
78                              {
79                                  refV = (refSpeed.get(i - 1).si + refSpeed.get(i).si) / 2.0;
80                              }
81                              double dx = x[i] - x[i - 1];
82                              sumRefTime = sumRefTime.plus(new Duration(dx / refV, DurationUnit.SI));
83                          }
84                      }
85                      catch (ValueException exception)
86                      {
87                          
88                          throw new RuntimeException("Trying to obtain value outside of range.", exception);
89                      }
90                      gtuTimes.put(trajectory.getGtuId(), sumTime.plus(trajectory.getTotalDuration()));
91                      gtuRefTimes.put(trajectory.getGtuId(), sumRefTime);
92                  }
93              }
94              catch (SamplingException exception)
95              {
96                  throw new RuntimeException("Exception while trying to determine delay in trajectory.", exception);
97              }
98          }
99          Duration delaySum = Duration.ZERO;
100         for (String id : gtuTimes.keySet())
101         {
102             Duration gtuTime = gtuTimes.get(id);
103             Duration gtuRefTime = gtuRefTimes.get(id);
104             if (gtuTime.gt(gtuRefTime))
105             {
106                 delaySum = delaySum.plus(gtuTime.minus(gtuRefTime));
107             }
108         }
109         return delaySum;
110     }
111 
112     
113     @Override
114     @SuppressWarnings("checkstyle:designforextension")
115     public String toString()
116     {
117         return "TotalDelayReference";
118     }
119 
120 }