001/* *********************************************************************** * 002 * project: org.matsim.* 003 * PlanToPlanStepBasedOnEvents.java 004 * * 005 * *********************************************************************** * 006 * * 007 * copyright : (C) 2012 by the members listed in the COPYING, * 008 * LICENSE and WARRANTY file. * 009 * email : info at matsim dot org * 010 * * 011 * *********************************************************************** * 012 * * 013 * This program is free software; you can redistribute it and/or modify * 014 * it under the terms of the GNU General Public License as published by * 015 * the Free Software Foundation; either version 2 of the License, or * 016 * (at your option) any later version. * 017 * See also COPYING, LICENSE and WARRANTY file * 018 * * 019 * *********************************************************************** */ 020 021package org.matsim.contrib.cadyts.measurement; 022 023import java.util.HashSet; 024import java.util.Map; 025import java.util.Set; 026import java.util.TreeMap; 027 028import org.apache.log4j.Logger; 029import org.junit.Assert; 030import org.matsim.api.core.v01.Id; 031import org.matsim.api.core.v01.Scenario; 032import org.matsim.api.core.v01.events.PersonArrivalEvent; 033import org.matsim.api.core.v01.events.PersonDepartureEvent; 034import org.matsim.api.core.v01.events.handler.PersonArrivalEventHandler; 035import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; 036import org.matsim.api.core.v01.population.Person; 037import org.matsim.api.core.v01.population.Plan; 038import org.matsim.contrib.analysis.kai.DataMap; 039import org.matsim.contrib.analysis.kai.Databins; 040import org.matsim.contrib.cadyts.general.PlansTranslator; 041 042import cadyts.demand.PlanBuilder; 043import cadyts.measurements.SingleLinkMeasurement.TYPE; 044import cadyts.supply.SimResults; 045 046public class MeasurementListener implements PlansTranslator<Measurement>, 047 PersonDepartureEventHandler, PersonArrivalEventHandler, SimResults<Measurement> { 048 049 private static final long serialVersionUID = 1L; 050 051 private static final Logger log = Logger.getLogger(MeasurementListener.class); 052 053 private final Scenario scenario; 054 055 private final Map<Id<Person>,PersonDepartureEvent> driverAgents = new TreeMap<>() ; 056 057 private int iteration = -1; 058 059 // this is _only_ there for output: 060 Set<Plan> plansEverSeen = new HashSet<>(); 061 062 private static final String STR_PLANSTEPFACTORY = "planStepFactory"; 063 private static final String STR_ITERATION = "iteration"; 064 065 private final Measurements measurements ; 066 067 private final Databins<Measurement> databins ; 068 069 MeasurementListener(final Scenario scenario, Measurements measurements) { 070 this.measurements = measurements ; 071 this.scenario = scenario; 072 073 double[] dataBoundaries = new double[24] ; 074 for ( int ii=0 ; ii<dataBoundaries.length; ii++ ) { 075 dataBoundaries[ii] = ii * 3600. ; 076 // hourly bins, not connected to anything; this might be improved ... 077 } 078 this.databins = new Databins<Measurement>( "travel times for measurement facility at each hour" , dataBoundaries ) ; 079 } 080 081 private long plansFound = 0; 082 private long plansNotFound = 0; 083 084 @Override 085 public final cadyts.demand.Plan<Measurement> getCadytsPlan(final Plan plan) { 086 @SuppressWarnings("unchecked") 087 PlanBuilder<Measurement> planStepFactory = (PlanBuilder<Measurement>) plan.getCustomAttributes().get(STR_PLANSTEPFACTORY); 088 if (planStepFactory == null) { 089 this.plansNotFound++; 090 return null; 091 } 092 this.plansFound++; 093 final cadyts.demand.Plan<Measurement> planSteps = planStepFactory.getResult(); 094 return planSteps; 095 } 096 097 @Override 098 public void reset(final int iteration1) { 099 this.iteration = iteration1; 100 101 log.warn("found " + this.plansFound + " out of " + (this.plansFound + this.plansNotFound) + " (" 102 + (100. * this.plansFound / (this.plansFound + this.plansNotFound)) + "%)"); 103 log.warn("(above values may both be at zero for a couple of iterations if multiple plans per agent all have no score)"); 104 105 this.driverAgents.clear(); 106 } 107 108 @Override 109 public void handleEvent(PersonDepartureEvent event) { 110 this.driverAgents.put(event.getPersonId(), event ) ; 111 } 112 113 @Override 114 public void handleEvent(PersonArrivalEvent event) { 115 PersonDepartureEvent dpEvent = this.driverAgents.remove( event.getPersonId() ) ; 116 double ttime = event.getTime() - dpEvent.getTime() ; 117 118 // the travel time determines the measurement "facility": 119 Measurement measurement = measurements.getMeasurementFromTTimeInSeconds(ttime) ; 120 121 // the following will fill the cadyts plan: 122 // get the planStepFactory for the plan (or create one): 123 Person person = this.scenario.getPopulation().getPersons().get(event.getPersonId()); 124 PlanBuilder<Measurement> tmpPlanStepFactory = getPlanStepFactoryForPlan(person.getSelectedPlan()); 125 // add the measurement: 126 if (tmpPlanStepFactory != null) { 127 // can this happen?? Maybe in early time steps??? 128 129 tmpPlanStepFactory.addTurn( measurement, (int) event.getTime()); 130 } 131 132 // the following will lead to getSimValue: 133 int idx = this.databins.getIndex( dpEvent.getTime() ) ; 134 this.databins.inc( measurement, idx); 135 136 } 137 138 // ################################################################################### 139 // only private functions below here (low level functionality) 140 141 private PlanBuilder<Measurement> getPlanStepFactoryForPlan(final Plan selectedPlan) { 142 143 @SuppressWarnings("unchecked") 144 PlanBuilder<Measurement> planStepFactory = (PlanBuilder<Measurement>) selectedPlan.getCustomAttributes().get(STR_PLANSTEPFACTORY); 145 146 Integer factoryIteration = (Integer) selectedPlan.getCustomAttributes().get(STR_ITERATION); 147 if (planStepFactory == null || factoryIteration == null || factoryIteration != this.iteration) { 148 // attach the iteration number to the plan: 149 selectedPlan.getCustomAttributes().put(STR_ITERATION, this.iteration); 150 151 // construct a new PlanBulder and attach it to the plan: 152 planStepFactory = new PlanBuilder<Measurement>(); 153 selectedPlan.getCustomAttributes().put(STR_PLANSTEPFACTORY, planStepFactory); 154 155 // memorize the plan as being seen: 156 this.plansEverSeen.add(selectedPlan); 157 } 158 159 return planStepFactory; 160 } 161 162 @Override 163 public double getSimValue(Measurement mea, int startTime_s, int endTime_s, TYPE type) { 164 Assert.assertNotNull( mea ); 165 return this.databins.getValue( mea, this.databins.getIndex( startTime_s ) ) ; 166 } 167 168 169 170}