summaryrefslogtreecommitdiff
path: root/domain
diff options
context:
space:
mode:
authorMike Vink <mike1994vink@gmail.com>2021-08-02 00:11:52 +0200
committerMike Vink <mike1994vink@gmail.com>2021-08-02 00:11:52 +0200
commit6d35c43741f02965f1702c35d7429a1df32ff576 (patch)
tree2550396fca77f7317215e6c101447e9be19e477b /domain
parent82e9d093ae1186646f06f2b1397d6fb75b6bde22 (diff)
feat(battle): UI and Backend Engine setup!
Diffstat (limited to 'domain')
-rw-r--r--domain/build.gradle7
-rw-r--r--domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java3
-rw-r--r--domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java16
-rw-r--r--domain/src/main/java/akkamon/domain/actors/AkkamonNexus.java2
-rw-r--r--domain/src/main/java/akkamon/domain/greeter/AkkaQuickstart.java25
-rw-r--r--domain/src/main/java/akkamon/domain/greeter/Greeter.java77
-rw-r--r--domain/src/main/java/akkamon/domain/greeter/GreeterBot.java35
-rw-r--r--domain/src/main/java/akkamon/domain/greeter/GreeterMain.java44
-rw-r--r--domain/src/main/java/akkamon/domain/iot/ActorHierarchyExperiments.java16
-rw-r--r--domain/src/main/java/akkamon/domain/iot/Device.java106
-rw-r--r--domain/src/main/java/akkamon/domain/iot/DeviceGroup.java117
-rw-r--r--domain/src/main/java/akkamon/domain/iot/DeviceGroupQuery.java128
-rw-r--r--domain/src/main/java/akkamon/domain/iot/DeviceManager.java193
-rw-r--r--domain/src/main/java/akkamon/domain/iot/IotEntryPoint.java9
-rw-r--r--domain/src/main/java/akkamon/domain/iot/IotSupervisor.java31
-rw-r--r--domain/src/main/java/akkamon/domain/iot/refs/Main.java32
-rw-r--r--domain/src/main/java/akkamon/domain/iot/refs/PrintMyActorRefActor.java30
-rw-r--r--domain/src/main/java/akkamon/domain/iot/startstop/MainStartStop.java31
-rw-r--r--domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor1.java35
-rw-r--r--domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor2.java30
-rw-r--r--domain/src/main/java/akkamon/domain/iot/supervision/MainSupervize.java31
-rw-r--r--domain/src/main/java/akkamon/domain/iot/supervision/SupervisedActor.java45
-rw-r--r--domain/src/main/java/akkamon/domain/iot/supervision/SupervisingActor.java36
-rw-r--r--domain/src/main/java/akkamon/domain/model/Factory.java5
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/Mon.java70
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/MonStats.java32
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/abilities/AbilityFactory.java16
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/abilities/AkkamonAbilities.java5
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/abilities/Immunity.java36
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/moves/BodySlam.java36
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/moves/MovesFactory.java11
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/status/AkkamonStatus.java5
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/status/NoStatus.java36
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/status/StatusFactory.java17
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/types/AkkamonTypes.java7
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/types/DragonType.java6
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/types/IceType.java6
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/types/NormalType.java7
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/types/PsychicType.java6
-rw-r--r--domain/src/main/java/akkamon/domain/model/akkamon/types/TypeFactory.java19
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/BattleEngine.java196
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/BattleEvents.java17
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/BattleMessage.java24
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/MonTeam.java17
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/Phases.java10
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/events/BattleEvent.java7
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/events/BattleEventIds.java5
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/events/Introduction.java15
-rw-r--r--domain/src/main/java/akkamon/domain/model/battle/state/BattleState.java18
-rw-r--r--domain/src/test/java/akkamon/domain/iot/DeviceGroupQueryTest.java245
-rw-r--r--domain/src/test/java/akkamon/domain/iot/DeviceTest.java162
-rw-r--r--domain/src/test/java/akkamon/domain/model/MonStatsTest.java40
-rw-r--r--domain/src/test/java/akkamon/domain/model/MonTest.java64
-rw-r--r--domain/src/test/java/akkamon/domain/model/MoveTest.java13
-rw-r--r--domain/src/test/java/akkamon/domain/model/battle/EngineTest.java79
55 files changed, 849 insertions, 1462 deletions
diff --git a/domain/build.gradle b/domain/build.gradle
index efe3079..978d5da 100644
--- a/domain/build.gradle
+++ b/domain/build.gradle
@@ -25,10 +25,17 @@ dependencies {
implementation 'ch.qos.logback:logback-classic:1.2.3'
implementation 'junit:junit:4.12'
+ implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
+ implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
+ implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
+ implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
+ implementation 'org.junit.jupiter:junit-jupiter:5.7.0'
testImplementation "com.typesafe.akka:akka-actor-testkit-typed_${versions.ScalaBinary}"
testImplementation "com.typesafe.akka:akka-stream-testkit_${versions.ScalaBinary}"
+ implementation 'com.google.code.gson:gson:2.8.7'
+
testImplementation 'junit:junit:4.12'
testRuntimeOnly 'junit:junit:4.12'
diff --git a/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java b/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java
index 919d21f..142d063 100644
--- a/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java
+++ b/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java
@@ -1,6 +1,7 @@
package akkamon.domain;
import akka.actor.typed.ActorRef;
+import akkamon.domain.actors.AkkamonBattle;
import akkamon.domain.actors.AkkamonNexus;
import java.util.List;
@@ -25,5 +26,5 @@ public interface AkkamonMessageEngine {
void broadCastHandshakeFail(String requestName, Set<AkkamonNexus.TrainerID> waitingToStartInteraction);
- void broadCastBattleStart(Set<AkkamonNexus.TrainerID> participants);
+ void broadCastBattleStart(AkkamonBattle.BattleCreatedResponse response);
}
diff --git a/domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java b/domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java
index 21c4239..c6cd508 100644
--- a/domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java
+++ b/domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java
@@ -6,19 +6,27 @@ import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive;
+import akkamon.domain.model.battle.BattleEngine;
+import akkamon.domain.model.battle.BattleMessage;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
public class AkkamonBattle extends AbstractBehavior<AkkamonBattle.Command> {
+ private BattleEngine engine;
+
public interface Command { }
public static class BattleCreatedResponse implements AkkamonNexus.Command {
public Set<AkkamonNexus.TrainerID> participants;
+ public Map<AkkamonNexus.TrainerID, BattleMessage> initState;
- public BattleCreatedResponse(Set<AkkamonNexus.TrainerID> participants) {
+ public BattleCreatedResponse(Set<AkkamonNexus.TrainerID> participants,
+ Map<AkkamonNexus.TrainerID, BattleMessage> initialisedState) {
this.participants = participants;
+ this.initState = initialisedState;
}
}
@@ -71,8 +79,12 @@ public class AkkamonBattle extends AbstractBehavior<AkkamonBattle.Command> {
getContext().getLog().info(String.valueOf(needLink));
if (needLink.isEmpty()) {
getContext().getLog().info("Sending Battle Created Response!");
+ this.engine = new BattleEngine(participants);
replyTo.tell(
- new BattleCreatedResponse(participants)
+ new BattleCreatedResponse(
+ participants,
+ engine.initialise()
+ )
);
return inProgress();
} else {
diff --git a/domain/src/main/java/akkamon/domain/actors/AkkamonNexus.java b/domain/src/main/java/akkamon/domain/actors/AkkamonNexus.java
index 17625b7..32acbf1 100644
--- a/domain/src/main/java/akkamon/domain/actors/AkkamonNexus.java
+++ b/domain/src/main/java/akkamon/domain/actors/AkkamonNexus.java
@@ -303,7 +303,7 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> {
private AkkamonNexus onBattleCreatedResponse(AkkamonBattle.BattleCreatedResponse r) {
getContext().getLog().info("Created battle between {} and {}, they should now only be listening to battle commands!");
- messageEngine.broadCastBattleStart(r.participants);
+ messageEngine.broadCastBattleStart(r);
return this;
}
diff --git a/domain/src/main/java/akkamon/domain/greeter/AkkaQuickstart.java b/domain/src/main/java/akkamon/domain/greeter/AkkaQuickstart.java
deleted file mode 100644
index 8b29aae..0000000
--- a/domain/src/main/java/akkamon/domain/greeter/AkkaQuickstart.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package akkamon.domain.greeter;
-
-import akka.actor.typed.ActorSystem;
-
-import java.io.IOException;
-
-public class AkkaQuickstart {
- public static void main(String[] args) {
- //#actor-system
- final ActorSystem<GreeterMain.SayHello> greeterMain = ActorSystem.create(GreeterMain.create(), "helloakka");
- //#actor-system
-
- //#main-send-messages
- greeterMain.tell(new GreeterMain.SayHello("Charles"));
- //#main-send-messages
-
- try {
- System.out.println(">>> Press ENTER to exit <<<");
- System.in.read();
- } catch (IOException ignored) {
- } finally {
- greeterMain.terminate();
- }
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/greeter/Greeter.java b/domain/src/main/java/akkamon/domain/greeter/Greeter.java
deleted file mode 100644
index ea2a948..0000000
--- a/domain/src/main/java/akkamon/domain/greeter/Greeter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package akkamon.domain.greeter;
-
-import akka.actor.typed.ActorRef;
-import akka.actor.typed.Behavior;
-import akka.actor.typed.javadsl.*;
-
-import java.util.Objects;
-
-// #greeter
-public class Greeter extends AbstractBehavior<Greeter.Greet> {
-
- public static final class Greet {
- public final String whom;
- public final ActorRef<Greeted> replyTo;
-
- public Greet(String whom, ActorRef<Greeted> replyTo) {
- this.whom = whom;
- this.replyTo = replyTo;
- }
- }
-
- public static final class Greeted {
- public final String whom;
- public final ActorRef<Greet> from;
-
- public Greeted(String whom, ActorRef<Greet> from) {
- this.whom = whom;
- this.from = from;
- }
-
-// #greeter
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Greeted greeted = (Greeted) o;
- return Objects.equals(whom, greeted.whom) &&
- Objects.equals(from, greeted.from);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(whom, from);
- }
-
- @Override
- public String toString() {
- return "Greeted{" +
- "whom='" + whom + '\'' +
- ", from=" + from +
- '}';
- }
-// #greeter
- }
-
- public static Behavior<Greet> create() {
- return Behaviors.setup(Greeter::new);
- }
-
- private Greeter(ActorContext<Greet> context) {
- super(context);
- }
-
- @Override
- public Receive<Greet> createReceive() {
- return newReceiveBuilder().onMessage(Greet.class, this::onGreet).build();
- }
-
- private Behavior<Greet> onGreet(Greet command) {
- getContext().getLog().info("Hello {}!", command.whom);
- //#greeter-send-message
- command.replyTo.tell(new Greeted(command.whom, getContext().getSelf()));
- //#greeter-send-message
- return this;
- }
-}
-// #greeter
diff --git a/domain/src/main/java/akkamon/domain/greeter/GreeterBot.java b/domain/src/main/java/akkamon/domain/greeter/GreeterBot.java
deleted file mode 100644
index 22fd601..0000000
--- a/domain/src/main/java/akkamon/domain/greeter/GreeterBot.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package akkamon.domain.greeter;
-
-import akka.actor.typed.Behavior;
-import akka.actor.typed.javadsl.*;
-
-public class GreeterBot extends AbstractBehavior<Greeter.Greeted> {
-
- public static Behavior<Greeter.Greeted> create(int max) {
- return Behaviors.setup(context -> new GreeterBot(context, max));
- }
-
- private final int max;
- private int greetingCounter;
-
- private GreeterBot(ActorContext<Greeter.Greeted> context, int max) {
- super(context);
- this.max = max;
- }
-
- @Override
- public Receive<Greeter.Greeted> createReceive() {
- return newReceiveBuilder().onMessage(Greeter.Greeted.class, this::onGreeted).build();
- }
-
- private Behavior<Greeter.Greeted> onGreeted(Greeter.Greeted message) {
- greetingCounter++;
- getContext().getLog().info("Greeting {} for {}", greetingCounter, message.whom);
- if (greetingCounter == max) {
- return Behaviors.stopped();
- } else {
- message.from.tell(new Greeter.Greet(message.whom, getContext().getSelf()));
- return this;
- }
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/greeter/GreeterMain.java b/domain/src/main/java/akkamon/domain/greeter/GreeterMain.java
deleted file mode 100644
index 9180a0e..0000000
--- a/domain/src/main/java/akkamon/domain/greeter/GreeterMain.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package akkamon.domain.greeter;
-
-import akka.actor.typed.ActorRef;
-import akka.actor.typed.Behavior;
-import akka.actor.typed.javadsl.*;
-
-public class GreeterMain extends AbstractBehavior<GreeterMain.SayHello> {
-
- public static class SayHello {
- public final String name;
-
- public SayHello(String name) {
- this.name = name;
- }
- }
-
- private final ActorRef<Greeter.Greet> greeter;
-
- public static Behavior<SayHello> create() {
- return Behaviors.setup(GreeterMain::new);
- }
-
- private GreeterMain(ActorContext<SayHello> context) {
- super(context);
- //#create-actors
- greeter = context.spawn(Greeter.create(), "greeter");
- //#create-actors
- }
-
- @Override
- public Receive<SayHello> createReceive() {
- return newReceiveBuilder().onMessage(SayHello.class, this::onSayHello).build();
- }
-
- private Behavior<SayHello> onSayHello(SayHello command) {
- //#create-actors
- ActorRef<Greeter.Greeted> replyTo =
- getContext().spawn(GreeterBot.create(3), command.name);
- greeter.tell(new Greeter.Greet(command.name, replyTo));
- //#create-actors
- return this;
- }
-}
-
diff --git a/domain/src/main/java/akkamon/domain/iot/ActorHierarchyExperiments.java b/domain/src/main/java/akkamon/domain/iot/ActorHierarchyExperiments.java
deleted file mode 100644
index cba3412..0000000
--- a/domain/src/main/java/akkamon/domain/iot/ActorHierarchyExperiments.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.typed.ActorRef;
-import akka.actor.typed.ActorSystem;
-import akkamon.domain.iot.supervision.MainSupervize;
-
-public class ActorHierarchyExperiments {
- public static void main(String[] args) {
- // ActorRef<String> testSystem = ActorSystem.create(Main.create(), "testSystem");
- // testSystem.tell("start");
- // ActorRef<String> testSystemStartStop = ActorSystem.create(MainStartStop.create(), "test-supervize");
- // testSystemStartStop.tell("start");
- ActorRef<String> testSupervize = ActorSystem.create(MainSupervize.create(), "test-supervize");
- testSupervize.tell("start");
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/Device.java b/domain/src/main/java/akkamon/domain/iot/Device.java
deleted file mode 100644
index c4e63f8..0000000
--- a/domain/src/main/java/akkamon/domain/iot/Device.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.typed.ActorRef;
-import akka.actor.typed.Behavior;
-import akka.actor.typed.PostStop;
-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.Optional;
-
-public class Device extends AbstractBehavior<Device.Command> {
-
- public interface Command {}
-
- public static final class RecordTemperature implements Command {
- final long requestId;
- final double value;
- final ActorRef<TemperatureRecorded> replyTo;
-
- public RecordTemperature(long requestId, double value, ActorRef<TemperatureRecorded> replyTo) {
- this.requestId = requestId;
- this.value = value;
- this.replyTo = replyTo;
- }
- }
-
- public static final class TemperatureRecorded {
- final long requestId;
-
- public TemperatureRecorded(long requestId) {
- this.requestId = requestId;
- }
- }
-
- public static final class ReadTemperature implements Command {
- final long requestId;
- final ActorRef<RespondTemperature> replyTo;
-
- public ReadTemperature(long requestId, ActorRef<RespondTemperature> replyTo) {
- this.requestId = requestId;
- this.replyTo = replyTo;
- }
- }
-
- public static final class RespondTemperature {
- final long requestId;
- final String deviceId;
- final Optional<Double> value;
-
- public RespondTemperature(long requestId, String deviceId, Optional<Double> value) {
- this.requestId = requestId;
- this.deviceId = deviceId;
- this.value = value;
- }
- }
-
- static enum Passivate implements Command {
- INSTANCE
- }
-
- public static Behavior<Command> create(String groupId, String deviceId) {
- return Behaviors.setup(context -> new Device(context, groupId, deviceId));
- }
-
- private final String groupId;
- private final String deviceId;
-
- private Optional<Double> lastTemperatureReading = Optional.empty();
-
- private Device(ActorContext<Command> context, String groupId, String deviceId) {
- super(context);
- this.groupId = groupId;
- this.deviceId = deviceId;
-
- context.getLog().info("Device actor {}-{} started", groupId, deviceId);
- }
-
- @Override
- public Receive<Command> createReceive() {
- return newReceiveBuilder()
- .onMessage(RecordTemperature.class, this::onRecordTemperature)
- .onMessage(ReadTemperature.class, this::onReadTemperature)
- .onMessage(Passivate.class, m -> Behaviors.stopped())
- .onSignal(PostStop.class, signal -> onPostStop())
- .build();
- }
-
- private Behavior<Command> onRecordTemperature(RecordTemperature r) {
- getContext().getLog().info("Recorded temperature reading {} with {}", r.value, r.requestId);
- lastTemperatureReading = Optional.of(r.value);
- r.replyTo.tell(new TemperatureRecorded(r.requestId));
- return this;
- }
-
- private Behavior<Command> onReadTemperature(ReadTemperature r) {
- r.replyTo.tell(new RespondTemperature(r.requestId, deviceId, lastTemperatureReading));
- return this;
- }
-
- private Behavior<Command> onPostStop() {
- getContext().getLog().info("Device actor {}-{} stopped", groupId, deviceId);
- return Behaviors.stopped();
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/DeviceGroup.java b/domain/src/main/java/akkamon/domain/iot/DeviceGroup.java
deleted file mode 100644
index 40e0d7f..0000000
--- a/domain/src/main/java/akkamon/domain/iot/DeviceGroup.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.typed.ActorRef;
-import akka.actor.typed.Behavior;
-import akka.actor.typed.PostStop;
-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.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-
-public class DeviceGroup extends AbstractBehavior<DeviceGroup.Command> {
-
- public interface Command {}
-
- private class DeviceTerminated implements Command {
- public final ActorRef<Device.Command> device;
- public final String groupId;
- public final String deviceId;
-
- DeviceTerminated(ActorRef<Device.Command> device, String groupId, String deviceId) {
- this.device = device;
- this.groupId = groupId;
- this.deviceId = deviceId;
- }
- }
-
- public static Behavior<Command> create(String groupId) {
- return Behaviors.setup(context -> new DeviceGroup(context, groupId));
- }
-
- private final String groupId;
- private final Map<String, ActorRef<Device.Command>> deviceIdToActor = new HashMap<>();
-
- private DeviceGroup(ActorContext<Command> context, String groupId) {
- super(context);
- this.groupId = groupId;
- context.getLog().info("DeviceGroup {} started", groupId);
- }
-
- private DeviceGroup onAllTemperatures(DeviceManager.RequestAllTemperatures r) {
- Map<String, ActorRef<Device.Command>> deviceIdToActorCopy = new HashMap<>(this.deviceIdToActor);
-
- getContext()
- .spawnAnonymous(
- DeviceGroupQuery.create(
- deviceIdToActorCopy, r.requestId, r.replyTo, Duration.ofSeconds(3)
- )
- );
-
- return this;
- }
-
- private DeviceGroup onTrackDevice(DeviceManager.RequestTrackDevice trackMsg) {
- if (this.groupId.equals(trackMsg.groupId)) {
- ActorRef<Device.Command> deviceActor = deviceIdToActor.get(trackMsg.deviceId);
- if (deviceActor != null) {
- trackMsg.replyTo.tell(new DeviceManager.DeviceRegistered(deviceActor));
- } else {
- getContext().getLog().info("Creating device actor for {}", trackMsg.deviceId);
- deviceActor =
- getContext()
- .spawn(Device.create(groupId, trackMsg.deviceId), "device-" + trackMsg.deviceId);
- getContext()
- .watchWith(deviceActor, new DeviceTerminated(deviceActor, groupId, trackMsg.deviceId));
- deviceIdToActor.put(trackMsg.deviceId, deviceActor);
- trackMsg.replyTo.tell(new DeviceManager.DeviceRegistered(deviceActor));
- }
- } else {
- getContext()
- .getLog()
- .warn(
- "Ignoring TrackDevice request for {}. This actor is responsible for {}.",
- groupId,
- this.groupId);
- }
- return this;
- }
-
-
- private DeviceGroup onDeviceList(DeviceManager.RequestDeviceList r) {
- r.replyTo.tell(new DeviceManager.ReplyDeviceList(r.requestId, deviceIdToActor.keySet()));
- return this;
- }
-
- private DeviceGroup onTerminated(DeviceTerminated t) {
- getContext().getLog().info("Device actor for {} has been terminated", t.deviceId);
- deviceIdToActor.remove(t.deviceId);
- return this;
- }
-
- @Override
- public Receive<Command> createReceive() {
- return newReceiveBuilder()
- .onMessage(DeviceManager.RequestTrackDevice.class, this::onTrackDevice)
- .onMessage(
- DeviceManager.RequestDeviceList.class,
- r -> r.groupId.equals(groupId),
- this::onDeviceList)
- .onMessage(DeviceTerminated.class, this::onTerminated)
- .onSignal(PostStop.class, signal -> onPostStop())
- .onMessage(
- DeviceManager.RequestAllTemperatures.class,
- r -> r.groupId.equals(groupId),
- this::onAllTemperatures
- )
- .build();
- }
-
- private DeviceGroup onPostStop() {
- getContext().getLog().info("DeviceGroup {} stopped", groupId);
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/DeviceGroupQuery.java b/domain/src/main/java/akkamon/domain/iot/DeviceGroupQuery.java
deleted file mode 100644
index b04fd23..0000000
--- a/domain/src/main/java/akkamon/domain/iot/DeviceGroupQuery.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.typed.ActorRef;
-import akka.actor.typed.Behavior;
-import akka.actor.typed.javadsl.*;
-
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class DeviceGroupQuery extends AbstractBehavior<DeviceGroupQuery.Command> {
-
-
- public interface Command {}
-
- private static enum CollectionTimeout implements Command {
- INSTANCE
- }
-
- static class WrappedRespondTemperature implements Command {
- final Device.RespondTemperature response;
-
- WrappedRespondTemperature(Device.RespondTemperature response) {
- this.response = response;
- }
- }
-
- private static class DeviceTerminated implements Command {
- final String deviceId;
-
- private DeviceTerminated(String deviceId) {
- this.deviceId = deviceId;
- }
- }
-
- public static Behavior<Command> create(
- Map<String, ActorRef<Device.Command>> deviceIdToActor,
- long requestId,
- ActorRef<DeviceManager.RespondAllTemperatures> requester,
- Duration timeout) {
- return Behaviors.setup(
- context ->
- Behaviors.withTimers(
- timers ->
- new DeviceGroupQuery(
- deviceIdToActor, requestId, requester, timeout, context, timers)));
- }
-
- private final long requestId;
- private final ActorRef<DeviceManager.RespondAllTemperatures> requester;
- private Map<String, DeviceManager.TemperatureReading> repliesSoFar = new HashMap();
- private final Set<String> stillWaiting;
-
- private DeviceGroupQuery(
- Map<String, ActorRef<Device.Command>> deviceIdToActor,
- long requestId,
- ActorRef<DeviceManager.RespondAllTemperatures> requester,
- Duration timeout,
- ActorContext<Command> context,
- TimerScheduler<Command> timers) {
- super(context);
- this.requestId = requestId;
- this.requester = requester;
-
- timers.startSingleTimer(CollectionTimeout.INSTANCE, timeout);
-
- ActorRef<Device.RespondTemperature> respondTemperatureAdapter =
- context.messageAdapter(Device.RespondTemperature.class, WrappedRespondTemperature::new);
-
- for (Map.Entry<String, ActorRef<Device.Command>> entry : deviceIdToActor.entrySet()) {
- context.watchWith(entry.getValue(), new DeviceTerminated(entry.getKey()));
- entry.getValue().tell(new Device.ReadTemperature(0L, respondTemperatureAdapter));
- }
- stillWaiting = new HashSet<>(deviceIdToActor.keySet());
- }
-
-
- @Override
- public Receive<Command> createReceive() {
- return newReceiveBuilder()
- .onMessage(WrappedRespondTemperature.class, this::onRespondTemperature)
- .onMessage(DeviceTerminated.class, this::onDeviceTerminated)
- .onMessage(CollectionTimeout.class, this::onCollectionTimeout)
- .build();
- }
-
- private Behavior<Command> onRespondTemperature(WrappedRespondTemperature r) {
- DeviceManager.TemperatureReading reading =
- r.response
- .value
- .map(v -> (DeviceManager.TemperatureReading) new DeviceManager.Temperature(v))
- .orElse(DeviceManager.TemperatureNotAvailable.INSTANCE);
-
- String deviceId = r.response.deviceId;
- repliesSoFar.put(deviceId, reading);
- stillWaiting.remove(deviceId);
-
- return respondWhenAllCollected();
- }
-
- private Behavior<Command> onDeviceTerminated(DeviceTerminated terminated) {
- if (stillWaiting.contains(terminated.deviceId)) {
- repliesSoFar.put(terminated.deviceId, DeviceManager.DeviceNotAvailable.INSTANCE);
- stillWaiting.remove(terminated.deviceId);
- }
- return respondWhenAllCollected();
- }
-
- private Behavior<Command> onCollectionTimeout(CollectionTimeout timeout) {
- for (String deviceId : stillWaiting) {
- repliesSoFar.put(deviceId, DeviceManager.DeviceTimedOut.INSTANCE);
- }
- stillWaiting.clear();
- return respondWhenAllCollected();
- }
-
- private Behavior<Command> respondWhenAllCollected() {
- if (stillWaiting.isEmpty()) {
- requester.tell(new DeviceManager.RespondAllTemperatures(requestId, repliesSoFar));
- return Behaviors.stopped();
- } else {
- return this;
- }
- }
-
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/DeviceManager.java b/domain/src/main/java/akkamon/domain/iot/DeviceManager.java
deleted file mode 100644
index c0f8b0d..0000000
--- a/domain/src/main/java/akkamon/domain/iot/DeviceManager.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.typed.ActorRef;
-import akka.actor.typed.Behavior;
-import akka.actor.typed.PostStop;
-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.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-public class DeviceManager extends AbstractBehavior<DeviceManager.Command> {
-
- public interface Command {}
-
- public static final class RequestTrackDevice implements DeviceManager.Command, DeviceGroup.Command {
- public final String groupId;
- public final String deviceId;
- public final ActorRef<DeviceRegistered> replyTo;
-
- public RequestTrackDevice(String groupId, String deviceId, ActorRef<DeviceRegistered> replyTo) {
- this.groupId = groupId;
- this.deviceId = deviceId;
- this.replyTo = replyTo;
- }
- }
-
- public static final class DeviceRegistered {
- public final ActorRef<Device.Command> device;
-
- public DeviceRegistered(ActorRef<Device.Command> device) {
- this.device = device;
- }
- }
-
- public static final class RequestDeviceList implements DeviceManager.Command, DeviceGroup.Command {
- final long requestId;
- final String groupId;
- final ActorRef<ReplyDeviceList> replyTo;
-
- public RequestDeviceList(long requestId, String groupId, ActorRef<ReplyDeviceList> replyTo) {
- this.requestId = requestId;
- this.groupId = groupId;
- this.replyTo = replyTo;
- }
- }
-
- public static final class ReplyDeviceList {
- final long requestId;
- final Set<String> ids;
-
- public ReplyDeviceList(long requestId, Set<String> ids) {
- this.requestId = requestId;
- this.ids = ids;
- }
- }
-
- private static class DeviceGroupTerminated implements DeviceManager.Command {
- public final String groupId;
-
- DeviceGroupTerminated(String groupId) {
- this.groupId = groupId;
- }
- }
-
- public static final class RequestAllTemperatures implements DeviceGroupQuery.Command, DeviceGroup.Command, Command {
-
- final long requestId;
- final String groupId;
- final ActorRef<RespondAllTemperatures> replyTo;
-
- public RequestAllTemperatures(
- long requestId, String groupId, ActorRef<RespondAllTemperatures> replyTo) {
- this.requestId = requestId;
- this.groupId = groupId;
- this.replyTo = replyTo;
- }
- }
-
- public static final class RespondAllTemperatures {
- final long requestId;
- final Map<String, TemperatureReading> temperatures;
-
- public RespondAllTemperatures(long requestId, Map<String, TemperatureReading> temperatures) {
- this.requestId = requestId;
- this.temperatures = temperatures;
- }
- }
-
- public interface TemperatureReading {}
-
- public static final class Temperature implements TemperatureReading {
- public final double value;
-
- public Temperature(double value) {
- this.value = value;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Temperature that = (Temperature) o;
-
- return Double.compare(that.value, value) == 0;
- }
-
- @Override
- public int hashCode() {
- long temp = Double.doubleToLongBits(value);
- return (int) (temp ^ (temp >>> 32));
- }
-
- @Override
- public String toString() {
- return "Temperature{" + "value=" + value + '}';
- }
- }
-
- public enum TemperatureNotAvailable implements TemperatureReading {
- INSTANCE
- }
-
- public enum DeviceNotAvailable implements TemperatureReading {
- INSTANCE
- }
-
- public enum DeviceTimedOut implements TemperatureReading {
- INSTANCE
- }
-
- public static Behavior<Command> create() {
- return Behaviors.setup(DeviceManager::new);
- }
-
- private final Map<String, ActorRef<DeviceGroup.Command>> groupIdToActor = new HashMap<>();
-
- private DeviceManager(ActorContext<Command> context) {
- super(context);
- context.getLog().info("DeviceManager started");
- }
-
- public Receive<Command> createReceive() {
- return newReceiveBuilder()
- .onMessage(RequestTrackDevice.class, this::onTrackDevice)
- .onMessage(RequestDeviceList.class, this::onRequestDeviceList)
- .onMessage(DeviceGroupTerminated.class, this::onTerminated)
- .onSignal(PostStop.class, signal -> onPostStop())
- .build();
- }
-
- private DeviceManager onTrackDevice(RequestTrackDevice trackMsg) {
- String groupId = trackMsg.groupId;
- ActorRef<DeviceGroup.Command> ref = groupIdToActor.get(groupId);
- if (ref != null) {
- ref.tell(trackMsg);
- } else {
- getContext().getLog().info("Creating device group actor for {}", groupId);
- ActorRef<DeviceGroup.Command> groupActor =
- getContext().spawn(DeviceGroup.create(groupId), "group-" + groupId);
- getContext().watchWith(groupActor, new DeviceGroupTerminated(groupId));
- groupActor.tell(trackMsg);
- groupIdToActor.put(groupId, groupActor);
- }
- return this;
- }
-
- private DeviceManager onRequestDeviceList(RequestDeviceList request) {
- ActorRef<DeviceGroup.Command> ref = groupIdToActor.get(request.groupId);
- if (ref != null) {
- ref.tell(request);
- } else {
- request.replyTo.tell(new ReplyDeviceList(request.requestId, Collections.emptySet()));
- }
- return this;
- }
-
- private DeviceManager onTerminated(DeviceGroupTerminated t) {
- getContext().getLog().info("Device group actor for {} has been terminated", t.groupId);
- groupIdToActor.remove(t.groupId);
- return this;
- }
-
- private DeviceManager onPostStop() {
- getContext().getLog().info("DeviceManager stopped");
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/IotEntryPoint.java b/domain/src/main/java/akkamon/domain/iot/IotEntryPoint.java
deleted file mode 100644
index e8faf9d..0000000
--- a/domain/src/main/java/akkamon/domain/iot/IotEntryPoint.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.typed.ActorSystem;
-
-public class IotEntryPoint {
- public static void main(String[] args) {
- ActorSystem.create(IotSupervisor.create(), "iot-system");
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/IotSupervisor.java b/domain/src/main/java/akkamon/domain/iot/IotSupervisor.java
deleted file mode 100644
index dc50929..0000000
--- a/domain/src/main/java/akkamon/domain/iot/IotSupervisor.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.typed.Behavior;
-import akka.actor.typed.PostStop;
-import akka.actor.typed.javadsl.AbstractBehavior;
-import akka.actor.typed.javadsl.ActorContext;
-import akka.actor.typed.javadsl.Behaviors;
-import akka.actor.typed.javadsl.Receive;
-
-public class IotSupervisor extends AbstractBehavior<Void> {
-
- public static Behavior<Void> create() {
- return Behaviors.setup(IotSupervisor::new);
- }
-
- private IotSupervisor(ActorContext<Void> context) {
- super(context);
- context.getLog().info("IoT Application started");
- }
-
- // No need to handle any messages
- @Override
- public Receive<Void> createReceive() {
- return newReceiveBuilder().onSignal(PostStop.class, signal -> onPostStop()).build();
- }
-
- private IotSupervisor onPostStop() {
- getContext().getLog().info("IoT Application stopped");
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/refs/Main.java b/domain/src/main/java/akkamon/domain/iot/refs/Main.java
deleted file mode 100644
index 923d505..0000000
--- a/domain/src/main/java/akkamon/domain/iot/refs/Main.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package akkamon.domain.iot.refs;
-
-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;
-
-class Main extends AbstractBehavior<String> {
-
- static Behavior<String> create() {
- return Behaviors.setup(Main::new);
- }
-
- private Main(ActorContext<String> context) {
- super(context);
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder().onMessageEquals("start", this::start).build();
- }
-
- private Behavior<String> start() {
- ActorRef<String> firstRef = getContext().spawn(PrintMyActorRefActor.create(), "first-actor");
-
- System.out.println("First: " + firstRef);
- firstRef.tell("printit");
- return Behaviors.same();
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/refs/PrintMyActorRefActor.java b/domain/src/main/java/akkamon/domain/iot/refs/PrintMyActorRefActor.java
deleted file mode 100644
index 76b5c42..0000000
--- a/domain/src/main/java/akkamon/domain/iot/refs/PrintMyActorRefActor.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package akkamon.domain.iot.refs;
-
-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;
-
-class PrintMyActorRefActor extends AbstractBehavior<String> {
-
- static Behavior<String> create() {
- return Behaviors.setup(PrintMyActorRefActor::new);
- }
-
- private PrintMyActorRefActor(ActorContext<String> context) {
- super(context);
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder().onMessageEquals("printit", this::printIt).build();
- }
-
- private Behavior<String> printIt() {
- ActorRef<String> secondRef = getContext().spawn(Behaviors.empty(), "second-actor");
- System.out.println("Second: " + secondRef);
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/startstop/MainStartStop.java b/domain/src/main/java/akkamon/domain/iot/startstop/MainStartStop.java
deleted file mode 100644
index d8f13be..0000000
--- a/domain/src/main/java/akkamon/domain/iot/startstop/MainStartStop.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package akkamon.domain.iot.startstop;
-
-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;
-
-public class MainStartStop extends AbstractBehavior<String> {
-
- static Behavior<String> create() {
- return Behaviors.setup(MainStartStop::new);
- }
-
- private MainStartStop(ActorContext<String> context) {
- super(context);
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder().onMessageEquals("start", this::start).build();
- }
-
- private Behavior<String> start() {
- ActorRef<String> first = getContext().spawn(StartStopActor1.create(), "first");
- first.tell("stop");
- return Behaviors.same();
- }
-
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor1.java b/domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor1.java
deleted file mode 100644
index 37c8237..0000000
--- a/domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor1.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package akkamon.domain.iot.startstop;
-
-import akka.actor.typed.Behavior;
-import akka.actor.typed.PostStop;
-import akka.actor.typed.javadsl.AbstractBehavior;
-import akka.actor.typed.javadsl.ActorContext;
-import akka.actor.typed.javadsl.Behaviors;
-import akka.actor.typed.javadsl.Receive;
-
-class StartStopActor1 extends AbstractBehavior<String> {
-
- static Behavior<String> create() {
- return Behaviors.setup(StartStopActor1::new);
- }
-
- private StartStopActor1(ActorContext<String> context) {
- super(context);
- System.out.println("first started");
-
- context.spawn(StartStopActor2.create(), "second");
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder()
- .onMessageEquals("stop", Behaviors::stopped)
- .onSignal(PostStop.class, signal -> onPostStop())
- .build();
- }
-
- private Behavior<String> onPostStop() {
- System.out.println("first stopped");
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor2.java b/domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor2.java
deleted file mode 100644
index 28d01cf..0000000
--- a/domain/src/main/java/akkamon/domain/iot/startstop/StartStopActor2.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package akkamon.domain.iot.startstop;
-
-import akka.actor.typed.Behavior;
-import akka.actor.typed.PostStop;
-import akka.actor.typed.javadsl.AbstractBehavior;
-import akka.actor.typed.javadsl.ActorContext;
-import akka.actor.typed.javadsl.Behaviors;
-import akka.actor.typed.javadsl.Receive;
-
-class StartStopActor2 extends AbstractBehavior<String> {
-
- static Behavior<String> create() {
- return Behaviors.setup(StartStopActor2::new);
- }
-
- private StartStopActor2(ActorContext<String> context) {
- super(context);
- System.out.println("second started");
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder().onSignal(PostStop.class, signal -> onPostStop()).build();
- }
-
- private Behavior<String> onPostStop() {
- System.out.println("second stopped");
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/supervision/MainSupervize.java b/domain/src/main/java/akkamon/domain/iot/supervision/MainSupervize.java
deleted file mode 100644
index 294245f..0000000
--- a/domain/src/main/java/akkamon/domain/iot/supervision/MainSupervize.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package akkamon.domain.iot.supervision;
-
-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;
-
-public class MainSupervize extends AbstractBehavior<String> {
-
- public static Behavior<String> create() {
- return Behaviors.setup(MainSupervize::new);
- }
-
- private MainSupervize(ActorContext<String> context) {
- super(context);
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder().onMessageEquals("start", this::start).build();
- }
-
- private Behavior<String> start() {
- ActorRef<String> supervisingActor = getContext().spawn(SupervisingActor.create(), "supervising-actor");
- supervisingActor.tell("failChild");
- return Behaviors.same();
- }
-
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/supervision/SupervisedActor.java b/domain/src/main/java/akkamon/domain/iot/supervision/SupervisedActor.java
deleted file mode 100644
index a050cfe..0000000
--- a/domain/src/main/java/akkamon/domain/iot/supervision/SupervisedActor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package akkamon.domain.iot.supervision;
-
-import akka.actor.typed.Behavior;
-import akka.actor.typed.PostStop;
-import akka.actor.typed.PreRestart;
-import akka.actor.typed.javadsl.AbstractBehavior;
-import akka.actor.typed.javadsl.ActorContext;
-import akka.actor.typed.javadsl.Behaviors;
-import akka.actor.typed.javadsl.Receive;
-
-class SupervisedActor extends AbstractBehavior<String> {
-
- static Behavior<String> create() {
- return Behaviors.setup(SupervisedActor::new);
- }
-
- private SupervisedActor(ActorContext<String> context) {
- super(context);
- System.out.println("supervised actor started");
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder()
- .onMessageEquals("fail", this::fail)
- .onSignal(PreRestart.class, signal -> preRestart())
- .onSignal(PostStop.class, signal -> postStop())
- .build();
- }
-
- private Behavior<String> fail() {
- System.out.println("supervised actor fails now");
- throw new RuntimeException("I failed!");
- }
-
- private Behavior<String> preRestart() {
- System.out.println("supervised will be restarted");
- return this;
- }
-
- private Behavior<String> postStop() {
- System.out.println("supervised stopped");
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/iot/supervision/SupervisingActor.java b/domain/src/main/java/akkamon/domain/iot/supervision/SupervisingActor.java
deleted file mode 100644
index f1e098b..0000000
--- a/domain/src/main/java/akkamon/domain/iot/supervision/SupervisingActor.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package akkamon.domain.iot.supervision;
-
-import akka.actor.typed.SupervisorStrategy;
-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;
-
-class SupervisingActor extends AbstractBehavior<String> {
-
- static Behavior<String> create() {
- return Behaviors.setup(SupervisingActor::new);
- }
-
- private final ActorRef<String> child;
-
- private SupervisingActor(ActorContext<String> context) {
- super(context);
- child =
- context.spawn(
- Behaviors.supervise(SupervisedActor.create()).onFailure(SupervisorStrategy.restart()),
- "supervised-actor");
- }
-
- @Override
- public Receive<String> createReceive() {
- return newReceiveBuilder().onMessageEquals("failChild", this::onFailChild).build();
- }
-
- private Behavior<String> onFailChild() {
- child.tell("fail");
- return this;
- }
-}
diff --git a/domain/src/main/java/akkamon/domain/model/Factory.java b/domain/src/main/java/akkamon/domain/model/Factory.java
new file mode 100644
index 0000000..a00ff11
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/Factory.java
@@ -0,0 +1,5 @@
+package akkamon.domain.model;
+
+public interface Factory<T, E> {
+ T fromName(E name);
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/Mon.java b/domain/src/main/java/akkamon/domain/model/akkamon/Mon.java
new file mode 100644
index 0000000..66a6e27
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/Mon.java
@@ -0,0 +1,70 @@
+package akkamon.domain.model.akkamon;
+
+import akkamon.domain.model.akkamon.abilities.AbilityFactory;
+import akkamon.domain.model.akkamon.abilities.AkkamonAbilities;
+import akkamon.domain.model.akkamon.moves.MovesFactory;
+import akkamon.domain.model.akkamon.status.AkkamonStatus;
+import akkamon.domain.model.akkamon.status.StatusFactory;
+import akkamon.domain.model.akkamon.types.AkkamonTypes;
+import akkamon.domain.model.akkamon.types.TypeFactory;
+import akkamon.domain.model.battle.Phases;
+
+import java.util.Map;
+import java.util.Objects;
+
+public class Mon {
+
+ public static abstract class TypeEquality {
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ else return true;
+ }
+ }
+
+ public static abstract class Type extends TypeEquality {
+ }
+
+ public static abstract class Ability extends TypeEquality implements Phases {
+
+ }
+
+ public static abstract class Status extends TypeEquality implements Phases {
+
+ }
+
+ public static abstract class Move implements Phases {
+ }
+
+ private String name;
+ private MonStats stats;
+ private Type type;
+ private Ability ability;
+ private Status status;
+ private Map<String, Move> moves;
+
+ public Mon(String name, MonStats stats, AkkamonTypes typeName, AkkamonAbilities abilityName, AkkamonStatus statusName, String[] moveNames) {
+ this.name = name;
+ this.stats = stats;
+ this.type = new TypeFactory().fromName(typeName);
+ this.ability = new AbilityFactory().fromName(abilityName);
+ this.status = new StatusFactory().fromName(statusName);
+ this.moves = new MovesFactory().fromNames(moveNames);
+ }
+
+
+ public String getName() { return name; }
+ public Type getType() {
+ return type;
+ }
+
+ public Ability getAbility() {
+ return ability;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/MonStats.java b/domain/src/main/java/akkamon/domain/model/akkamon/MonStats.java
new file mode 100644
index 0000000..ee4eee3
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/MonStats.java
@@ -0,0 +1,32 @@
+package akkamon.domain.model.akkamon;
+
+public class MonStats {
+ public final int HP;
+ public final int Attack;
+ public final int Defence;
+ public final int SpecialAttack;
+ public final int SpecialDefence;
+ public final int Speed;
+ public final int accuracy = 1;
+ public final int evasion = 1;
+
+ public MonStats(int[] base, int[] evs, int[] ivs, double[] natureMultiplier, int level) {
+ this.HP = setHP(base[0], evs[0], ivs[0], level);
+ this.Attack = setStat(base[1], evs[1], ivs[1], natureMultiplier[1], level);
+ this.Defence = setStat(base[2], evs[2], ivs[2], natureMultiplier[2], level);
+ this.SpecialAttack = setStat(base[3], evs[3], ivs[3], natureMultiplier[3], level);
+ this.SpecialDefence = setStat(base[4], evs[4], ivs[4], natureMultiplier[4], level);
+ this.Speed = setStat(base[5], evs[5], ivs[5], natureMultiplier[5], level);
+ }
+
+ private int setStat(int base, int ev, int iv, double nature, int level) {
+ double firstTerm = ( ( 2 * base + iv + (ev / 4.0) ) * level / 100 ) + 5;
+ return (int) (firstTerm * nature);
+ }
+
+ private int setHP(int base, int ev, int iv, int level) {
+ double firstTerm = (2 * base + iv + (ev / 4.0)) * level / 100;
+ return (int) (firstTerm + level + 10);
+ }
+
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/abilities/AbilityFactory.java b/domain/src/main/java/akkamon/domain/model/akkamon/abilities/AbilityFactory.java
new file mode 100644
index 0000000..73cfe1d
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/abilities/AbilityFactory.java
@@ -0,0 +1,16 @@
+package akkamon.domain.model.akkamon.abilities;
+
+import akkamon.domain.model.Factory;
+import akkamon.domain.model.akkamon.Mon;
+
+public class AbilityFactory implements Factory<Mon.Ability, AkkamonAbilities> {
+ @Override
+ public Mon.Ability fromName(AkkamonAbilities name) {
+ switch (name) {
+ case IMMUNITY:
+ return new Immunity();
+ default:
+ return null;
+ }
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/abilities/AkkamonAbilities.java b/domain/src/main/java/akkamon/domain/model/akkamon/abilities/AkkamonAbilities.java
new file mode 100644
index 0000000..d879d4e
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/abilities/AkkamonAbilities.java
@@ -0,0 +1,5 @@
+package akkamon.domain.model.akkamon.abilities;
+
+public enum AkkamonAbilities {
+ SYNCHRONIZE, PRESSURE, INNER_FOCUS, IMMUNITY
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/abilities/Immunity.java b/domain/src/main/java/akkamon/domain/model/akkamon/abilities/Immunity.java
new file mode 100644
index 0000000..c82889e
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/abilities/Immunity.java
@@ -0,0 +1,36 @@
+package akkamon.domain.model.akkamon.abilities;
+
+import akkamon.domain.model.akkamon.Mon;
+
+public class Immunity extends Mon.Ability {
+
+ @Override
+ public void startTurn() {
+
+ }
+
+ @Override
+ public void fight() {
+
+ }
+
+ @Override
+ public void getAttacked() {
+
+ }
+
+ @Override
+ public void useItem() {
+
+ }
+
+ @Override
+ public void switchOut() {
+
+ }
+
+ @Override
+ public void endTurn() {
+
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/moves/BodySlam.java b/domain/src/main/java/akkamon/domain/model/akkamon/moves/BodySlam.java
new file mode 100644
index 0000000..8fd686c
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/moves/BodySlam.java
@@ -0,0 +1,36 @@
+package akkamon.domain.model.akkamon.moves;
+
+import akkamon.domain.model.akkamon.Mon;
+
+public class BodySlam extends Mon.Move {
+
+ @Override
+ public void startTurn() {
+
+ }
+
+ @Override
+ public void fight() {
+
+ }
+
+ @Override
+ public void getAttacked() {
+
+ }
+
+ @Override
+ public void useItem() {
+
+ }
+
+ @Override
+ public void switchOut() {
+
+ }
+
+ @Override
+ public void endTurn() {
+
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/moves/MovesFactory.java b/domain/src/main/java/akkamon/domain/model/akkamon/moves/MovesFactory.java
new file mode 100644
index 0000000..63f6784
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/moves/MovesFactory.java
@@ -0,0 +1,11 @@
+package akkamon.domain.model.akkamon.moves;
+
+import akkamon.domain.model.akkamon.Mon;
+
+import java.util.Map;
+
+public class MovesFactory {
+ public Map<String, Mon.Move> fromNames(String[] names) {
+ return null;
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/status/AkkamonStatus.java b/domain/src/main/java/akkamon/domain/model/akkamon/status/AkkamonStatus.java
new file mode 100644
index 0000000..379b9b8
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/status/AkkamonStatus.java
@@ -0,0 +1,5 @@
+package akkamon.domain.model.akkamon.status;
+
+public enum AkkamonStatus {
+ NONE
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/status/NoStatus.java b/domain/src/main/java/akkamon/domain/model/akkamon/status/NoStatus.java
new file mode 100644
index 0000000..fe3c649
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/status/NoStatus.java
@@ -0,0 +1,36 @@
+package akkamon.domain.model.akkamon.status;
+
+import akkamon.domain.model.akkamon.Mon;
+
+public class NoStatus extends Mon.Status {
+
+ @Override
+ public void startTurn() {
+
+ }
+
+ @Override
+ public void fight() {
+
+ }
+
+ @Override
+ public void getAttacked() {
+
+ }
+
+ @Override
+ public void useItem() {
+
+ }
+
+ @Override
+ public void switchOut() {
+
+ }
+
+ @Override
+ public void endTurn() {
+
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/status/StatusFactory.java b/domain/src/main/java/akkamon/domain/model/akkamon/status/StatusFactory.java
new file mode 100644
index 0000000..b5897d0
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/status/StatusFactory.java
@@ -0,0 +1,17 @@
+package akkamon.domain.model.akkamon.status;
+
+import akkamon.domain.model.Factory;
+import akkamon.domain.model.akkamon.Mon;
+
+public class StatusFactory implements Factory<Mon.Status, AkkamonStatus> {
+
+ @Override
+ public Mon.Status fromName(AkkamonStatus name) {
+ switch (name) {
+ case NONE:
+ return new NoStatus();
+ default:
+ return null;
+ }
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/types/AkkamonTypes.java b/domain/src/main/java/akkamon/domain/model/akkamon/types/AkkamonTypes.java
new file mode 100644
index 0000000..a8402d4
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/types/AkkamonTypes.java
@@ -0,0 +1,7 @@
+package akkamon.domain.model.akkamon.types;
+
+public enum AkkamonTypes {
+ NORMAL,
+ DRAGON,
+ PSYCHIC
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/types/DragonType.java b/domain/src/main/java/akkamon/domain/model/akkamon/types/DragonType.java
new file mode 100644
index 0000000..dcf5daa
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/types/DragonType.java
@@ -0,0 +1,6 @@
+package akkamon.domain.model.akkamon.types;
+
+import akkamon.domain.model.akkamon.Mon;
+
+public class DragonType extends Mon.Type {
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/types/IceType.java b/domain/src/main/java/akkamon/domain/model/akkamon/types/IceType.java
new file mode 100644
index 0000000..5d83935
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/types/IceType.java
@@ -0,0 +1,6 @@
+package akkamon.domain.model.akkamon.types;
+
+import akkamon.domain.model.akkamon.Mon;
+
+public class IceType extends Mon.Type {
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/types/NormalType.java b/domain/src/main/java/akkamon/domain/model/akkamon/types/NormalType.java
new file mode 100644
index 0000000..4c5f845
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/types/NormalType.java
@@ -0,0 +1,7 @@
+package akkamon.domain.model.akkamon.types;
+
+import akkamon.domain.model.akkamon.Mon;
+
+public class NormalType extends Mon.Type {
+
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/types/PsychicType.java b/domain/src/main/java/akkamon/domain/model/akkamon/types/PsychicType.java
new file mode 100644
index 0000000..6a46568
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/types/PsychicType.java
@@ -0,0 +1,6 @@
+package akkamon.domain.model.akkamon.types;
+
+import akkamon.domain.model.akkamon.Mon;
+
+public class PsychicType extends Mon.Type {
+}
diff --git a/domain/src/main/java/akkamon/domain/model/akkamon/types/TypeFactory.java b/domain/src/main/java/akkamon/domain/model/akkamon/types/TypeFactory.java
new file mode 100644
index 0000000..34f0082
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/akkamon/types/TypeFactory.java
@@ -0,0 +1,19 @@
+package akkamon.domain.model.akkamon.types;
+
+import akkamon.domain.model.Factory;
+import akkamon.domain.model.akkamon.Mon;
+
+public class TypeFactory implements Factory<Mon.Type, AkkamonTypes> {
+ public Mon.Type fromName(AkkamonTypes type) {
+ switch (type) {
+ case NORMAL:
+ return new NormalType();
+ case DRAGON:
+ return new DragonType();
+ case PSYCHIC:
+ return new PsychicType();
+ default:
+ return null;
+ }
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/BattleEngine.java b/domain/src/main/java/akkamon/domain/model/battle/BattleEngine.java
new file mode 100644
index 0000000..5c78695
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/BattleEngine.java
@@ -0,0 +1,196 @@
+package akkamon.domain.model.battle;
+
+import akkamon.domain.actors.AkkamonNexus;
+import akkamon.domain.model.akkamon.Mon;
+import akkamon.domain.model.akkamon.MonStats;
+import akkamon.domain.model.akkamon.abilities.AkkamonAbilities;
+import akkamon.domain.model.akkamon.status.AkkamonStatus;
+import akkamon.domain.model.akkamon.types.AkkamonTypes;
+import akkamon.domain.model.battle.events.Introduction;
+import akkamon.domain.model.battle.state.BattleState;
+
+import java.util.*;
+
+public class BattleEngine {
+
+ private final Map<AkkamonNexus.TrainerID, List<AkkamonNexus.TrainerID>> trainerIDToOpponents = new HashMap<>();
+ private final BattleEvents events;
+ private final BattleState state;
+
+ public BattleEngine(Set<AkkamonNexus.TrainerID> participants) {
+
+ Random random = new Random();
+ List<MonTeam> demoTeams = createDemoTeams();
+ Map<AkkamonNexus.TrainerID, MonTeam> trainerIDtoTeam = new HashMap<>();
+
+ for (AkkamonNexus.TrainerID trainerID : participants) {
+ trainerIDtoTeam.put(trainerID, demoTeams.remove(random.nextInt(demoTeams.size())));
+
+ List<AkkamonNexus.TrainerID> opponents = new ArrayList<>(participants);
+
+ opponents.remove(trainerID);
+ trainerIDToOpponents.put(trainerID, opponents);
+ }
+
+ this.events = new BattleEvents(participants);
+ this.state = new BattleState(trainerIDtoTeam);
+
+ }
+
+ public Map<AkkamonNexus.TrainerID, List<AkkamonNexus.TrainerID>> getTrainerIDToOpponents() {
+ return trainerIDToOpponents;
+ }
+
+ public BattleEvents getEvents() {
+ return events;
+ }
+
+ public BattleState getState() {
+ return state;
+ }
+
+ public Map<AkkamonNexus.TrainerID, BattleMessage> initialise() {
+ for (AkkamonNexus.TrainerID trainerID : trainerIDToOpponents.keySet()) {
+ this.events.trainerIDEventMap.get(trainerID).add(
+ new Introduction(
+ )
+ );
+ }
+ return bundleEventsAndState();
+ }
+
+ private Map<AkkamonNexus.TrainerID, BattleMessage> bundleEventsAndState() {
+ Map<AkkamonNexus.TrainerID, BattleMessage> messageMap = new HashMap<>();
+
+ for (AkkamonNexus.TrainerID trainerID : trainerIDToOpponents.keySet()) {
+ messageMap.put(trainerID, new BattleMessage(
+ trainerID,
+ events,
+ state
+ ));
+ }
+ return messageMap;
+ }
+
+ public static List<MonTeam> createDemoTeams() {
+ int[] baseSnorlax = {160, 110, 65, 65, 110, 30};
+ int[] evs = {252, 4, 0, 0, 252, 0};
+ int[] ivs = {31,31,31,31,31,31};
+ double[] natureMultiplier = {1, 1, 1, 1, 1.1, 0.9};
+ int level = 100;
+ MonStats stats = new MonStats(
+ baseSnorlax,
+ evs,
+ ivs,
+ natureMultiplier,
+ level
+ );
+ Mon snorlax = new Mon(
+ "Snorlax",
+ stats,
+ AkkamonTypes.NORMAL,
+ AkkamonAbilities.IMMUNITY,
+ AkkamonStatus.NONE,
+ new String[] {
+ "Body Slam",
+ "Reflect",
+ "Rest",
+ "Ice Beam"
+ }
+ );
+
+ int[] baseMew = {100, 100, 100, 100, 100, 100};
+ int[] evsMew = {252, 252, 0, 0, 4, 0};
+ int[] ivsMew = {31,31,31,31,31,31};
+ double[] natureMultiplierMew = {1, 1.1, 1, 0.9, 1, 1};
+ int levelMew = 100;
+ MonStats statsMew = new MonStats(
+ baseMew,
+ evsMew,
+ ivsMew,
+ natureMultiplierMew,
+ levelMew
+ );
+ Mon mew = new Mon(
+ "Mew",
+ statsMew,
+ AkkamonTypes.PSYCHIC,
+ AkkamonAbilities.SYNCHRONIZE,
+ AkkamonStatus.NONE,
+ new String[] {
+ "Swords Dance",
+ "Earthquake",
+ "Body Slam",
+ "Soft-Boiled"
+ }
+ );
+
+ List<Mon> team1list = new ArrayList<>();
+ team1list.add(mew);
+ team1list.add(snorlax);
+
+ int[] baseMew2 = {106, 110, 90, 154, 90, 130};
+ int[] evsMew2 = {0, 0, 0, 252, 4, 252};
+ int[] ivsMew2 = {31,31,31,31,31,31};
+ double[] natureMultiplierMew2 = {1, 0.9, 1, 1.1, 1, 1};
+ int levelMew2 = 100;
+ MonStats statsMew2 = new MonStats(
+ baseMew2,
+ evsMew2,
+ ivsMew2,
+ natureMultiplierMew2,
+ levelMew2
+ );
+ Mon mew2 = new Mon(
+ "Mewtwo",
+ statsMew2,
+ AkkamonTypes.PSYCHIC,
+ AkkamonAbilities.PRESSURE,
+ AkkamonStatus.NONE,
+ new String[] {
+ "Amnesia",
+ "Psychic",
+ "Ice Beam",
+ "Agility"
+ }
+ );
+
+ int[] baseDragonite = {91, 134, 95, 100, 100, 80};
+ int[] evsDragonite = {0, 0, 0, 252, 4, 252};
+ int[] ivsDragonite = {31,31,31,31,31,31};
+ double[] natureMultiplierDragonite = {1, 0.9, 1, 1.1, 1, 1};
+ int levelDragonite = 100;
+ MonStats statsDragonite = new MonStats(
+ baseDragonite,
+ evsDragonite,
+ ivsDragonite,
+ natureMultiplierDragonite,
+ levelDragonite
+ );
+
+ Mon dragonite = new Mon(
+ "Dragonite",
+ statsDragonite,
+ AkkamonTypes.DRAGON,
+ AkkamonAbilities.INNER_FOCUS,
+ AkkamonStatus.NONE,
+ new String[] {
+ "Blizzard",
+ "Thunder Wave",
+ "Wrap",
+ "Agility"
+ }
+ );
+
+ List<Mon> team2list = new ArrayList<>();
+ team2list.add(mew2);
+ team2list.add(dragonite);
+
+ List<MonTeam> demoTeams = new ArrayList<>();
+ demoTeams.add(new MonTeam(team1list));
+ demoTeams.add(new MonTeam(team2list));
+
+ return demoTeams;
+ }
+
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/BattleEvents.java b/domain/src/main/java/akkamon/domain/model/battle/BattleEvents.java
new file mode 100644
index 0000000..0cc7a21
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/BattleEvents.java
@@ -0,0 +1,17 @@
+package akkamon.domain.model.battle;
+
+import akkamon.domain.actors.AkkamonNexus;
+import akkamon.domain.model.battle.events.BattleEvent;
+
+import java.util.*;
+
+public class BattleEvents {
+
+ public final Map<AkkamonNexus.TrainerID, Queue<BattleEvent>> trainerIDEventMap = new HashMap<>();
+
+ public BattleEvents(Set<AkkamonNexus.TrainerID> participants) {
+ for (AkkamonNexus.TrainerID trainerID : participants) {
+ trainerIDEventMap.put(trainerID, new LinkedList<>());
+ }
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/BattleMessage.java b/domain/src/main/java/akkamon/domain/model/battle/BattleMessage.java
new file mode 100644
index 0000000..bd00c8c
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/BattleMessage.java
@@ -0,0 +1,24 @@
+package akkamon.domain.model.battle;
+
+import akkamon.domain.actors.AkkamonNexus;
+import akkamon.domain.model.akkamon.Mon;
+import akkamon.domain.model.battle.events.BattleEvent;
+import akkamon.domain.model.battle.state.BattleState;
+
+import java.util.Queue;
+
+public class BattleMessage {
+
+ public Queue<BattleEvent> eventsToPlay;
+ public BattleState state;
+
+ public BattleMessage(
+ AkkamonNexus.TrainerID trainerID,
+ BattleEvents events,
+ BattleState state
+ ) {
+ this.eventsToPlay = events.trainerIDEventMap.get(trainerID);
+ this.state = state;
+ }
+
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/MonTeam.java b/domain/src/main/java/akkamon/domain/model/battle/MonTeam.java
new file mode 100644
index 0000000..10764af
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/MonTeam.java
@@ -0,0 +1,17 @@
+package akkamon.domain.model.battle;
+
+import akkamon.domain.model.akkamon.Mon;
+
+import java.util.List;
+
+public class MonTeam {
+
+ public Mon activeMon;
+ public List<Mon> team;
+
+ public MonTeam(List<Mon> team) {
+ this.activeMon = team.get(0);
+ this.team = team;
+ }
+
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/Phases.java b/domain/src/main/java/akkamon/domain/model/battle/Phases.java
new file mode 100644
index 0000000..7db073e
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/Phases.java
@@ -0,0 +1,10 @@
+package akkamon.domain.model.battle;
+
+public interface Phases {
+ void startTurn();
+ void fight();
+ void getAttacked();
+ void useItem();
+ void switchOut();
+ void endTurn();
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/events/BattleEvent.java b/domain/src/main/java/akkamon/domain/model/battle/events/BattleEvent.java
new file mode 100644
index 0000000..2256016
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/events/BattleEvent.java
@@ -0,0 +1,7 @@
+package akkamon.domain.model.battle.events;
+
+import java.util.List;
+
+public abstract class BattleEvent {
+ public BattleEventIds id;
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/events/BattleEventIds.java b/domain/src/main/java/akkamon/domain/model/battle/events/BattleEventIds.java
new file mode 100644
index 0000000..b048d00
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/events/BattleEventIds.java
@@ -0,0 +1,5 @@
+package akkamon.domain.model.battle.events;
+
+public enum BattleEventIds {
+ INTRODUCTION
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/events/Introduction.java b/domain/src/main/java/akkamon/domain/model/battle/events/Introduction.java
new file mode 100644
index 0000000..7c05f3e
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/events/Introduction.java
@@ -0,0 +1,15 @@
+package akkamon.domain.model.battle.events;
+
+import akkamon.domain.actors.AkkamonNexus;
+import akkamon.domain.model.battle.MonTeam;
+
+import java.util.List;
+import java.util.Map;
+
+public class Introduction extends BattleEvent {
+
+ public Introduction(
+ ) {
+ this.id = BattleEventIds.INTRODUCTION;
+ }
+}
diff --git a/domain/src/main/java/akkamon/domain/model/battle/state/BattleState.java b/domain/src/main/java/akkamon/domain/model/battle/state/BattleState.java
new file mode 100644
index 0000000..b0e34b5
--- /dev/null
+++ b/domain/src/main/java/akkamon/domain/model/battle/state/BattleState.java
@@ -0,0 +1,18 @@
+package akkamon.domain.model.battle.state;
+
+import akkamon.domain.actors.AkkamonNexus;
+import akkamon.domain.model.battle.MonTeam;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class BattleState {
+
+ public Map<String, MonTeam> teams = new HashMap<>();
+
+ public BattleState(Map<AkkamonNexus.TrainerID, MonTeam> trainerIDtoTeam) {
+ for (AkkamonNexus.TrainerID trainerID : trainerIDtoTeam.keySet()) {
+ this.teams.put(trainerID.id, trainerIDtoTeam.get(trainerID));
+ }
+ }
+}
diff --git a/domain/src/test/java/akkamon/domain/iot/DeviceGroupQueryTest.java b/domain/src/test/java/akkamon/domain/iot/DeviceGroupQueryTest.java
deleted file mode 100644
index ebfeda5..0000000
--- a/domain/src/test/java/akkamon/domain/iot/DeviceGroupQueryTest.java
+++ /dev/null
@@ -1,245 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.testkit.typed.javadsl.TestKitJunitResource;
-import akka.actor.testkit.typed.javadsl.TestProbe;
-import akka.actor.typed.ActorRef;
-import akkamon.domain.iot.DeviceManager.*;
-import akkamon.domain.iot.DeviceManager.RespondAllTemperatures;
-import akkamon.domain.iot.DeviceManager.Temperature;
-import akkamon.domain.iot.DeviceManager.TemperatureReading;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-
-import static org.junit.Assert.*;
-
-public class DeviceGroupQueryTest {
-
- @ClassRule
- public static final TestKitJunitResource testKit = new TestKitJunitResource();
-
- @Test
- public void testReturnTemperatureValueForWorkingDevices() {
- TestProbe<RespondAllTemperatures> requester =
- testKit.createTestProbe(RespondAllTemperatures.class);
- TestProbe<Device.Command> device1 = testKit.createTestProbe(Device.Command.class);
- TestProbe<Device.Command> device2 = testKit.createTestProbe(Device.Command.class);
-
- Map<String, ActorRef<Device.Command>> deviceIdToActor = new HashMap<>();
- deviceIdToActor.put("device1", device1.getRef());
- deviceIdToActor.put("device2", device2.getRef());
-
- ActorRef<DeviceGroupQuery.Command> queryActor =
- testKit.spawn(
- DeviceGroupQuery.create(
- deviceIdToActor, 1L, requester.getRef(), Duration.ofSeconds(3)));
-
- device1.expectMessageClass(Device.ReadTemperature.class);
- device2.expectMessageClass(Device.ReadTemperature.class);
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device1", Optional.of(1.0))));
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device2", Optional.of(2.0))));
-
- RespondAllTemperatures response = requester.receiveMessage();
- assertEquals(1L, response.requestId);
-
- Map<String, TemperatureReading> expectedTemperatures = new HashMap<>();
- expectedTemperatures.put("device1", new Temperature(1.0));
- expectedTemperatures.put("device2", new Temperature(2.0));
-
- assertEquals(expectedTemperatures, response.temperatures);
- }
-
- @Test
- public void testReturnTemperatureNotAvailableForDevicesWithNoReadings() {
- TestProbe<RespondAllTemperatures> requester =
- testKit.createTestProbe(RespondAllTemperatures.class);
- TestProbe<Device.Command> device1 = testKit.createTestProbe(Device.Command.class);
- TestProbe<Device.Command> device2 = testKit.createTestProbe(Device.Command.class);
-
- Map<String, ActorRef<Device.Command>> deviceIdToActor = new HashMap<>();
- deviceIdToActor.put("device1", device1.getRef());
- deviceIdToActor.put("device2", device2.getRef());
-
- ActorRef<DeviceGroupQuery.Command> queryActor =
- testKit.spawn(
- DeviceGroupQuery.create(
- deviceIdToActor, 1L, requester.getRef(), Duration.ofSeconds(3)));
-
- assertEquals(0L, device1.expectMessageClass(Device.ReadTemperature.class).requestId);
- assertEquals(0L, device2.expectMessageClass(Device.ReadTemperature.class).requestId);
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device1", Optional.empty())));
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device2", Optional.of(2.0))));
-
- RespondAllTemperatures response = requester.receiveMessage();
- assertEquals(1L, response.requestId);
-
- Map<String, TemperatureReading> expectedTemperatures = new HashMap<>();
- expectedTemperatures.put("device1", TemperatureNotAvailable.INSTANCE);
- expectedTemperatures.put("device2", new Temperature(2.0));
-
- assertEquals(expectedTemperatures, response.temperatures);
- }
-
- @Test
- public void testReturnDeviceNotAvailableIfDeviceStopsBeforeAnswering() {
- TestProbe<RespondAllTemperatures> requester =
- testKit.createTestProbe(RespondAllTemperatures.class);
- TestProbe<Device.Command> device1 = testKit.createTestProbe(Device.Command.class);
- TestProbe<Device.Command> device2 = testKit.createTestProbe(Device.Command.class);
-
- Map<String, ActorRef<Device.Command>> deviceIdToActor = new HashMap<>();
- deviceIdToActor.put("device1", device1.getRef());
- deviceIdToActor.put("device2", device2.getRef());
-
- ActorRef<DeviceGroupQuery.Command> queryActor =
- testKit.spawn(
- DeviceGroupQuery.create(
- deviceIdToActor, 1L, requester.getRef(), Duration.ofSeconds(3)));
-
- assertEquals(0L, device1.expectMessageClass(Device.ReadTemperature.class).requestId);
- assertEquals(0L, device2.expectMessageClass(Device.ReadTemperature.class).requestId);
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device1", Optional.of(1.0))));
-
- device2.stop();
-
- RespondAllTemperatures response = requester.receiveMessage();
- assertEquals(1L, response.requestId);
-
- Map<String, TemperatureReading> expectedTemperatures = new HashMap<>();
- expectedTemperatures.put("device1", new Temperature(1.0));
- expectedTemperatures.put("device2", DeviceNotAvailable.INSTANCE);
-
- assertEquals(expectedTemperatures, response.temperatures);
- }
-
- @Test
- public void testReturnTemperatureReadingEvenIfDeviceStopsAfterAnswering() {
- TestProbe<RespondAllTemperatures> requester =
- testKit.createTestProbe(RespondAllTemperatures.class);
- TestProbe<Device.Command> device1 = testKit.createTestProbe(Device.Command.class);
- TestProbe<Device.Command> device2 = testKit.createTestProbe(Device.Command.class);
-
- Map<String, ActorRef<Device.Command>> deviceIdToActor = new HashMap<>();
- deviceIdToActor.put("device1", device1.getRef());
- deviceIdToActor.put("device2", device2.getRef());
-
- ActorRef<DeviceGroupQuery.Command> queryActor =
- testKit.spawn(
- DeviceGroupQuery.create(
- deviceIdToActor, 1L, requester.getRef(), Duration.ofSeconds(3)));
-
- assertEquals(0L, device1.expectMessageClass(Device.ReadTemperature.class).requestId);
- assertEquals(0L, device2.expectMessageClass(Device.ReadTemperature.class).requestId);
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device1", Optional.of(1.0))));
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device2", Optional.of(2.0))));
-
- device2.stop();
-
- RespondAllTemperatures response = requester.receiveMessage();
- assertEquals(1L, response.requestId);
-
- Map<String, TemperatureReading> expectedTemperatures = new HashMap<>();
- expectedTemperatures.put("device1", new Temperature(1.0));
- expectedTemperatures.put("device2", new Temperature(2.0));
-
- assertEquals(expectedTemperatures, response.temperatures);
- }
-
- @Test
- public void testReturnDeviceTimedOutIfDeviceDoesNotAnswerInTime() {
- TestProbe<RespondAllTemperatures> requester =
- testKit.createTestProbe(RespondAllTemperatures.class);
- TestProbe<Device.Command> device1 = testKit.createTestProbe(Device.Command.class);
- TestProbe<Device.Command> device2 = testKit.createTestProbe(Device.Command.class);
-
- Map<String, ActorRef<Device.Command>> deviceIdToActor = new HashMap<>();
- deviceIdToActor.put("device1", device1.getRef());
- deviceIdToActor.put("device2", device2.getRef());
-
- ActorRef<DeviceGroupQuery.Command> queryActor =
- testKit.spawn(
- DeviceGroupQuery.create(
- deviceIdToActor, 1L, requester.getRef(), Duration.ofMillis(200)));
-
- assertEquals(0L, device1.expectMessageClass(Device.ReadTemperature.class).requestId);
- assertEquals(0L, device2.expectMessageClass(Device.ReadTemperature.class).requestId);
-
- queryActor.tell(
- new DeviceGroupQuery.WrappedRespondTemperature(
- new Device.RespondTemperature(0L, "device1", Optional.of(1.0))));
-
- // no reply from device2
-
- RespondAllTemperatures response = requester.receiveMessage();
- assertEquals(1L, response.requestId);
-
- Map<String, TemperatureReading> expectedTemperatures = new HashMap<>();
- expectedTemperatures.put("device1", new Temperature(1.0));
- expectedTemperatures.put("device2", DeviceTimedOut.INSTANCE);
-
- assertEquals(expectedTemperatures, response.temperatures);
- }
-
- @Test
- public void testCollectTemperaturesFromAllActiveDevices() {
- TestProbe<DeviceRegistered> registeredProbe = testKit.createTestProbe(DeviceRegistered.class);
- ActorRef<DeviceGroup.Command> groupActor = testKit.spawn(DeviceGroup.create("group"));
-
- groupActor.tell(new RequestTrackDevice("group", "device1", registeredProbe.getRef()));
- ActorRef<Device.Command> deviceActor1 = registeredProbe.receiveMessage().device;
-
- groupActor.tell(new RequestTrackDevice("group", "device2", registeredProbe.getRef()));
- ActorRef<Device.Command> deviceActor2 = registeredProbe.receiveMessage().device;
-
- groupActor.tell(new RequestTrackDevice("group", "device3", registeredProbe.getRef()));
- ActorRef<Device.Command> deviceActor3 = registeredProbe.receiveMessage().device;
-
- // Check that the device actors are working
- TestProbe<Device.TemperatureRecorded> recordProbe =
- testKit.createTestProbe(Device.TemperatureRecorded.class);
- deviceActor1.tell(new Device.RecordTemperature(0L, 1.0, recordProbe.getRef()));
- assertEquals(0L, recordProbe.receiveMessage().requestId);
- deviceActor2.tell(new Device.RecordTemperature(1L, 2.0, recordProbe.getRef()));
- assertEquals(1L, recordProbe.receiveMessage().requestId);
- // No temperature for device 3
-
- TestProbe<RespondAllTemperatures> allTempProbe =
- testKit.createTestProbe(RespondAllTemperatures.class);
- groupActor.tell(new RequestAllTemperatures(0L, "group", allTempProbe.getRef()));
- RespondAllTemperatures response = allTempProbe.receiveMessage();
- assertEquals(0L, response.requestId);
-
- Map<String, TemperatureReading> expectedTemperatures = new HashMap<>();
- expectedTemperatures.put("device1", new Temperature(1.0));
- expectedTemperatures.put("device2", new Temperature(2.0));
- expectedTemperatures.put("device3", TemperatureNotAvailable.INSTANCE);
-
- assertEquals(expectedTemperatures, response.temperatures);
- }
-
-} \ No newline at end of file
diff --git a/domain/src/test/java/akkamon/domain/iot/DeviceTest.java b/domain/src/test/java/akkamon/domain/iot/DeviceTest.java
deleted file mode 100644
index a05499f..0000000
--- a/domain/src/test/java/akkamon/domain/iot/DeviceTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package akkamon.domain.iot;
-
-import akka.actor.testkit.typed.javadsl.TestKitJunitResource;
-import akka.actor.testkit.typed.javadsl.TestProbe;
-import akka.actor.typed.ActorRef;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-public class DeviceTest {
-
- @ClassRule
- public static final TestKitJunitResource testKit = new TestKitJunitResource();
-
- @Test
- public void testReplyWithEmptyReadingIfNoTemperatureIsKnown() {
- TestProbe<Device.RespondTemperature> probe = testKit.createTestProbe(Device.RespondTemperature.class);
-
- ActorRef<Device.Command> deviceActor = testKit.spawn(Device.create("group", "device"));
- deviceActor.tell(new Device.ReadTemperature(42L, probe.getRef()));
- Device.RespondTemperature response = probe.receiveMessage();
- assertEquals(42L, response.requestId);
- assertEquals(Optional.empty(), response.value);
-
-
- }
-
- @Test
- public void testReplyWithLatestTemperatureReading() {
- TestProbe<Device.TemperatureRecorded> recordProbe =
- testKit.createTestProbe(Device.TemperatureRecorded.class);
-
- TestProbe<Device.RespondTemperature> readProbe =
- testKit.createTestProbe(Device.RespondTemperature.class);
-
- ActorRef<Device.Command> deviceActor = testKit.spawn(Device.create("group", "device"));
-
- deviceActor.tell(new Device.RecordTemperature(1L, 24.0, recordProbe.getRef()));
- assertEquals(1L, recordProbe.receiveMessage().requestId);
-
- deviceActor.tell(new Device.ReadTemperature(2L, readProbe.getRef()));
- Device.RespondTemperature response1 = readProbe.receiveMessage();
- assertEquals(2L, response1.requestId);
- assertEquals(Optional.of(24.0), response1.value);
-
- deviceActor.tell(new Device.RecordTemperature(3L, 55.0, recordProbe.getRef()));
- assertEquals(3L, recordProbe.receiveMessage().requestId);
-
- deviceActor.tell(new Device.ReadTemperature(4L, readProbe.getRef()));
- Device.RespondTemperature response2 = readProbe.receiveMessage();
- assertEquals(4L, response2.requestId);
- assertEquals(Optional.of(55.0), response2.value);
- }
-
- @Test
- public void testReplyToRegistrationRequests() {
- TestProbe<DeviceManager.DeviceRegistered> probe = testKit.createTestProbe(DeviceManager.DeviceRegistered.class);
- ActorRef<DeviceGroup.Command> groupActor = testKit.spawn(DeviceGroup.create("group"));
-
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device", probe.getRef()));
- DeviceManager.DeviceRegistered registered1 = probe.receiveMessage();
-
- // another deviceId
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device3", probe.getRef()));
- DeviceManager.DeviceRegistered registered2 = probe.receiveMessage();
- assertNotEquals(registered1.device, registered2.device);
-
- // Check that the device actors are working
- TestProbe<Device.TemperatureRecorded> recordProbe =
- testKit.createTestProbe(Device.TemperatureRecorded.class);
- registered1.device.tell(new Device.RecordTemperature(0L, 1.0, recordProbe.getRef()));
- assertEquals(0L, recordProbe.receiveMessage().requestId);
- registered2.device.tell(new Device.RecordTemperature(1L, 2.0, recordProbe.getRef()));
- assertEquals(1L, recordProbe.receiveMessage().requestId);
- }
-
- @Test
- public void testIgnoreWrongRegistrationRequests() {
- TestProbe<DeviceManager.DeviceRegistered> probe = testKit.createTestProbe(DeviceManager.DeviceRegistered.class);
- ActorRef<DeviceGroup.Command> groupActor = testKit.spawn(DeviceGroup.create("group"));
- groupActor.tell(new DeviceManager.RequestTrackDevice("wrongGroup", "device1", probe.getRef()));
- probe.expectNoMessage();
- }
-
-
- @Test
- public void testReturnSameActorForSameDeviceId() {
- TestProbe<DeviceManager.DeviceRegistered> probe = testKit.createTestProbe(DeviceManager.DeviceRegistered.class);
- ActorRef<DeviceGroup.Command> groupActor = testKit.spawn(DeviceGroup.create("group"));
-
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device", probe.getRef()));
- DeviceManager.DeviceRegistered registered1 = probe.receiveMessage();
-
- // registering same again should be idempotent
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device", probe.getRef()));
- DeviceManager.DeviceRegistered registered2 = probe.receiveMessage();
- assertEquals(registered1.device, registered2.device);
- }
-
- @Test
-public void testListActiveDevices() {
- TestProbe<DeviceManager.DeviceRegistered> registeredProbe = testKit.createTestProbe(DeviceManager.DeviceRegistered.class);
- ActorRef<DeviceGroup.Command> groupActor = testKit.spawn(DeviceGroup.create("group"));
-
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device1", registeredProbe.getRef()));
- registeredProbe.receiveMessage();
-
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device2", registeredProbe.getRef()));
- registeredProbe.receiveMessage();
-
- TestProbe<DeviceManager.ReplyDeviceList> deviceListProbe = testKit.createTestProbe(DeviceManager.ReplyDeviceList.class);
-
- groupActor.tell(new DeviceManager.RequestDeviceList(0L, "group", deviceListProbe.getRef()));
- DeviceManager.ReplyDeviceList reply = deviceListProbe.receiveMessage();
- assertEquals(0L, reply.requestId);
- Set<String> testIds = Stream.of("device1", "device2").collect(Collectors.toSet());
- assertEquals(testIds, reply.ids);
-}
-
-@Test
-public void testListActiveDevicesAfterOneShutsDown() {
- TestProbe<DeviceManager.DeviceRegistered> registeredProbe = testKit.createTestProbe(DeviceManager.DeviceRegistered.class);
- ActorRef<DeviceGroup.Command> groupActor = testKit.spawn(DeviceGroup.create("group"));
-
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device1", registeredProbe.getRef()));
- DeviceManager.DeviceRegistered registered1 = registeredProbe.receiveMessage();
-
- groupActor.tell(new DeviceManager.RequestTrackDevice("group", "device2", registeredProbe.getRef()));
- DeviceManager.DeviceRegistered registered2 = registeredProbe.receiveMessage();
-
- ActorRef<Device.Command> toShutDown = registered1.device;
-
- TestProbe<DeviceManager.ReplyDeviceList> deviceListProbe = testKit.createTestProbe(DeviceManager.ReplyDeviceList.class);
-
- groupActor.tell(new DeviceManager.RequestDeviceList(0L, "group", deviceListProbe.getRef()));
- DeviceManager.ReplyDeviceList reply = deviceListProbe.receiveMessage();
- assertEquals(0L, reply.requestId);
- assertEquals(Stream.of("device1", "device2").collect(Collectors.toSet()), reply.ids);
-
- toShutDown.tell(Device.Passivate.INSTANCE);
- registeredProbe.expectTerminated(toShutDown, registeredProbe.getRemainingOrDefault());
-
- // using awaitAssert to retry because it might take longer for the groupActor
- // to see the Terminated, that order is undefined
- registeredProbe.awaitAssert(
- () -> {
- groupActor.tell(new DeviceManager.RequestDeviceList(1L, "group", deviceListProbe.getRef()));
- DeviceManager.ReplyDeviceList r = deviceListProbe.receiveMessage();
- assertEquals(1L, r.requestId);
- assertEquals(Stream.of("device2").collect(Collectors.toSet()), r.ids);
- return null;
- });
-}
-
-}
diff --git a/domain/src/test/java/akkamon/domain/model/MonStatsTest.java b/domain/src/test/java/akkamon/domain/model/MonStatsTest.java
new file mode 100644
index 0000000..c8f1818
--- /dev/null
+++ b/domain/src/test/java/akkamon/domain/model/MonStatsTest.java
@@ -0,0 +1,40 @@
+package akkamon.domain.model;
+
+import akkamon.domain.model.akkamon.MonStats;
+import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class MonStatsTest {
+
+
+ @Test
+ public void a_mons_hp_can_be_constructed_from_base_ev_nature_and_iv_values() {
+
+ int[] baseSnorlax = {160, 110, 65, 65, 110, 30};
+ int[] evs = {252, 4, 0, 0, 252, 0};
+ int[] ivs = {31,31,31,31,31,31};
+ double[] natureMultiplier = {1, 1, 1, 1, 1.1, 0.9};
+ int level = 100;
+
+ MonStats stats = new MonStats(
+ baseSnorlax,
+ evs,
+ ivs,
+ natureMultiplier,
+ level
+ );
+
+ assertAll(
+ () -> {
+ assertEquals(524, stats.HP);
+ assertEquals(257, stats.Attack);
+ assertEquals(166, stats.Defence);
+ assertEquals(166, stats.SpecialAttack);
+ assertEquals(350, stats.SpecialDefence);
+ assertEquals(86, stats.Speed);
+ }
+ );
+ }
+
+} \ No newline at end of file
diff --git a/domain/src/test/java/akkamon/domain/model/MonTest.java b/domain/src/test/java/akkamon/domain/model/MonTest.java
new file mode 100644
index 0000000..d07cf0e
--- /dev/null
+++ b/domain/src/test/java/akkamon/domain/model/MonTest.java
@@ -0,0 +1,64 @@
+package akkamon.domain.model;
+
+import akkamon.domain.model.akkamon.Mon;
+import akkamon.domain.model.akkamon.MonStats;
+import akkamon.domain.model.akkamon.abilities.AkkamonAbilities;
+import akkamon.domain.model.akkamon.abilities.Immunity;
+import akkamon.domain.model.akkamon.status.AkkamonStatus;
+import akkamon.domain.model.akkamon.status.NoStatus;
+import akkamon.domain.model.akkamon.types.AkkamonTypes;
+import akkamon.domain.model.akkamon.types.NormalType;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Nested;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+class MonTest {
+
+ @Test
+ public void a_mon_can_be_constructed() {
+
+ int[] baseSnorlax = {160, 110, 65, 65, 110, 30};
+ int[] evs = {252, 4, 0, 0, 252, 0};
+ int[] ivs = {31,31,31,31,31,31};
+ double[] natureMultiplier = {1, 1, 1, 1, 1.1, 0.9};
+ int level = 100;
+
+ MonStats stats = new MonStats(
+ baseSnorlax,
+ evs,
+ ivs,
+ natureMultiplier,
+ level
+ );
+
+ Mon snorlax = new Mon(
+ "Snorlax",
+ stats,
+ AkkamonTypes.NORMAL,
+ AkkamonAbilities.IMMUNITY,
+ AkkamonStatus.NONE,
+ new String[] {
+ "Body Slam",
+ "Reflect",
+ "Rest",
+ "Ice Beam"
+ }
+ );
+
+ assertEquals(new NormalType(), snorlax.getType());
+ assertEquals(new Immunity(), snorlax.getAbility());
+ assertEquals(new NoStatus(), snorlax.getStatus());
+ }
+
+ @Nested
+ public class SnorlaxBehaviour {
+
+ @Nested
+ public class startTurn {
+
+ }
+
+ }
+} \ No newline at end of file
diff --git a/domain/src/test/java/akkamon/domain/model/MoveTest.java b/domain/src/test/java/akkamon/domain/model/MoveTest.java
new file mode 100644
index 0000000..5795193
--- /dev/null
+++ b/domain/src/test/java/akkamon/domain/model/MoveTest.java
@@ -0,0 +1,13 @@
+package akkamon.domain.model;
+
+import akkamon.domain.model.akkamon.moves.BodySlam;
+
+class MoveTest {
+
+ public void a_move_can_be_instantiated() {
+
+ BodySlam move = new BodySlam(
+
+ );
+ }
+} \ No newline at end of file
diff --git a/domain/src/test/java/akkamon/domain/model/battle/EngineTest.java b/domain/src/test/java/akkamon/domain/model/battle/EngineTest.java
new file mode 100644
index 0000000..75cd4ca
--- /dev/null
+++ b/domain/src/test/java/akkamon/domain/model/battle/EngineTest.java
@@ -0,0 +1,79 @@
+package akkamon.domain.model.battle;
+
+import akkamon.domain.actors.AkkamonNexus;
+import akkamon.domain.model.battle.events.BattleEvent;
+import akkamon.domain.model.battle.events.Introduction;
+import com.google.gson.Gson;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class EngineTest {
+
+ @Test
+ void the_engine_is_constructed_with_two_trainer_ids() {
+ AkkamonNexus.TrainerID trainerID = new AkkamonNexus.TrainerID(
+ "Ash",
+ "Pallet Town"
+ );
+
+ AkkamonNexus.TrainerID trainerID1 = new AkkamonNexus.TrainerID(
+ "Brock",
+ "Pewter City"
+ );
+
+ Set<AkkamonNexus.TrainerID> participants = new HashSet();
+ participants.add(trainerID);
+ participants.add(trainerID1);
+
+ BattleEngine engine = new BattleEngine(participants);
+ Map<String, MonTeam> teams = engine.getState().teams;
+
+ Set<String> participantids = new HashSet<>();
+
+ for (AkkamonNexus.TrainerID id : participants) {
+ participantids.add(id.id);
+ }
+
+ assertEquals(participantids, teams.keySet());
+ }
+
+
+ BattleEngine engine;
+ Gson gson = new Gson();
+
+ @BeforeEach
+ void setUP() {
+ AkkamonNexus.TrainerID trainerID = new AkkamonNexus.TrainerID(
+ "Ash",
+ "Pallet Town"
+ );
+
+ AkkamonNexus.TrainerID trainerID1 = new AkkamonNexus.TrainerID(
+ "Brock",
+ "Pewter City"
+ );
+
+ Set<AkkamonNexus.TrainerID> participants = new HashSet();
+ participants.add(trainerID);
+ participants.add(trainerID1);
+
+ engine = new BattleEngine(participants);
+
+ }
+
+ @Test
+ void given_the_battle_is_not_started_when_request_start_battle_is_called_then_return_initial_state_and_events_to_start_battle_in_the_client() {
+ Map<AkkamonNexus.TrainerID, BattleMessage> message = engine.initialise();
+ for (AkkamonNexus.TrainerID trainerID : message.keySet()) {
+ System.out.println(gson.toJson(message.get(trainerID)));
+ }
+ }
+
+} \ No newline at end of file