diff --git a/src/main/java/com/example/SubActor.java b/src/main/java/com/example/SubActor.java new file mode 100644 index 0000000..97594ad --- /dev/null +++ b/src/main/java/com/example/SubActor.java @@ -0,0 +1,218 @@ +package com.example; + +import akka.actor.typed.ActorRef; +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.*; + +import java.time.Duration; +import java.util.Objects; + +public class SubActor extends AbstractBehavior { + + + //Timer, um bei den Berechnungen eine Sekunde lang zu warten + TimerScheduler timer; + + 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 & Integer von der linken Seite + String leftString; + int leftInt; + + //Zurückgegebener String & Integer von der rechten Seite + String rightString; + int rightInt; + + 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 + public record LeftResponse(String string, int wert) implements Message{ } + + //Antwort von dem rechten Kind + public record RightResponse(String string, int wert) implements Message{ } + + //Nachricht an sich selbst, um nach einer Sekunde Wartezeit das Ergebnis zu berechnen + public record Compute() implements Message{} + + private SubActor(ActorContext context, TimerScheduler timer){ + super(context); + this.timer = timer; + } + + public static Behavior create(){ + return Behaviors.setup(context -> Behaviors.withTimers(timers -> new SubActor(context,timers))); + } + + @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) + .onMessage(Compute.class, this::onComputeMessage) + .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()), val.inner())); + }else{ + initial.tell(new Actor.RightResponse(String.valueOf(val.inner()), val.inner())); + } + } + return this; + } + + //Nachricht von dem SubActor, von welchem dieser SubActor erstellt wurde, 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()), val.inner())); + }else{ + oberActor.tell(new SubActor.RightResponse(String.valueOf(val.inner()), val.inner())); + } + } + return this; + } + + public Behavior onLeftResponse(LeftResponse response){ + this.leftString = response.string; + this.leftInt = response.wert; + if(this.rightString != null){ + timer.startSingleTimer(new Compute(), Duration.ofSeconds(1)); + } + return this; + } + + public Behavior onRightResponse(RightResponse response){ + this.rightString = response.string; + this.rightInt = response.wert; + if(this.leftString != null){ + timer.startSingleTimer(new Compute(), Duration.ofSeconds(1)); + } + return this; + } + + private Behavior onComputeMessage(Compute response) { + if (oberActor != null) { + //side == true bedeutet, dass dieser Actor das linke Kind ist und es wird LeftResponse geschickt + if (side == true) { + if (operationString.equals("+")) { + oberActor.tell(new LeftResponse("(" + leftString + operationString + rightString + ")", + leftInt + rightInt)); + } else if (operationString.equals("-")) { + oberActor.tell(new LeftResponse("(" + leftString + operationString + rightString + ")", + leftInt - rightInt)); + } else { + oberActor.tell(new LeftResponse("(" + leftString + operationString + rightString + ")", + leftInt * rightInt)); + } + } else { + if (operationString.equals("+")) { + oberActor.tell(new RightResponse("(" + leftString + operationString + rightString + ")", + leftInt + rightInt)); + } else if (operationString.equals("-")) { + oberActor.tell(new RightResponse("(" + leftString + operationString + rightString + ")", + leftInt - rightInt)); + } else { + oberActor.tell(new RightResponse("(" + leftString + operationString + rightString + ")", + leftInt * rightInt)); + } + } + } else { + if (side == true) { + if (operationString.equals("+")) { + initial.tell(new Actor.LeftResponse("(" + leftString + operationString + rightString + ")", + leftInt + rightInt)); + } else if (operationString.equals("-")) { + initial.tell(new Actor.LeftResponse("(" + leftString + operationString + rightString + ")", + leftInt - rightInt)); + } else { + initial.tell(new Actor.LeftResponse("(" + leftString + operationString + rightString + ")", + leftInt * rightInt)); + } + } else { + if (operationString.equals("+")) { + initial.tell(new Actor.RightResponse("(" + leftString + operationString + rightString + ")", + leftInt + rightInt)); + } else if (operationString.equals("-")) { + initial.tell(new Actor.RightResponse("(" + leftString + operationString + rightString + ")", + leftInt - rightInt)); + } else { + initial.tell(new Actor.RightResponse("(" + leftString + operationString + rightString + ")", + leftInt * rightInt)); + } + } + } + return this; + } +}