View Javadoc
1   package org.djutils.stats.summarizers.event;
2   
3   import java.io.Serializable;
4   import java.rmi.RemoteException;
5   
6   import org.djutils.event.Event;
7   import org.djutils.event.EventListener;
8   import org.djutils.event.EventListenerMap;
9   import org.djutils.event.EventProducer;
10  import org.djutils.event.LocalEventProducer;
11  import org.djutils.exceptions.Throw;
12  import org.djutils.stats.summarizers.WeightedTally;
13  
14  /**
15   * The EventBasedWeightedTally class defines a time-weighted tally that can be notified with weights and values using the
16   * EventListener. It also produces events when values are tallied and when the tally is initialized. It embeds an EventProducer
17   * so it can keep listeners informed about new observations.
18   * <p>
19   * Copyright (c) 2002-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
20   * for project information <a href="https://simulation.tudelft.nl/" target="_blank"> https://simulation.tudelft.nl</a>. The DSOL
21   * project is distributed under a three-clause BSD-style license, which can be found at
22   * <a href="https://simulation.tudelft.nl/dsol/3.0/license.html" target="_blank">
23   * https://simulation.tudelft.nl/dsol/3.0/license.html</a>. <br>
24   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank"> Alexander Verbraeck</a>
25   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
26   */
27  public class EventBasedWeightedTally extends WeightedTally implements EventProducer, EventListener
28  {
29      /** */
30      private static final long serialVersionUID = 20200228L;
31  
32      /** The embedded EventProducer. */
33      private EventProducer eventProducer = null;
34  
35      /**
36       * Construct a new WeightedTally with a description.
37       * @param description String; the description of this WeightedTally
38       */
39      public EventBasedWeightedTally(final String description)
40      {
41          this(description, new LocalEventProducer());
42      }
43  
44      /**
45       * Construct a new WeightedTally with a description.
46       * @param description String; the description of this WeightedTally
47       * @param eventProducer EventProducer; the EventProducer to embed and use in this statistic
48       */
49      public EventBasedWeightedTally(final String description, final EventProducer eventProducer)
50      {
51          super(description);
52          Throw.whenNull(eventProducer, "eventProducer cannot be null");
53          this.eventProducer = eventProducer;
54      }
55  
56      @Override
57      public EventListenerMap getEventListenerMap() throws RemoteException
58      {
59          return this.eventProducer.getEventListenerMap();
60      }
61  
62      @Override
63      public void initialize()
64      {
65          super.initialize();
66          if (this.eventProducer != null)
67          {
68              try
69              {
70                  this.eventProducer.fireEvent(StatisticsEvents.INITIALIZED_EVENT);
71              }
72              catch (RemoteException exception)
73              {
74                  throw new RuntimeException(exception);
75              }
76          }
77      }
78  
79      @Override
80      public void notify(final Event event)
81      {
82          // metadata descriptor checks content
83          Object[] content = (Object[]) event.getContent();
84          double weight = ((Number) content[0]).doubleValue();
85          double value = ((Number) content[1]).doubleValue();
86          register(weight, value);
87      }
88  
89      /**
90       * Process one observed weighted value.
91       * @param weight double; the weight of the value to process
92       * @param value double; the value to process
93       * @return double; the value
94       */
95      @Override
96      public double register(final double weight, final double value)
97      {
98          super.register(weight, value);
99          try
100         {
101             if (hasListeners())
102             {
103                 this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_OBSERVATION_ADDED_EVENT,
104                         new Serializable[] {weight, value});
105                 fireEvents();
106             }
107         }
108         catch (RemoteException exception)
109         {
110             throw new RuntimeException(exception);
111         }
112         return value;
113     }
114 
115     /**
116      * Method that can be overridden to fire own events or additional events when registering an observation.
117      * @throws RemoteException on network error
118      */
119     protected void fireEvents() throws RemoteException
120     {
121         this.eventProducer.fireEvent(StatisticsEvents.N_EVENT, getN());
122         this.eventProducer.fireEvent(StatisticsEvents.MIN_EVENT, getMin());
123         this.eventProducer.fireEvent(StatisticsEvents.MAX_EVENT, getMax());
124         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_POPULATION_MEAN_EVENT, getWeightedPopulationMean());
125         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_POPULATION_VARIANCE_EVENT, getWeightedPopulationVariance());
126         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_POPULATION_STDEV_EVENT, getWeightedPopulationStDev());
127         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SUM_EVENT, getWeightedSum());
128         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SAMPLE_MEAN_EVENT, getWeightedSampleMean());
129         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SAMPLE_VARIANCE_EVENT, getWeightedSampleVariance());
130         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SAMPLE_STDEV_EVENT, getWeightedSampleStDev());
131     }
132 
133     @Override
134     public String toString()
135     {
136         return super.toString();
137     }
138 
139 }