diff --git a/src/main/java/com/example/Actor.java b/src/main/java/com/example/Actor.java index a846e7d..9ad12a2 100644 --- a/src/main/java/com/example/Actor.java +++ b/src/main/java/com/example/Actor.java @@ -1,12 +1,24 @@ package com.example; +import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Behaviors; import akka.actor.typed.javadsl.Receive; +import java.util.Objects; + public class Actor extends AbstractBehavior { + //TODO: Wartezeit bei der Operation + //Zurückgegebener String von der linken Seite + String leftSide; + + //Zurückgegebener String von der rechten Seite + String rightSide; + + //Zeichen für die Operation (Add, Sub, Mul) welche benutzt wird + String operationString; String name; Expression expression; @@ -14,6 +26,12 @@ public class Actor extends AbstractBehavior { public record StartMessage(Expression expression) implements Message{} + //Antwort von dem linken Kind + public record LeftResponse(String string) implements Message{} + + //Antwort von dem rechten Kind + public record RightResponse(String string) implements Message{} + private Actor(ActorContext context, String name){ super(context); this.name = name; @@ -27,15 +45,52 @@ public class Actor extends AbstractBehavior { public Receive createReceive(){ return newReceiveBuilder() .onMessage(StartMessage.class, this::onStartMessage) + .onMessage(LeftResponse.class, this::onLeftResponse) + .onMessage(RightResponse.class, this::onRightResponse) .build(); } private Behavior onStartMessage(StartMessage message){ this.expression = message.expression; - //Wenn initial nur Val übergeben wird -> einfach ausgeben - if(expression instanceof Expression.Val){ - System.out.println(((Expression.Val) expression).inner()); + //Wenn initial nur Val übergeben wird → einfach ausgeben ansonsten UnterActors erstellen + if (Objects.requireNonNull(expression) instanceof Expression.Add add) { + this.operationString = "+"; + ActorRef LeftSubActor = getContext().spawnAnonymous(SubActor.create()); + LeftSubActor.tell(new SubActor.PrintAndEvaluate(getContext().getSelf(),add.left(), true)); + ActorRef RightSubActor = getContext().spawnAnonymous(SubActor.create()); + RightSubActor.tell(new SubActor.PrintAndEvaluate(getContext().getSelf(),add.right(), false)); + } + else if (expression instanceof Expression.Sub sub) { + this.operationString = "-"; + ActorRef LeftSubActor = getContext().spawnAnonymous(SubActor.create()); + LeftSubActor.tell(new SubActor.PrintAndEvaluate(getContext().getSelf(),sub.left(), true)); + ActorRef RightSubActor = getContext().spawnAnonymous(SubActor.create()); + RightSubActor.tell(new SubActor.PrintAndEvaluate(getContext().getSelf(),sub.right(), false)); + } + else if (expression instanceof Expression.Mul mul) { + this.operationString = "*"; + ActorRef LeftSubActor = getContext().spawnAnonymous(SubActor.create()); + LeftSubActor.tell(new SubActor.PrintAndEvaluate(getContext().getSelf(),mul.left(), true)); + ActorRef RightSubActor = getContext().spawnAnonymous(SubActor.create()); + RightSubActor.tell(new SubActor.PrintAndEvaluate(getContext().getSelf(),mul.right(), false)); + } else if (expression instanceof Expression.Val val) { + System.out.println(val.inner()); + } + return this; + } + private Behavior onLeftResponse(LeftResponse response){ + this.leftSide = response.string; + if(this.rightSide != null){ + System.out.println("(" + leftSide + operationString + rightSide + ")"); + } + return this; + } + + private Behavior onRightResponse(RightResponse response){ + this.rightSide = response.string; + if(this.leftSide != null){ + System.out.println("(" + leftSide + operationString + rightSide + ")"); } return this; } diff --git a/src/main/java/com/example/AkkaMainSystem.java b/src/main/java/com/example/AkkaMainSystem.java index d27ef68..a575eec 100644 --- a/src/main/java/com/example/AkkaMainSystem.java +++ b/src/main/java/com/example/AkkaMainSystem.java @@ -26,16 +26,12 @@ public class AkkaMainSystem extends AbstractBehavior { } private Behavior onCreate(Create command) { - //#create-actors - ActorRef a = this.getContext().spawn(ExampleActor.create("Alice"), "alice"); - ActorRef b = this.getContext().spawn(ExampleTimerActor.create(), "timeractor"); - //#create-actors Expression expression = Expression.generateExpression(6, 9); - Expression testExp = Expression.generateExpression(1,9); + Expression testExp = Expression.generateExpression(4,9); ActorRef test = this.getContext().spawn(Actor.create("Seng"), "Sengmann"); test.tell(new Actor.StartMessage(testExp)); - System.out.println(testExp.toString()+ " Wert:" +expression.eval()); + System.out.println("SOLL: "+testExp.toString()+ " Wert:" +testExp.eval()); return this; } } diff --git a/src/main/java/com/example/SubActor.java b/src/main/java/com/example/SubActor.java new file mode 100644 index 0000000..3103216 --- /dev/null +++ b/src/main/java/com/example/SubActor.java @@ -0,0 +1,180 @@ +package com.example; + +import akka.actor.typed.ActorRef; +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.AbstractBehavior; +import akka.actor.typed.javadsl.ActorContext; +import akka.actor.typed.javadsl.Behaviors; +import akka.actor.typed.javadsl.Receive; + +import java.util.Objects; + +public class SubActor extends AbstractBehavior { + //TODO: Wartezeit bei den Operationen + Expression expression; + + //Zeichen für die Operation (Add, Sub, Mul) welche benutzt wird + String operationString; + + //Referenz auf den initialen Actor + ActorRef initial; + + //Referenz auf den (potenziellen) OberSubActor. Es ist immer entweder initial oder oberActor null. + ActorRef oberActor; + + //Linke Seite: true, Rechte Seite: false um zu wissen welche Seite des Ausdrucks berechnet wird. + boolean side; + + //Zurückgegebener String von der linken Seite + String leftSide; + + //Zurückgegebener String von der rechten Seite + String rightSide; + + public interface Message {} + + //Message kommt von dem initialen Actor + public record PrintAndEvaluate(ActorRef sender,Expression expression, Boolean side) implements Message{ } + + //Message kommt von einem anderen SubActor + public record SubPrintAndEvaluate(ActorRef sender,Expression expression, Boolean side) implements Message{ } + + //Antwort von dem linken Kind (TODO: Später Integer hinzufügen wenn mit den Strings alles funktioniert) + public record LeftResponse(String string) implements Message{ } + + //Antwort von dem rechten Kind (TODO: Später Integer hinzufügen wenn mit den Strings alles funktioniert) + public record RightResponse(String string) implements Message{ } + + private SubActor(ActorContext context){ + super(context); + } + + public static Behavior create(){ + return Behaviors.setup(context -> new SubActor(context)); + } + + @Override + public Receive createReceive(){ + return newReceiveBuilder() + .onMessage(PrintAndEvaluate.class, this::onPrintAndEvaluate) + .onMessage(SubPrintAndEvaluate.class, this::onSubPrintAndEvaluate) + .onMessage(LeftResponse.class, this::onLeftResponse) + .onMessage(RightResponse.class, this::onRightResponse) + .build(); + } + + //Die Nachricht von dem initialen Actor wird verarbeitet. + //Dabei wird seine Referenz in @initial gespeichert + public Behavior onPrintAndEvaluate(PrintAndEvaluate message) { + this.initial = message.sender; + this.expression = message.expression; + this.side = message.side; + //Wenn initial nur Val übergeben wird → einfach ausgeben ansonsten UnterActors erstellen + if (Objects.requireNonNull(expression) instanceof Expression.Add add) { + this.operationString = "+"; + ActorRef subActorLeft = getContext().spawnAnonymous(SubActor.create()); + subActorLeft.tell(new SubPrintAndEvaluate(getContext().getSelf(), add.left(), true)); + ActorRef subActorRight = getContext().spawnAnonymous(SubActor.create()); + subActorRight.tell(new SubPrintAndEvaluate(getContext().getSelf(), add.right(), false)); + } else if (expression instanceof Expression.Sub sub) { + this.operationString = "-"; + ActorRef subActorLeft = getContext().spawnAnonymous(SubActor.create()); + subActorLeft.tell(new SubPrintAndEvaluate(getContext().getSelf(),sub.left(), true)); + ActorRef subActorRight = getContext().spawnAnonymous(SubActor.create()); + subActorRight.tell(new SubPrintAndEvaluate(getContext().getSelf(),sub.right(), false)); + } else if (expression instanceof Expression.Mul mul) { + this.operationString = "*"; + ActorRef subActorLeft = getContext().spawnAnonymous(SubActor.create()); + subActorLeft.tell(new SubPrintAndEvaluate(getContext().getSelf(),mul.left(), true)); + ActorRef subActorRight = getContext().spawnAnonymous(SubActor.create()); + subActorRight.tell(new SubPrintAndEvaluate(getContext().getSelf(),mul.right(), false)); + } else if (expression instanceof Expression.Val val) { + if(side == true){ + initial.tell(new Actor.LeftResponse(String.valueOf(val.inner()))); + }else{ + initial.tell(new Actor.RightResponse(String.valueOf(val.inner()))); + } + } + return this; + } + + //Nachricht von einem SubActor wird verarbeitet. + //Dabei wird seine Referenz in oberActor gespeichert. + public Behavior onSubPrintAndEvaluate(SubPrintAndEvaluate message){ + this.oberActor = message.sender; + this.expression = message.expression; + this.side = message.side; + //Wenn initial nur Val übergeben wird → einfach ausgeben ansonsten UnterActors erstellen + if (Objects.requireNonNull(expression) instanceof Expression.Add add) { + this.operationString = "+"; + ActorRef subActorLeft = getContext().spawnAnonymous(SubActor.create()); + subActorLeft.tell(new SubPrintAndEvaluate(getContext().getSelf(),add.left(), true)); + ActorRef subActorRight = getContext().spawnAnonymous(SubActor.create()); + subActorRight.tell(new SubPrintAndEvaluate(getContext().getSelf(),add.right(), false)); + } + else if (expression instanceof Expression.Sub sub) { + this.operationString = "-"; + ActorRef subActorLeft = getContext().spawnAnonymous(SubActor.create()); + subActorLeft.tell(new SubPrintAndEvaluate(getContext().getSelf(),sub.left(), true)); + ActorRef subActorRight = getContext().spawnAnonymous(SubActor.create()); + subActorRight.tell(new SubPrintAndEvaluate(getContext().getSelf(),sub.right(), false)); + } + else if (expression instanceof Expression.Mul mul) { + this.operationString = "*"; + ActorRef subActorLeft = getContext().spawnAnonymous(SubActor.create()); + subActorLeft.tell(new SubPrintAndEvaluate(getContext().getSelf(),mul.left(), true)); + ActorRef subActorRight = getContext().spawnAnonymous(SubActor.create()); + subActorRight.tell(new SubPrintAndEvaluate(getContext().getSelf(),mul.right(), false)); + } else if (expression instanceof Expression.Val val) { + if(side == true){ + oberActor.tell(new SubActor.LeftResponse(String.valueOf(val.inner()))); + }else{ + oberActor.tell(new SubActor.RightResponse(String.valueOf(val.inner()))); + } + } + return this; + } + + public Behavior onLeftResponse(LeftResponse response){ + this.leftSide = response.string; + if(this.rightSide != null){ + if(oberActor != null){ + //side == true bedeutet, dass dieser Actor das linke Kind ist und es wird LeftResponse geschickt + if(side == true){ + oberActor.tell(new SubActor.LeftResponse("(" + leftSide + operationString + rightSide + ")")); + }else { + oberActor.tell(new SubActor.RightResponse("(" + leftSide + operationString + rightSide + ")")); + } + }else{ + if(side == true){ + initial.tell(new Actor.LeftResponse("(" + leftSide + operationString + rightSide + ")")); + }else { + initial.tell(new Actor.RightResponse("(" + leftSide + operationString + rightSide + ")")); + } + } + } + return this; + } + + public Behavior onRightResponse(RightResponse response){ + this.rightSide = response.string; + if(this.leftSide != null){ + if(oberActor != null){ + //side == true bedeutet, dass dieser Actor das linke Kind ist und es wird LeftResponse geschickt + if(side == true){ + oberActor.tell(new SubActor.LeftResponse("(" + leftSide + operationString + rightSide + ")")); + }else { + oberActor.tell(new SubActor.RightResponse("(" + leftSide + operationString + rightSide + ")")); + } + }else { + if(side == true){ + initial.tell(new Actor.LeftResponse("(" + leftSide + operationString + rightSide + ")")); + }else { + initial.tell(new Actor.RightResponse("(" + leftSide + operationString + rightSide + ")")); + } + } + } + return this; + } + +}