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      /** {@inheritDoc} */
57      @Override
58      public EventListenerMap getEventListenerMap() throws RemoteException
59      {
60          return this.eventProducer.getEventListenerMap();
61      }
62  
63      /** {@inheritDoc} */
64      @Override
65      public void initialize()
66      {
67          super.initialize();
68          if (this.eventProducer != null)
69          {
70              try
71              {
72                  this.eventProducer.fireEvent(StatisticsEvents.INITIALIZED_EVENT);
73              }
74              catch (RemoteException exception)
75              {
76                  throw new RuntimeException(exception);
77              }
78          }
79      }
80  
81      /** {@inheritDoc} */
82      @Override
83      public void notify(final Event event)
84      {
85          // metadata descriptor checks content
86          Object[] content = (Object[]) event.getContent();
87          double weight = ((Number) content[0]).doubleValue();
88          double value = ((Number) content[1]).doubleValue();
89          register(weight, value);
90      }
91  
92      /**
93       * Process one observed weighted value.
94       * @param weight double; the weight of the value to process
95       * @param value double; the value to process
96       * @return double; the value
97       */
98      @Override
99      public double register(final double weight, final double value)
100     {
101         super.register(weight, value);
102         try
103         {
104             if (hasListeners())
105             {
106                 this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_OBSERVATION_ADDED_EVENT,
107                         new Serializable[] {weight, value});
108                 fireEvents();
109             }
110         }
111         catch (RemoteException exception)
112         {
113             throw new RuntimeException(exception);
114         }
115         return value;
116     }
117 
118     /**
119      * Method that can be overridden to fire own events or additional events when registering an observation.
120      * @throws RemoteException on network error
121      */
122     protected void fireEvents() throws RemoteException
123     {
124         this.eventProducer.fireEvent(StatisticsEvents.N_EVENT, getN());
125         this.eventProducer.fireEvent(StatisticsEvents.MIN_EVENT, getMin());
126         this.eventProducer.fireEvent(StatisticsEvents.MAX_EVENT, getMax());
127         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_POPULATION_MEAN_EVENT, getWeightedPopulationMean());
128         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_POPULATION_VARIANCE_EVENT, getWeightedPopulationVariance());
129         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_POPULATION_STDEV_EVENT, getWeightedPopulationStDev());
130         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SUM_EVENT, getWeightedSum());
131         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SAMPLE_MEAN_EVENT, getWeightedSampleMean());
132         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SAMPLE_VARIANCE_EVENT, getWeightedSampleVariance());
133         this.eventProducer.fireEvent(StatisticsEvents.WEIGHTED_SAMPLE_STDEV_EVENT, getWeightedSampleStDev());
134     }
135 
136     /** {@inheritDoc} */
137     @Override
138     public String toString()
139     {
140         return super.toString();
141     }
142 
143 }