Skip to content

Commit 6171611

Browse files
committed
Added cell occupancy event generation for partitions
1 parent eee111d commit 6171611

11 files changed

Lines changed: 1584 additions & 1118 deletions

File tree

simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/plugins/partitions/datamanagers/PartitionsDataManager.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
import gov.hhs.aspr.ms.gcm.simulation.nucleus.DataManager;
1212
import gov.hhs.aspr.ms.gcm.simulation.nucleus.DataManagerContext;
1313
import gov.hhs.aspr.ms.gcm.simulation.nucleus.Event;
14+
import gov.hhs.aspr.ms.gcm.simulation.nucleus.EventFilter;
15+
import gov.hhs.aspr.ms.gcm.simulation.nucleus.IdentifiableFunctionMap;
16+
import gov.hhs.aspr.ms.gcm.simulation.plugins.partitions.events.CellOccupancyEvent;
1417
import gov.hhs.aspr.ms.gcm.simulation.plugins.partitions.support.DegeneratePopulationPartitionImpl;
1518
import gov.hhs.aspr.ms.gcm.simulation.plugins.partitions.support.FilterSensitivity;
1619
import gov.hhs.aspr.ms.gcm.simulation.plugins.partitions.support.LabelSet;
@@ -54,6 +57,11 @@
5457
* Subscribes to other events as needed to support the population partition
5558
* maintenance
5659
* </p>
60+
* <p>
61+
* Produces {@linkplain CellOccupancyEvent} whenever a person is added to an
62+
* empty partition cell if the partition has its produceCellOccupancyEvents
63+
* policy set to true.
64+
* </p>
5765
*/
5866
public final class PartitionsDataManager extends DataManager {
5967

@@ -528,10 +536,10 @@ public void addPartition(final Partition partition, final Object key) {
528536

529537
PopulationPartition populationPartition;
530538
if (partition.isDegenerate()) {
531-
populationPartition = new DegeneratePopulationPartitionImpl(key,dataManagerContext, partition,
539+
populationPartition = new DegeneratePopulationPartitionImpl(key, dataManagerContext, partition,
532540
supportRunContinuity);
533541
} else {
534-
populationPartition = new PopulationPartitionImpl(key,dataManagerContext, partition, supportRunContinuity);
542+
populationPartition = new PopulationPartitionImpl(key, dataManagerContext, partition, supportRunContinuity);
535543
}
536544
keyToPopulationPartitionMap.put(key, populationPartition);
537545

@@ -577,16 +585,30 @@ public void removePartition(final Object key) {
577585
}
578586
}
579587
}
580-
581-
582-
// public void subscribeForCellOccupancyEvents(final Object key, final LabelSet labelSet) {
583-
//
584-
// }
585-
586-
// public void unsubscribeForCellOccupancyEvents(final Object key, final LabelSet labelSet) {
587-
//
588-
//}
589588

589+
/*
590+
* Enum supporting event filters for McmPersonDistributionEvents
591+
*/
592+
private static enum CellOccupancyEventFunctionId {
593+
ID;
594+
}
590595

596+
/*
597+
* Map supporting event filters for ActiveHubAssignmentEvent
598+
*/
599+
private IdentifiableFunctionMap<CellOccupancyEvent> cellOccupancyEventFunctionMap = //
600+
IdentifiableFunctionMap.builder(CellOccupancyEvent.class)//
601+
.put(CellOccupancyEventFunctionId.ID, e -> e.id())//
602+
.build();//
591603

604+
/**
605+
* Returns an event filter used to subscribe to {@link CellOccupancyEvent}
606+
* events. Matches on key id.
607+
*
608+
*/
609+
public EventFilter<CellOccupancyEvent> getEventFilterForCellOccupancyEvent(Object key) {
610+
return EventFilter.builder(CellOccupancyEvent.class)//
611+
.addFunctionValuePair(cellOccupancyEventFunctionMap.get(CellOccupancyEventFunctionId.ID), key)//
612+
.build();
613+
}
592614
}

simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/plugins/partitions/events/PartitionCellOccupancyEvent.java renamed to simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/plugins/partitions/events/CellOccupancyEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
* give label set has transitioned from zero to a positive number of people.
1010
*/
1111
@Immutable
12-
public record PartitionCellOccupancyEvent(Object id, LabelSet labelSet) implements Event {
12+
public record CellOccupancyEvent(Object id, LabelSet labelSet) implements Event {
1313
}

simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/plugins/partitions/support/DegeneratePopulationPartitionImpl.java

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import gov.hhs.aspr.ms.gcm.simulation.nucleus.DataManagerContext;
1212
import gov.hhs.aspr.ms.gcm.simulation.nucleus.Event;
13+
import gov.hhs.aspr.ms.gcm.simulation.plugins.partitions.events.CellOccupancyEvent;
1314
import gov.hhs.aspr.ms.gcm.simulation.plugins.partitions.support.filters.Filter;
1415
import gov.hhs.aspr.ms.gcm.simulation.plugins.partitions.support.filters.TrueFilter;
1516
import gov.hhs.aspr.ms.gcm.simulation.plugins.people.datamanagers.PeopleDataManager;
@@ -28,13 +29,9 @@
2829
public class DegeneratePopulationPartitionImpl implements PopulationPartition {
2930

3031
private final StochasticsDataManager stochasticsDataManager;
31-
3232
private final PeopleContainer peopleContainer;
33-
3433
private final PartitionsContext partitionsContext;
3534
private final DataManagerContext dataManagerContext;
36-
private final Object id;
37-
3835
private final Filter filter;
3936

4037
private final Map<Class<? extends Event>, List<FilterSensitivity<? extends Event>>> eventClassToFilterSensitivityMap = new LinkedHashMap<>();
@@ -51,12 +48,13 @@ public class DegeneratePopulationPartitionImpl implements PopulationPartition {
5148
* <li>if the partition contains labelers</li>
5249
* </ul>
5350
*/
54-
public DegeneratePopulationPartitionImpl(final Object id, final DataManagerContext dataManagerContext, final Partition partition,
55-
boolean supportRunContinuity) {
56-
this.id = id;
51+
public DegeneratePopulationPartitionImpl(final Object id, final DataManagerContext dataManagerContext,
52+
final Partition partition, boolean supportRunContinuity) {
53+
cellOccupancyEvent = new CellOccupancyEvent(id, occupancyLabelSet);
54+
produceCellOccupanceEvents = partition.produceCellOccupancyEvents();
5755
this.dataManagerContext = dataManagerContext;
58-
this.partitionsContext = new PartitionsContextImpl(dataManagerContext);
59-
stochasticsDataManager = partitionsContext.getDataManager(StochasticsDataManager.class);
56+
partitionsContext = new PartitionsContextImpl(dataManagerContext);
57+
stochasticsDataManager = dataManagerContext.getDataManager(StochasticsDataManager.class);
6058
filter = partition.getFilter().orElse(new TrueFilter());
6159

6260
if (!partition.isDegenerate()) {
@@ -72,11 +70,10 @@ public DegeneratePopulationPartitionImpl(final Object id, final DataManagerConte
7270
}
7371
list.add(filterSensitivity);
7472
}
75-
73+
7674
final PeopleDataManager peopleDataManager = partitionsContext.getDataManager(PeopleDataManager.class);
7775
peopleContainer = new BasePeopleContainer(peopleDataManager, supportRunContinuity);
7876

79-
8077
final int personIdLimit = peopleDataManager.getPersonIdLimit();
8178
for (int i = 0; i < personIdLimit; i++) {
8279
if (peopleDataManager.personIndexExists(i)) {
@@ -101,10 +98,28 @@ public void attemptPersonAddition(final PersonId personId) {
10198
* simulation or new to this population partition and thus cannot already in
10299
* members of this population partition.
103100
*/
104-
peopleContainer.unsafeAdd(personId);
101+
102+
if(produceCellOccupanceEvents) {
103+
boolean initiallyEmpty = peopleContainer.size() == 0;
104+
peopleContainer.unsafeAdd(personId);
105+
//The container should only fail to add when it is not initially empty
106+
if (initiallyEmpty) {
107+
dataManagerContext.releaseObservationEvent(cellOccupancyEvent);
108+
}
109+
}else {
110+
peopleContainer.unsafeAdd(personId);
111+
}
112+
113+
105114
}
106115
}
107116

117+
private final LabelSet occupancyLabelSet = LabelSet.builder().build();
118+
private final boolean produceCellOccupanceEvents;
119+
private final CellOccupancyEvent cellOccupancyEvent;
120+
121+
122+
108123
@Override
109124
public void attemptPersonRemoval(final PersonId personId) {
110125
peopleContainer.remove(personId);
@@ -172,7 +187,17 @@ public void handleEvent(final Event event) {
172187

173188
if (personId != null) {
174189
if (filter.evaluate(partitionsContext, personId)) {
175-
peopleContainer.safeAdd(personId);
190+
191+
if(produceCellOccupanceEvents) {
192+
boolean initiallyEmpty = peopleContainer.size() == 0;
193+
peopleContainer.safeAdd(personId);
194+
//The container should only fail to add when it is not initially empty
195+
if (initiallyEmpty) {
196+
dataManagerContext.releaseObservationEvent(cellOccupancyEvent);
197+
}
198+
}else {
199+
peopleContainer.safeAdd(personId);
200+
}
176201
} else {
177202
peopleContainer.remove(personId);
178203
}

simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/plugins/partitions/support/Partition.java

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ public Builder setFilter(Filter filter) {
107107
data.filter = filter;
108108
return this;
109109
}
110+
111+
/**
112+
* Sets the policy for the production of CellOccupancyEvent objects during the maintenance of the {@linkplain Partition}. Defaults to false.
113+
*/
114+
public Builder setProduceCellOccupancyEvents(boolean produceCellOccupancyEvents) {
115+
ensureDataMutability();
116+
data.produceCellOccupancyEvents = produceCellOccupancyEvents;
117+
return this;
118+
}
110119

111120
/**
112121
* Set the retention policy for derived partition cell keys for people. Defaults
@@ -164,6 +173,8 @@ private static class Data {
164173
private Map<Object, Labeler> labelers = new LinkedHashMap<>();
165174

166175
private Filter filter;
176+
177+
private boolean produceCellOccupancyEvents;
167178

168179
private boolean locked;
169180

@@ -177,44 +188,36 @@ private Data(Data data) {
177188
locked = data.locked;
178189
}
179190

180-
/**
181-
* Standard implementation consistent with the {@link #equals(Object)} method
182-
*/
183191
@Override
184192
public int hashCode() {
185-
return Objects.hash(retainPersonKeys, labelers, filter);
193+
return Objects.hash(filter, labelers, produceCellOccupancyEvents, retainPersonKeys);
186194
}
187195

188-
/**
189-
* Two {@link Data} instances are equal if and only if
190-
* their inputs are equal.
191-
*/
192196
@Override
193197
public boolean equals(Object obj) {
194198
if (this == obj) {
195199
return true;
196200
}
197-
if (obj == null) {
198-
return false;
199-
}
200-
if (getClass() != obj.getClass()) {
201+
if (!(obj instanceof Data)) {
201202
return false;
202203
}
203204
Data other = (Data) obj;
204-
return retainPersonKeys == other.retainPersonKeys && Objects.equals(labelers, other.labelers)
205-
&& Objects.equals(filter, other.filter);
205+
return Objects.equals(filter, other.filter) && Objects.equals(labelers, other.labelers)
206+
&& produceCellOccupancyEvents == other.produceCellOccupancyEvents
207+
&& retainPersonKeys == other.retainPersonKeys;
206208
}
207209

208210
@Override
209211
public String toString() {
210-
211212
StringBuilder builder = new StringBuilder();
212213
builder.append("Data [filter=");
213214
builder.append(filter);
214215
builder.append(", labelers=");
215216
builder.append(labelers);
216217
builder.append(", retainPersonKeys=");
217218
builder.append(retainPersonKeys);
219+
builder.append(", produceCellOccupancyEvents=");
220+
builder.append(produceCellOccupancyEvents);
218221
builder.append("]");
219222
return builder.toString();
220223
}
@@ -227,6 +230,13 @@ public String toString() {
227230
public Optional<Filter> getFilter() {
228231
return Optional.ofNullable(data.filter);
229232
}
233+
234+
/**
235+
* Returns the policy for producing CellOccupancyEvents.
236+
*/
237+
public boolean produceCellOccupancyEvents() {
238+
return data.produceCellOccupancyEvents;
239+
}
230240

231241
/**
232242
* Returns the collected labelsers. Each labelers will have a unique id.

simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/plugins/partitions/support/PopulationPartition.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,21 @@ public interface PopulationPartition {
103103
* create this population partition. No precondition tests will be performed.
104104
*/
105105
public <T> Optional<T> getPersonValue(LabelSetFunction<T> labelSetFunction, PersonId personId);
106+
107+
108+
// /**
109+
// * Subscribes an actor to PartitionOccupancyEvents associated with the given
110+
// * label set and partition.
111+
// *
112+
// */
113+
// public void subscribeToPartitionOccupancyEvents(final Object key, final LabelSet labelSet);
114+
//
115+
//
116+
// /**
117+
// * Un-subscribes an actor to PartitionOccupancyEvents associated with the given
118+
// * label set and partition.
119+
// */
120+
//
121+
// public void unsubscribeToPartitionOccupancyEvents(final Object key, final LabelSet labelSet);
106122

107123
}

0 commit comments

Comments
 (0)