diff --git a/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegment.java b/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegment.java
index bf86d15..199a8ad 100644
--- a/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegment.java
+++ b/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegment.java
@@ -1,2 +1,99 @@
-package uulm.teamname.marvelous.server.Lobby.pipelining;public class PauseSegment {
+package uulm.teamname.marvelous.server.Lobby.pipelining;
+
+import uulm.teamname.marvelous.gamelibrary.Tuple;
+import uulm.teamname.marvelous.gamelibrary.events.Event;
+import uulm.teamname.marvelous.gamelibrary.events.EventBuilder;
+import uulm.teamname.marvelous.gamelibrary.events.EventType;
+import uulm.teamname.marvelous.gamelibrary.requests.Request;
+import uulm.teamname.marvelous.gamelibrary.requests.RequestBuilder;
+import uulm.teamname.marvelous.gamelibrary.requests.RequestType;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class PauseSegment implements Segment {
+
+ private boolean paused;
+
+ public PauseSegment(){
+ paused = false;
+ }
+
+ public void pauseGame(){
+ if(!paused)
+ paused = true;
+ }
+ public void pauseEnd(){
+ if(paused)
+ paused = false;
+ }
+
+ public boolean isPaused() {
+ return paused;
+ }
+
+
+ /**
+ * Pipelining method to process a set of requests.
+ * The list of requests will be processed according to the following rules:
+ *
+ * - If there is a PauseStartRequest, the paused value will be set to true
+ * - Any CharacterRequests will be removed from the requests if the game is paused. These include:
+ *
+ * - MeeleAttackRequest
+ * - RangedAttackRequest
+ * - MoveRequest
+ * - ExchangeInfinityStoneRequest
+ * - UseInfinityStoneRequest
+ * - EndRoundRequest
+ *
+ *
+ * - If a mistake is made (request is sent while pause active), the client will get an error
+ * - If there is a PauseStopRequest the game will be unpaused
+ *
+ * @param packet
+ */
+ @Override
+ public void processRequests(List packet, List carrier, AtomicBoolean abort) {
+ // check if there is a pause request (either start or stop)
+ if (packet.contains(new RequestBuilder(RequestType.PauseStartRequest).buildGameRequest())) {
+ if (!paused) {
+ // pause the game
+ pauseGame();
+ // create a new PauseStartEvent
+ carrier.add(new EventBuilder(EventType.PauseStartEvent).buildGameEvent());
+ } else { // if the game is already paused
+ abort.set(true);
+ return;
+ }
+ } else if (packet.contains(new RequestBuilder(RequestType.PauseStopRequest).buildGameRequest())) {
+ if (paused) {
+ // pause the game
+ pauseEnd();
+ // create a new PauseStartRequest
+ carrier.add(new EventBuilder(EventType.PauseStopEvent).buildGameEvent());
+ } else { // if the game is not paused
+ abort.set(true);
+ return;
+ }
+ }
+
+ // filter the events
+ if (paused) {
+ for (Request request: packet) {
+ switch (request.type) {
+ case MeleeAttackRequest,
+ RangedAttackRequest,
+ MoveRequest,
+ ExchangeInfinityStoneRequest,
+ UseInfinityStoneRequest,
+ EndRoundRequest,
+ PauseStopRequest,
+ PauseStartRequest -> packet.remove(request);
+
+ case DisconnectRequest, Req -> { /* do nothing */ }
+ }
+ }
+ }
+ }
}
diff --git a/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Pipeline.java b/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Pipeline.java
index 601d903..8f1cee2 100644
--- a/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Pipeline.java
+++ b/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Pipeline.java
@@ -1,23 +1,65 @@
-package uulm.teamname.marvelous.server.Lobby;
+package uulm.teamname.marvelous.server.Lobby.pipelining;
+import uulm.teamname.marvelous.gamelibrary.Tuple;
+import uulm.teamname.marvelous.gamelibrary.events.Event;
import uulm.teamname.marvelous.gamelibrary.requests.Request;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+/**
+ * The {@link Pipeline} class pipelines {@link Request Requests} through {@link Segment Segments} to
+ * create {@link Event Events}. To add functionality without dabbling in the game library, create a new {@link Segment}.
+ */
public class Pipeline {
- private final Segment[] segments;
+ /** The segments of the pipeline, which will be executed from left to right (index 0 to segments.size()) */
+ private final ArrayList segments;
- public Pipeline(Segment[] segments) {
- this.segments = segments;
+ /**
+ * Creates a new empty {@link Pipeline} object
+ */
+ public Pipeline() {
+ this.segments = new ArrayList<>();
}
- public void processEvents(Request[] requests) {
- Request[] out;
+ /**
+ * Pipeline the {@link Request Requests} through all {@link Segment Segments} that are in the pipeline.
+ * The {@link Request Requests} are declared as the Packet. The {@link Request Requests} are filtered
+ * by each {@link Segment segment}, whereby each {@link Segment segment} takes (and thereby removes) all
+ * {@link Event events} relevant to the {@link Segment segment}. The {@link Event Events} are returned at the
+ * end of the pipeline.
+ * @param requests are the requests that are being pipelined through the pipeline
+ * @return a {@link Tuple}<{@link Boolean}, {@link Event}[]>, whereby the {@link Boolean} declares whether the
+ * execution of the {@link Pipeline} is successful. If that is the case, the events can be ignored,
+ * and an error message can be sent to the client.
+ */
+ public Tuple processRequests(Request[] requests) {
+ List packet = Arrays.asList(requests);
+ List carrier = new ArrayList<>();
+ AtomicBoolean abort = new AtomicBoolean();
+ abort.set(false);
for (Segment segment: segments) {
- out = segment.processEvents(requests);
+ segment.processRequests(packet, carrier, abort);
+ if (packet.size() == 0 || abort.get()) {
+ break;
+ }
}
+ return new Tuple (abort.get(), carrier.toArray(new Event[0]));
}
-
+ /**
+ * Adds a segment to the pipeline. Note that ORDER MATTERS! The first segment added will be the
+ * first segment to process events. Also note that segments cannot be removed once added. This is by
+ * design, as removing segments would give the pipeline runtime customizability, which it is not supposed to
+ * possess in the first place.
+ * @param toAdd is the segment that will be added to the pipeline
+ * @return the pipeline itself for chaining
+ */
+ public Pipeline addSegment(Segment toAdd) {
+ this.segments.add(toAdd);
+ return this;
+ }
}
diff --git a/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Segment.java b/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Segment.java
index 48d9ad2..9ca634c 100644
--- a/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Segment.java
+++ b/Server/src/main/java/uulm/teamname/marvelous/server/Lobby/pipelining/Segment.java
@@ -1,8 +1,26 @@
-package uulm.teamname.marvelous.server.Lobby;
+package uulm.teamname.marvelous.server.Lobby.pipelining;
+import uulm.teamname.marvelous.gamelibrary.Tuple;
import uulm.teamname.marvelous.gamelibrary.events.Event;
import uulm.teamname.marvelous.gamelibrary.requests.Request;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
public interface Segment {
- public Request[] processEvents(Request[] events);
+ /**
+ * Pipelining method to process a set of requests.
+ * The list of requests will be processed according to some set of rules. Hereby,
+ * the {@link Request Requests} in the packet will be filtered out as appropriate,
+ * whereby the resulting {@link Event Events} are appended to the carrier.
+ * @param packet is a {@link List} of {@link Request Requests} that is filtered
+ * by the {@link Segment} as appropriate
+ * @param carrier is a {@link List} of {@link Event Events} that is appended to
+ * if new requests are generated from the execution of the {@link Segment}
+ * @param abort is an {@link AtomicBoolean} describing whether an error has occurred during the execution of
+ * the {@link Segment} Note that error here does not describe an execution error
+ * of the segment, but instead an error in the events passed to it, like for example moving into a Rock.
+ * The conventional way of setting this boolean is to write {@code abort.set(true); return;}
+ */
+ public void processRequests(List packet, List carrier, AtomicBoolean abort);
}
diff --git a/Server/src/test/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegmentTest.java b/Server/src/test/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegmentTest.java
index 7a0e1e7..66b5826 100644
--- a/Server/src/test/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegmentTest.java
+++ b/Server/src/test/java/uulm/teamname/marvelous/server/Lobby/pipelining/PauseSegmentTest.java
@@ -1,5 +1,44 @@
+package uulm.teamname.marvelous.server.Lobby.pipelining;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import static org.assertj.core.api.Assertions.*;
+
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
+
class PauseSegmentTest {
-
+
+ PauseSegment pauseSegment;
+
+ @BeforeEach
+ void setUp() {
+ pauseSegment = new PauseSegment();
+ }
+
+ @Test
+ void pauseGame() {
+ assertThat(pauseSegment.isPaused()).isFalse();
+ pauseSegment.pauseGame();
+ assertThat(pauseSegment.isPaused()).isTrue();
+ pauseSegment.pauseGame();
+ assertThat(pauseSegment.isPaused()).isTrue();
+ }
+
+ @Test
+ void pauseEnd() {
+ assertThat(pauseSegment.isPaused()).isFalse();
+ pauseSegment.pauseEnd();
+ assertThat(pauseSegment.isPaused()).isFalse();
+ pauseSegment.pauseGame();
+ assertThat(pauseSegment.isPaused()).isTrue();
+ pauseSegment.pauseEnd();
+ assertThat(pauseSegment.isPaused()).isFalse();
+ }
+
+ @Test
+ void processEvents() {
+ // TODO: check that events get pipelined normally if not paused, but filtered if paused
+ // and check that events work properly
+ }
}
\ No newline at end of file