private void ParseEvents(OPLParser oplParser, IEnumerable<SignalEvent> signalEvents, BlockingBackConfig config)
        {
            int vehicleCount = 0;
            int oldCount = 0;
            uint lastVehicleEntering = 0;
            uint lastVehicleExit = 0;
            uint lastBlockedBegin = 0;

            foreach (string signalName in config.BlockedSignals) {
                _blockingBackBlockedRanges.Add(signalName, new TimePeriodCollection());
            }

            foreach (SignalEvent signalEvent in signalEvents) {
                oldCount = vehicleCount;

                uint curTime = signalEvent.TimeAsUnixTime;
                string eventElementName;
                if (signalEvent.EventType == SignalEvent.Type.TransitVehicleDetectedInLogic) {
                    eventElementName = signalEvent.ElementName + " " + signalEvent.ExtraInfo;
                } else {
                    eventElementName = signalEvent.ElementName;
                }
                if (config.StrikeIn.Contains(eventElementName)) {
                    // A vehicle has entered the monitored section.
                    vehicleCount += 1;
                    lastVehicleEntering = curTime;
                } else if (config.StrikeOut.Contains(eventElementName)) {
                    // A vehicle has left the monitored section.
                    if (vehicleCount > 0) {
                        vehicleCount -= 1;
                    }
                    lastVehicleExit = curTime;
                }

                if (config.TimeOut != 0 && lastVehicleExit > 0 && curTime - lastVehicleExit > config.TimeOut) {
                    if (vehicleCount > 0) {
                        vehicleCount -= 1;
                        lastVehicleExit = curTime;
                    }
                }

                // Check whether we've crossed the threshold for blocking/unblocking the signal groups.
                if (oldCount < config.MaxVehicles && vehicleCount >= config.MaxVehicles) {
                    lastBlockedBegin = curTime;
                    foreach (string signalName in config.BlockedSignals) {
                        _blockingBackEvents.Add(new SignalEvent(SignalEvent.Type.SignalGroupBlocked, curTime,
                            oplParser.GetSignalElementUidByName(signalName), signalName,
                            signalEvent.ElementName));
                    }
                } else if (oldCount >= config.MaxVehicles && vehicleCount < config.MaxVehicles) {
                    foreach (string signalName in config.BlockedSignals) {
                        _blockingBackBlockedRanges[signalName].Add(
                            new TimeRange(Utils.UnixTimeToDateTime(lastBlockedBegin),
                            Utils.UnixTimeToDateTime(curTime), true));
                        _blockingBackEvents.Add(new SignalEvent(SignalEvent.Type.SignalGroupUnblocked, curTime,
                            oplParser.GetSignalElementUidByName(signalName), signalName,
                            signalEvent.ElementName));
                    }
                }
            }
        }
 private void AddIntergreenEvents(OPLParser oplParser, IEnumerable<SignalEvent> signalEvents)
 {
     foreach (SignalEvent signalEvent in signalEvents) {
         var curName = signalEvent.ElementName;
         // If a signal group changes to red, all conflicting signal groups become unblocked
         // after the intergreen time has elapsed.
         // Note: Strictly speaking the termination of the green phase is the interesting point,
         // however we currently assume the usual case of a transit vehicle actively replacing
         // it's own signal to red, in which case there is no yellow phase.
         if (signalEvent.EventType == SignalEvent.Type.SignalGroupChangeToRed) {
             foreach (string conflictingElement in _intergreenTimes[curName].Keys) {
                 _intergreenEvents.Add(new SignalEvent(SignalEvent.Type.SignalGroupUnblocked,
                     (uint)(signalEvent.TimeAsUnixTime + _intergreenTimes[curName][conflictingElement]),
                     oplParser.GetSignalElementUidByName(conflictingElement),
                     conflictingElement, curName));
             }
         }
         // If a signal group changes to green, we need to look back in time and determine the
         // latest point at which a conflicting signal group had to switch away from green.
         else if (signalEvent.EventType == SignalEvent.Type.SignalGroupChangeToGreen) {
             foreach (string conflictingElement in _intergreenTimes.Keys) {
                 if (_intergreenTimes[conflictingElement].ContainsKey(curName)) {
                     _intergreenEvents.Add(new SignalEvent(SignalEvent.Type.SignalGroupBlocked,
                     (uint)(signalEvent.TimeAsUnixTime - _intergreenTimes[conflictingElement][curName]),
                     oplParser.GetSignalElementUidByName(conflictingElement),
                     conflictingElement, curName));
                 }
             }
         }
     }
 }