AddressBook, Customer und Paket sollten komplett vollständig sein.

DeliveryCar zu einem großen Teil gemacht
This commit is contained in:
Egor Rutkowski 2024-05-15 21:12:33 +02:00
parent ab7328301b
commit 08f604be37
6 changed files with 118 additions and 23 deletions

View File

@ -8,14 +8,15 @@ import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive; import akka.actor.typed.javadsl.Receive;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Random;
public class AddressBook extends AbstractBehavior<AddressBook.Message> { public class AddressBook extends AbstractBehavior<AddressBook.Message> {
ArrayList<ActorRef<Customer.Message>> customers; ArrayList<ActorRef<Customer.Message>> customers = new ArrayList<>();
public interface Message {} public interface Message {}
public record CustomerMessage(ActorRef<Customer.Message> fragender, String nameFragender) implements Message{}
//Message, wenn ein Empfänger nach einer Adresse fragt
public record CustomerMessage(ActorRef<Customer.Message> fragender, String nameFragender,ActorRef<DeliveryCar.Message> truckReference) implements Message{}
@Override @Override
public Receive<AddressBook.Message> createReceive() { public Receive<AddressBook.Message> createReceive() {
@ -24,21 +25,30 @@ public class AddressBook extends AbstractBehavior<AddressBook.Message> {
.build(); .build();
} }
//create Methode mit custo = der Liste der Empfänger
public static Behavior<AddressBook.Message> create(ArrayList<ActorRef<Customer.Message>> custo){ public static Behavior<AddressBook.Message> create(ArrayList<ActorRef<Customer.Message>> custo){
return Behaviors.setup(context -> new AddressBook(context, custo)); return Behaviors.setup(context -> new AddressBook(context, custo));
} }
private AddressBook(ActorContext<AddressBook.Message> context, ArrayList<ActorRef<Customer.Message>> actors){ //Konstruktor von dem Adressbuch, in dem auch jedem Customer direkt eine Hello Nachricht geschickt wird, damit diese
//das Adressbuch auch kennen (um nach Empfängern fragen zu können).
private AddressBook(ActorContext<AddressBook.Message> context, ArrayList<ActorRef<Customer.Message>> custo){
super(context); super(context);
customers = actors; if(!custo.isEmpty()){
this.customers.addAll(custo);
for (ActorRef<Customer.Message> cst: this.customers) {
cst.tell(new Customer.AddressHello(getContext().getSelf()));
}
}
} }
//Methode, um einen zufälligen Empfänger auszugeben //Methode, um einen zufälligen Empfänger auszugeben
public Behavior<Message> onCustomerMessage(CustomerMessage msg){ public Behavior<Message> onCustomerMessage(CustomerMessage msg){
Collections.shuffle(customers); Random random = new Random();
var addressOf = customers.get(0); int index = random.nextInt(customers.size());
var addressOf = customers.get(index);
getContext().getLog().info("{} asked for an address",msg.nameFragender); getContext().getLog().info("{} asked for an address",msg.nameFragender);
msg.fragender.tell(new Customer.AddressMessage(addressOf)); msg.fragender.tell(new Customer.AddressMessage(addressOf, msg.truckReference));
return this; return this;
} }
} }

View File

@ -30,10 +30,11 @@ public class AkkaMainSystem extends AbstractBehavior<AkkaMainSystem.Create> {
ActorRef<Customer.Message> a = this.getContext().spawn(Customer.create("Alice"), "alice"); ActorRef<Customer.Message> a = this.getContext().spawn(Customer.create("Alice"), "alice");
ActorRef<Customer.Message> b = this.getContext().spawn(Customer.create("Bob"), "bob"); ActorRef<Customer.Message> b = this.getContext().spawn(Customer.create("Bob"), "bob");
ActorRef<Customer.Message> c = this.getContext().spawn(Customer.create("Charlie"), "charlie"); ActorRef<Customer.Message> c = this.getContext().spawn(Customer.create("Charlie"), "charlie");
ActorRef<Customer.Message> d = this.getContext().spawn(Customer.create("Derik"), "derik");
ActorRef<ExampleTimerActor.Message> timerActor = this.getContext().spawn(ExampleTimerActor.create(), "timeractor"); ActorRef<ExampleTimerActor.Message> timerActor = this.getContext().spawn(ExampleTimerActor.create(), "timeractor");
//#create-actors //#create-actors
ArrayList<ActorRef<Customer.Message>> actors = new ArrayList<>(Arrays.asList(a,b,c)); ArrayList<ActorRef<Customer.Message>> actors = new ArrayList<>(Arrays.asList(a,b,c,d));
ActorRef<AddressBook.Message> adressBook = this.getContext().spawn(AddressBook.create(actors), "addressbook"); ActorRef<AddressBook.Message> addressBook = this.getContext().spawn(AddressBook.create(actors), "addressbook");
return this; return this;
} }
} }

