Skip to content
This repository has been archived by the owner on Oct 1, 2022. It is now read-only.

Commit

Permalink
Change notification retrieval to use streams instead of iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-eberle committed May 10, 2018
1 parent 4027c57 commit d140c09
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public static Property<Context, Boolean> setIdleBehaviorActiveWhile(boolean valu
}

public static Guard<Context> triggerGuard(Class<? extends Notification> type, Node<Context> child) {
return new Guard<>(entity -> entity.component.getNotificationsIterator(type).hasNext(), true, child);
return new Guard<>(entity -> entity.component.hasNotificationOfType(type), true, child);
}

public static Action<Context> startAnimation(EMovableAction animation, short duration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,26 +156,27 @@ protected Root<Context> createBehaviorTree() {
}

private static Action<Context> accept_SaveDeliveryJob() {
return new Action<>(c -> {
BearerComponent.DeliveryJob job = c.component.getNotificationsIterator(BearerComponent.DeliveryJob.class).next();
job.offer.distributionAccepted();
job.request.deliveryAccepted();
c.entity.bearerC().setDeliveryJob(job);
return new Action<>(context -> {
context.component.forFirstNotificationOfType(BearerComponent.DeliveryJob.class, job -> {
job.offer.distributionAccepted();
job.request.deliveryAccepted();
context.entity.bearerC().setDeliveryJob(job);
});
});
}

private static Action<Context> accept_SaveBecomeSoldierJob() {
return new Action<>(c -> {
BearerComponent.BecomeSoldierJob job = c.component.getNotificationsIterator(BearerComponent.BecomeSoldierJob.class).next();
c.entity.bearerC().setBecomeSoldierJob(job);
return new Action<>(context -> {
context.component.forFirstNotificationOfType(BearerComponent.BecomeSoldierJob.class, context.entity.bearerC()::setBecomeSoldierJob);
});
}

private static Action<Context> accept_SaveBecomeWorkerJob() {
return new Action<>(c -> {
BearerComponent.BecomeWorkerJob job = c.component.getNotificationsIterator(BearerComponent.BecomeWorkerJob.class).next();
job.offer.distributionAccepted();
c.entity.bearerC().setBecomeWorkerJob(job);
return new Action<>(context -> {
context.component.forFirstNotificationOfType(BearerComponent.BecomeWorkerJob.class, job -> {
job.offer.distributionAccepted();
context.entity.bearerC().setBecomeWorkerJob(job);
});
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package jsettlers.logic.movable.components;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import java8.util.Optional;
import java8.util.function.Consumer;
import java8.util.stream.Stream;
import jsettlers.logic.movable.Entity;
import jsettlers.logic.movable.Notification;

import static java8.util.stream.StreamSupport.stream;

public abstract class Component implements Serializable {
private static final long serialVersionUID = -3071296154652495126L;
public Entity entity;
private HashSet<Notification> consumedNotifications = new HashSet<>();
private static final long serialVersionUID = -3071296154652495126L;

public Entity entity;
private HashSet<Notification> consumedNotifications = new HashSet<>();

/**
* Called once when the entity gets enabled for the first time
Expand Down Expand Up @@ -55,67 +58,35 @@ protected void onDisable() {}

protected void onDestroy() {}

public <T extends Notification> List<T> getNotifications(Class<T> type) {
Iterator<T> it = getNotificationsIterator(type);
List<T> result = new ArrayList<T>();
while (it.hasNext()) {
result.add(it.next());
<T extends Notification> Optional<T> getNextNotification(Class<T> type, boolean consume) {
Optional<T> result = getNotificationsOfType(type).findFirst();
if (consume) {
result.ifPresent(this::consumeNotification);
}
return result;
}

public <T extends Notification> T getNextNotification(Class<T> type, boolean consume) {
Iterator<T> it = getNotificationsIterator(type);
T note = it.next();
if (note != null) {
if (consume) { consumeNotification(note); }
}
return null;
public <T extends Notification> boolean hasNotificationOfType(Class<T> type) {
return getNotificationsOfType(type).findAny().isPresent();
}

public <T extends Notification> boolean containsNotification(Class<T> type) {
return getNotificationsIterator(type).hasNext();
public <T extends Notification> boolean hasNotificationOfType(Class<T> type, boolean consume) { // this implementation uses findFirst to guarantee determinism
return getNextNotification(type, consume).isPresent();
}

public <T extends Notification> Iterator<T> getNotificationsIterator(Class<T> type) {
class NotificationIterator implements Iterator<T> {
private T nextItem;
private Iterator<Notification> it = entity.getAllNotifications().iterator();
private boolean consumed = false;

private NotificationIterator() {
findNext();
}

private void findNext() {
consumed = false;
nextItem = null;
while (it.hasNext()) {
Notification n = it.next();
if (type.isInstance(n) && !consumedNotifications.contains(n)) {
nextItem = (T) n;
return;
}
nextItem = null;
}
}

@Override
public boolean hasNext() {
if (consumed) { findNext(); }
return nextItem != null;
}

@Override
public T next() {
consumed = true;
return nextItem;
}
}
return new NotificationIterator();
private <T extends Notification> Stream<T> getNotificationsOfType(Class<T> type) {
//noinspection unchecked
return stream(entity.getAllNotifications())
.parallel()

This comment has been minimized.

Copy link
@michaelzangl

michaelzangl May 10, 2018

Member

How many are you expecting to get? In our cases, it is probably faster to not do any parallel searching - we don't have that many entities and in most cases we find what we are looking for really fast.

.filter(notification -> !consumedNotifications.contains(notification))
.filter(type::isInstance).map(notification -> (T) notification);
}

<T extends Notification> void forFirstNotificationOfType(Class<T> type, Consumer<T> consumer) {
getNotificationsOfType(type).findFirst().ifPresent(consumer);
}

public boolean consumeNotification(Notification notification) {
boolean consumeNotification(Notification notification) {
if (entity.getAllNotifications().contains(notification)) {
consumedNotifications.add(notification);
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package jsettlers.logic.movable.components;

import java8.util.Optional;
import jsettlers.algorithms.path.Path;
import jsettlers.common.map.shapes.HexGridArea;
import jsettlers.common.material.ESearchType;
Expand Down Expand Up @@ -94,7 +95,7 @@ protected Root<Context> createBehaviorTree() {
guard(c -> c.entity.specC().isWorking(), true,
selector(
BehaviorTreeHelper.debug("find a place and work there", memSequence(
Find_GoToWorkablePosition(),
new FindGoToWorkablePosition(),
waitForTargetReachedAndFailIfNotReachable(),
WorkOnPosIfPossible(),
startAnimation(EMovableAction.ACTION1, ACTION1_DURATION),
Expand Down Expand Up @@ -130,16 +131,11 @@ private static Action<Context> WorkOnPosIfPossible() {
);
}

private static Find_GoToWorkablePosition Find_GoToWorkablePosition() {
return new Find_GoToWorkablePosition();
}

private static class Find_GoToWorkablePosition extends Action<Context> {

private static class FindGoToWorkablePosition extends Action<Context> {
private static final long serialVersionUID = -5393050237159114345L;

public Find_GoToWorkablePosition() {
super(Find_GoToWorkablePosition::run);
FindGoToWorkablePosition() {
super(FindGoToWorkablePosition::run);
}

private static ShortPoint2D getCloseWorkablePos(Context c) {
Expand Down Expand Up @@ -196,8 +192,7 @@ public static NodeStatus run(Context c) {
}
}

private static void setTargetWorkPos(Context c) {
PlayerCmdComponent.LeftClickCommand cmd = c.component.getNotificationsIterator(PlayerCmdComponent.LeftClickCommand.class).next();
c.entity.specC().setTargetWorkPos(cmd.pos);
private static void setTargetWorkPos(Context context) {
context.component.forFirstNotificationOfType(PlayerCmdComponent.LeftClickCommand.class, command -> context.entity.specC().setTargetWorkPos(command.pos));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package jsettlers.logic.movable.components;

import java8.util.Optional;
import jsettlers.algorithms.path.Path;
import jsettlers.common.material.ESearchType;
import jsettlers.common.movable.EDirection;
Expand Down Expand Up @@ -109,9 +110,9 @@ private Root<Context> CreateBehaviorTree() {
selector(
BehaviorTreeHelper.debug("if LeavePositionRequest", triggerGuard(LeavePositionRequest.class,
BehaviorTreeHelper.debug("try go in random direction", action(context -> {
LeavePositionRequest note = context.component.getNextNotification(LeavePositionRequest.class, false);
if (note != null && goToRandomDirection(note.sender)) {
context.component.consumeNotification(note);
Optional<LeavePositionRequest> note = context.component.getNextNotification(LeavePositionRequest.class, false);
if (note.isPresent() && goToRandomDirection(note.get().sender)) {
context.component.consumeNotification(note.get());
return NodeStatus.SUCCESS;
}
return NodeStatus.FAILURE;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package jsettlers.logic.movable.simplebehaviortree.nodes;

import java.util.Iterator;

import jsettlers.logic.movable.Context;
import jsettlers.logic.movable.Notification;

Expand All @@ -13,15 +11,6 @@ public NotificationCondition(Class<? extends Notification> type) {
}

public NotificationCondition(Class<? extends Notification> type, boolean consume) {
super((context) -> {
Iterator<? extends Notification> it = context.component.getNotificationsIterator(type);
if (it.hasNext()) {
if (consume) {
context.component.consumeNotification(it.next());
}
return true;
}
return false;
});
super((context) -> context.component.hasNotificationOfType(type, consume));
}
}

0 comments on commit d140c09

Please sign in to comment.