diff options
| author | Mike Vink <mike1994vink@gmail.com> | 2021-08-02 00:11:52 +0200 |
|---|---|---|
| committer | Mike Vink <mike1994vink@gmail.com> | 2021-08-02 00:11:52 +0200 |
| commit | 6d35c43741f02965f1702c35d7429a1df32ff576 (patch) | |
| tree | 2550396fca77f7317215e6c101447e9be19e477b /domain | |
| parent | 82e9d093ae1186646f06f2b1397d6fb75b6bde22 (diff) | |
feat(battle): UI and Backend Engine setup!
Diffstat (limited to 'domain')
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 |