View File

@ -7,19 +7,26 @@ import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors; import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive; import akka.actor.typed.javadsl.Receive;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random; import java.util.Random;
public class Customer extends AbstractBehavior<Customer.Message> { public class Customer extends AbstractBehavior<Customer.Message> {
String name; String name;
String[] gegenstaende = {"Spülmaschine","Altes CD-Regal", "Goldbarren","20kg Hanteln", "Holzkohlegrill","Blumenerde"};
ActorRef<AddressBook.Message> adrBook;
ArrayList<String> gegenstaende = new ArrayList<>(Arrays.asList("Spülmaschine","Altes CD-Regal", "Goldbarren","20kg Hanteln", "Holzkohlegrill","Blumenerde"));
public interface Message {} public interface Message {}
//Delivery Nachricht Typ //Delivery Nachricht Typ
public record DeliveryMessage(Paket paket) implements Message {} public record DeliveryMessage(Paket paket) implements Message {}
//Pickup Nachricht Typ //Pickup Nachricht Typ
public record PickUpMessage(ActorRef<AkkaMainSystem.Create> truckReference, String someString) implements Message {} public record PickUpMessage(ActorRef<DeliveryCar.Message> truckReference, String someString) implements Message {}
public record AddressHello(ActorRef<AddressBook.Message> book) implements Message {}
public record AddressMessage(ActorRef<Customer.Message> addresse, ActorRef<DeliveryCar.Message> truckReference) implements Message {}
private Customer(ActorContext<Message> context, String name){ private Customer(ActorContext<Message> context, String name){
super(context); super(context);
@ -35,26 +42,47 @@ public class Customer extends AbstractBehavior<Customer.Message> {
public Receive<Message> createReceive() { public Receive<Message> createReceive() {
return newReceiveBuilder() return newReceiveBuilder()
.onMessage(DeliveryMessage.class, this::onDeliveryMessage) .onMessage(DeliveryMessage.class, this::onDeliveryMessage)
.onMessage(AddressHello.class, this::onAddressHello)
.onMessage(PickUpMessage.class, this::onPickUpMessage) .onMessage(PickUpMessage.class, this::onPickUpMessage)
.onMessage(AddressMessage.class, this::onAddressMessage)
.build(); .build();
} }
//Hier wird das Adressbuch gespeichert, nachdem es sich gemeldet hat
private Behavior<Message> onAddressHello(AddressHello msg){
this.adrBook = msg.book;
return this;
}
//Verhalten, wenn Pickup Nachricht eingegangen ist //Verhalten, wenn Pickup Nachricht eingegangen ist
//Wenn 80% getroffen wurden, wird eine Anfrage an das Adressbuch geschickt und die Antwort
// an anderer Stelle (onAddressMessage) verarbeitet, um das Paket zu verschicken
private Behavior<Message> onPickUpMessage(PickUpMessage msg){ private Behavior<Message> onPickUpMessage(PickUpMessage msg){
Random random = new Random(); Random random = new Random();
int number = random.nextInt(100); int number = random.nextInt(101);
if(number <= 80){ if(number <= 80){
//TODO: Nachricht an AddressBook schicken //truck wird hier übergeben, damit man im nächsten Schritt wieder auf ihn zugreifen kann.
this.adrBook.tell(new AddressBook.CustomerMessage(getContext().getSelf(), this.name, msg.truckReference));
}else{ }else{
//TODO: PickupResponse an Wagen schicken msg.truckReference.tell(new DeliveryCar.PickupResponse(null));
} }
return this; return this;
} }
//Adresse des Empfängers von dem Adressbuch empfangen und das Paket wird in den Truck geladen und verschickt
private Behavior<Message> onAddressMessage(AddressMessage adr){
Random random = new Random();
int index = random.nextInt(gegenstaende.size());
String gegenstand = gegenstaende.get(index);
Paket paket = new Paket(gegenstand,this.name, adr.addresse);
getContext().getLog().info("Paket mit dem Inhalt {} wurde an {} verschickt", paket.inhalt, adr.addresse.path().name());
adr.truckReference.tell(new DeliveryCar.PickupResponse(paket));
return this;
}
//Verhalten, wenn Paket eingegangen ist //Verhalten, wenn Paket eingegangen ist
private Behavior<Message> onDeliveryMessage(DeliveryMessage pkt){ private Behavior<Message> onDeliveryMessage(DeliveryMessage pkt){
getContext().getLog().info("Ich habe ein Paket von {} erhalten mit dem Inhalt: {}",pkt.paket.inhalt, pkt.paket.absender); getContext().getLog().info("Ich habe ein Paket von {} erhalten mit dem Inhalt: {}", pkt.paket.absender, pkt.paket.inhalt);
return this; return this;
} }
} }

View File

@ -1,12 +1,19 @@
package com.example; package com.example;
import akka.actor.typed.ActorRef; import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Receive; import akka.actor.typed.javadsl.Receive;
import java.util.ArrayList; import java.util.ArrayList;
//TODO: Timer Aktivitäten müssen hinzugefügt werden
//TODO: Delivery Nachricht für den Fall, dass der Truck ein Paket für den Customer hat, bei dem der Truck gerade ist
//Gedanke: Eventuell mit Overseer wie in Blatt 1 arbeiten für das Einhalten der Routen
//TODO: Pickup Nachricht an den Customer, wenn der Truck noch freie Plätze hat
//TODO: Arrive Nachricht
public class DeliveryCar extends AbstractBehavior<DeliveryCar.Message> { public class DeliveryCar extends AbstractBehavior<DeliveryCar.Message> {
ArrayList<Paket> pakete; ArrayList<Paket> pakete;
@ -15,9 +22,12 @@ public class DeliveryCar extends AbstractBehavior<DeliveryCar.Message> {
public record LoadMessage(ArrayList<Paket> pakete) implements Message{} public record LoadMessage(ArrayList<Paket> pakete) implements Message{}
public interface Message {} public interface Message {}
public record PickupResponse(Paket paket) implements Message{}
@Override @Override
public Receive<Message> createReceive() { public Receive<Message> createReceive() {
return newReceiveBuilder().build(); return newReceiveBuilder()
.onMessage(PickupResponse.class, this::onPickupResponse)
.build();
} }
private DeliveryCar(ActorContext<DeliveryCar.Message> context,ArrayList<ActorRef<Customer.Message>> route){ private DeliveryCar(ActorContext<DeliveryCar.Message> context,ArrayList<ActorRef<Customer.Message>> route){
@ -26,4 +36,27 @@ public class DeliveryCar extends AbstractBehavior<DeliveryCar.Message> {
} }
//Pakete aus dem Verteilzentrum einladen
//TODO: Eventuell das losfahren und handlen, zu welchem Empfänger er fahren muss, mit einem Overseer Actor implementieren
public Behavior<DeliveryCar.Message> onLoadMessage(LoadMessage msg){
if(!msg.pakete.isEmpty()){
this.pakete.addAll(msg.pakete);
}
//vielleicht sowas wie in Blatt 1 Lösung mit einem Overseer Actor und dann einem overseer Attribut im Konstruktor
//this.overseer.tell(new Overseer.LoadedMessage()
return this;
}
//Customer gibt PickupResponse entweder mit einem Paket oder ohne eins
//Die Methode kann nur ausgeführt werden, wenn zuvor eine Pickup Nachricht an den Empfänger gesendet wurde und das
//impliziert, dass der Truck noch Platz für weitere Pakete hat
public Behavior<Message> onPickupResponse(PickupResponse rsp){
if(rsp.paket != null){
pakete.add(rsp.paket);
getContext().getLog().info("Aktuelle Anzahl der Pakete im Truck: {}",pakete.size());
}
//TODO: Fall behandeln, dass kein Paket übergeben wurde (wahrscheinlich einfach Timer setzen)
return this;
}
} }

View File

@ -0,0 +1,21 @@
package com.example;
import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Receive;
//TODO: Implementierung dieser Klasse
public class DistributionCenter extends AbstractBehavior<DistributionCenter.Message> {
public DistributionCenter(ActorContext<Message> context) {
super(context);
}
interface Message{}
@Override
public Receive<Message> createReceive() {
return newReceiveBuilder().build();
}
}

View File

@ -1,13 +1,15 @@
package com.example; package com.example;
import akka.actor.typed.ActorRef;
public class Paket { public class Paket {
String inhalt; String inhalt;
String absender; String absender;
Customer empfaenger; ActorRef<Customer.Message> empfaenger;
Paket(String i, String a, Customer e){ Paket(String inhalt, String absender, ActorRef<Customer.Message> empfaenger){
this.inhalt = i; this.inhalt = inhalt;
this.absender = a; this.absender = absender;
this.empfaenger = e; this.empfaenger = empfaenger;
} }
} }