@Override
  public void handleEvent(WarmEmissionEvent event) {

    Id<Person> driverId =
        Id.createPersonId(
            event
                .getVehicleId()); // TODO [AA]: either it should be mapped to vehicle id or read
                                  // events file too to get driver id

    if (this.af != null) { // area filtering
      Link link = network.getLinks().get(event.getLinkId());
      if (!this.af.isLinkInsideShape(link)) return;

      if (this.ug == null || this.pf == null) { // only area filtering
        delegate.handleEvent(event);
      } else if (this.pf
          .getUserGroupAsStringFromPersonId(driverId)
          .equals(this.ug)) { // both filtering
        delegate.handleEvent(event);
      }

    } else {

      if (this.ug == null || this.pf == null) { // no filtering
        delegate.handleEvent(event);
      } else if (this.pf
          .getUserGroupAsStringFromPersonId(driverId)
          .equals(this.ug)) { // user group filtering
        delegate.handleEvent(event);
      }
    }
  }
  @Override
  public void handleEvent(WarmEmissionEvent event) {
    Double time = event.getTime();
    if (time == 0.0) time = this.timeBinSize;
    Id<Link> linkId = event.getLinkId();
    Map<WarmPollutant, Double> warmEmissionsOfEvent = event.getWarmEmissions();
    double endOfTimeInterval = 0.0;

    if (warmEmissionsOfEvent == null) {
      warmEmissionsOfEvent = new HashMap<WarmPollutant, Double>();
      for (WarmPollutant wp : WarmPollutant.values()) {
        warmEmissionsOfEvent.put(wp, 0.0);
      }
    } else {
      for (WarmPollutant wp : WarmPollutant.values()) {
        if (warmEmissionsOfEvent.get(wp) == null) {
          warmEmissionsOfEvent.put(wp, 0.0);
        }
      }
    }

    endOfTimeInterval = Math.ceil(time / timeBinSize) * timeBinSize;
    if (endOfTimeInterval <= 0.0) endOfTimeInterval = timeBinSize;

    Map<Id<Link>, Map<WarmPollutant, Double>> warmEmissionsTotal;
    Map<Id<Link>, Double> countTotal;

    if (this.time2warmEmissionsTotal.get(endOfTimeInterval) != null) {
      warmEmissionsTotal = this.time2warmEmissionsTotal.get(endOfTimeInterval);
      countTotal = this.time2linkIdLeaveCount.get(endOfTimeInterval);

      if (warmEmissionsTotal.get(linkId) != null) {
        Map<WarmPollutant, Double> warmEmissionsSoFar = warmEmissionsTotal.get(linkId);

        for (WarmPollutant wp : WarmPollutant.values()) {
          warmEmissionsSoFar.put(wp, warmEmissionsOfEvent.get(wp) + warmEmissionsSoFar.get(wp));
        }

        double countsSoFar = countTotal.get(linkId);
        double newValue = countsSoFar + 1.;
        countTotal.put(linkId, newValue);
        warmEmissionsTotal.put(linkId, warmEmissionsSoFar);
      } else {
        warmEmissionsTotal.put(linkId, warmEmissionsOfEvent);
        countTotal.put(linkId, 1.);
      }
    } else {
      countTotal = new HashMap<>();
      warmEmissionsTotal = new HashMap<Id<Link>, Map<WarmPollutant, Double>>();
      warmEmissionsTotal.put(linkId, warmEmissionsOfEvent);
      countTotal.put(linkId, 1.);
    }
    this.time2warmEmissionsTotal.put(endOfTimeInterval, warmEmissionsTotal);
    this.time2linkIdLeaveCount.put(endOfTimeInterval, countTotal);
  }
  @Override
  public void handleEvent(WarmEmissionEvent event) {
    // calc emission costs of event
    double emissionCost = ecm.calculateWarmEmissionCosts(event.getWarmEmissions());

    // calc time bin of event
    int timeBin = getTimeBin(event.getTime());

    // user group
    UserGroup userGroup = getUserGroup(event.getVehicleId());

    Id<Link> linkId = event.getLinkId();

    // store cost for (timebin x usergroup x link) combination
    timeBin2group2link2flatEmissionCost
        .get(timeBin)
        .addEmissionCosts(userGroup, linkId, emissionCost);
  }