list) throws IllegalStateException {
+ theBulbModel.setPosition(BulbModel.Position.SCREWED);
list.add(SCREW);
}
- private static void validateBulb(Bulb bulb) throws IllegalArgumentException {
- if (bulb.getPosition() != Bulb.Position.SCREWED)
+ private static void validateBulb(BulbModel bulbModel) throws IllegalArgumentException {
+ if (bulbModel.getPosition() != BulbModel.Position.SCREWED)
throw new IllegalArgumentException("Bulb must be screwed in at the start");
- if (bulb.getLight() == null)
+ if (bulbModel.getLight() == null)
throw new IllegalArgumentException("Bulb must be lit or unlit");
- if (bulb.getColor() == null)
+ if (bulbModel.getColor() == null)
throw new IllegalArgumentException("Bulb must have a color");
- if (bulb.getOpacity() == null)
+ if (bulbModel.getOpacity() == null)
throw new IllegalArgumentException("Bulb must be Opaque or Translucent");
}
}
diff --git a/src/main/java/bomb/modules/t/the/bulb/TheBulbController.java b/src/main/java/bomb/modules/t/the/bulb/TheBulbController.java
index beab992e..d806382d 100644
--- a/src/main/java/bomb/modules/t/the/bulb/TheBulbController.java
+++ b/src/main/java/bomb/modules/t/the/bulb/TheBulbController.java
@@ -9,17 +9,17 @@
import java.util.List;
-import static bomb.modules.t.the.bulb.Bulb.Color.BLUE;
-import static bomb.modules.t.the.bulb.Bulb.Color.GREEN;
-import static bomb.modules.t.the.bulb.Bulb.Color.PURPLE;
-import static bomb.modules.t.the.bulb.Bulb.Color.RED;
-import static bomb.modules.t.the.bulb.Bulb.Color.WHITE;
-import static bomb.modules.t.the.bulb.Bulb.Color.YELLOW;
-import static bomb.modules.t.the.bulb.Bulb.Light.OFF;
-import static bomb.modules.t.the.bulb.Bulb.Light.ON;
-import static bomb.modules.t.the.bulb.Bulb.Opacity.OPAQUE;
-import static bomb.modules.t.the.bulb.Bulb.Opacity.TRANSLUCENT;
-import static bomb.modules.t.the.bulb.Bulb.Position.SCREWED;
+import static bomb.modules.t.the.bulb.BulbModel.Color.BLUE;
+import static bomb.modules.t.the.bulb.BulbModel.Color.GREEN;
+import static bomb.modules.t.the.bulb.BulbModel.Color.PURPLE;
+import static bomb.modules.t.the.bulb.BulbModel.Color.RED;
+import static bomb.modules.t.the.bulb.BulbModel.Color.WHITE;
+import static bomb.modules.t.the.bulb.BulbModel.Color.YELLOW;
+import static bomb.modules.t.the.bulb.BulbModel.Light.OFF;
+import static bomb.modules.t.the.bulb.BulbModel.Light.ON;
+import static bomb.modules.t.the.bulb.BulbModel.Opacity.OPAQUE;
+import static bomb.modules.t.the.bulb.BulbModel.Opacity.TRANSLUCENT;
+import static bomb.modules.t.the.bulb.BulbModel.Position.SCREWED;
public final class TheBulbController implements Resettable {
@FXML
@@ -46,7 +46,7 @@ private void enableSubmitButton() {
@FXML
private void submitBulbInfo() {
- Bulb input = new Bulb();
+ BulbModel input = new BulbModel();
input.setColor(retrieveColor());
input.setLight(retrieveLuminosity());
input.setOpacity(retrieveOpacity());
@@ -55,7 +55,7 @@ private void submitBulbInfo() {
outputToTextArea(TheBulb.solve(input));
}
- private Bulb.Color retrieveColor() {
+ private BulbModel.Color retrieveColor() {
String resultingColor = FacadeFX.getToggleName(colorGroup);
return switch(resultingColor) {
case "Red" -> RED;
@@ -67,12 +67,12 @@ private Bulb.Color retrieveColor() {
};
}
- private Bulb.Light retrieveLuminosity() {
+ private BulbModel.Light retrieveLuminosity() {
String resultingLight = FacadeFX.getToggleName(luminosityGroup);
return resultingLight.equals("Lit") ? ON : OFF;
}
- private Bulb.Opacity retrieveOpacity() {
+ private BulbModel.Opacity retrieveOpacity() {
String resultingOpacity = FacadeFX.getToggleName(opacityGroup);
return resultingOpacity.equals("Opaque") ? OPAQUE : TRANSLUCENT;
}
diff --git a/src/main/java/bomb/tools/boot/FxmlBootDrive.java b/src/main/java/bomb/tools/boot/FxmlBootDrive.java
new file mode 100644
index 00000000..a765239b
--- /dev/null
+++ b/src/main/java/bomb/tools/boot/FxmlBootDrive.java
@@ -0,0 +1,119 @@
+package bomb.tools.boot;
+
+import bomb.Widget;
+import bomb.annotation.DisplayComponent;
+import bomb.modules.ab.blind.alley.BlindAlley;
+import bomb.modules.ab.blind.alley.BlindAlleyController;
+import bomb.modules.s.souvenir.Souvenir;
+import bomb.modules.s.souvenir.SouvenirController;
+import bomb.tools.note.NoteController;
+import bomb.tools.pattern.facade.FacadeFX;
+import bomb.tools.pattern.observer.BlindAlleyPaneObserver;
+import bomb.tools.pattern.observer.ObserverHub;
+import bomb.tools.pattern.observer.ResetObserver;
+import bomb.tools.pattern.observer.SouvenirPaneObserver;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.layout.Region;
+import org.javatuples.Pair;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SequencedMap;
+
+import static bomb.tools.pattern.observer.ObserverHub.ObserverIndex.BLIND_ALLEY_PANE;
+import static bomb.tools.pattern.observer.ObserverHub.ObserverIndex.SOUVENIR_PANE;
+import static java.util.Arrays.asList;
+
+/**
+ * FxmlBootDrive uses the Adapter Pattern to perform the part of the boot sequence with the highest bottleneck in performance.
+ * The purpose for this set of classes is to have a way to quickly switch between methodologies for booting the program
+ * under different operating systems scenarios. As the number of FXML files for the project increases,
+ * maintaining a short boot time for this program will more become critical.
+ *
+ * The standard way uses a stream. This stream is sequential on Linux machines and parallel on Windows,
+ * thus using the thread pool initialized by Java. This means that performance is dependent on how many pooled threads
+ * can be created by the JVM.
+ *
+ * The new way uses Java 21's virtual threads so that we can see if there are any promising results in boot time.
+ * As of Oct 13, 2023 on Windows, the performance is comparable to the standard drive, perhaps slightly faster; however,
+ * it's not reliable. I.e. some runs will boot with no problem, and other runs will abruptly pause while loading FXML files.
+ * Reason is unknown, but more testing is required on other machines.
+ */
+public sealed interface FxmlBootDrive permits StandardFxmlBootDrive, VirtualThreadFxmlBootDrive {
+ String WIDGET_FILE = extractAssociatedFile(Widget.class);
+ String SOUVENIR_FILE = extractAssociatedFile(Souvenir.class);
+ String BLIND_ALLEY_FILE = extractAssociatedFile(BlindAlley.class);
+
+ Logger LOG = LoggerFactory.getLogger(FxmlBootDrive.class);
+ SequencedMap createFXMLMap(ResetObserver resetObserver);
+
+ @Contract(" -> new")
+ static @NotNull FxmlBootDrive createStandardDrive() {
+ return new StandardFxmlBootDrive();
+ }
+
+ @Contract(" -> new")
+ static @NotNull FxmlBootDrive createVirtualDrive() {
+ return new VirtualThreadFxmlBootDrive();
+ }
+
+ static @NotNull List> getAnnotatedClasses() {
+ var annotatedClasses = new ArrayList<>(List.of(Widget.class, NoteController.class));
+ var queue = new ArrayDeque<>(asList(Widget.class.getPermittedSubclasses()));
+
+ Class> temp;
+ while ((temp = queue.poll()) != null) {
+ Class>[] subclasses = temp.getPermittedSubclasses();
+ if (subclasses != null) {
+ queue.addAll(asList(subclasses));
+ }
+
+ if (temp.isAnnotationPresent(DisplayComponent.class)) {
+ annotatedClasses.add(temp);
+ }
+ }
+ return annotatedClasses;
+ }
+
+ static @NotNull Pair mapClassToRegion(@NotNull Class> clazz, ResetObserver resetObserver) {
+ DisplayComponent annotation = clazz.getAnnotation(DisplayComponent.class);
+ URL resource = clazz.getResource(annotation.resource());
+ String buttonLinkerName = annotation.buttonLinkerName();
+
+ return new Pair<>(
+ buttonLinkerName,
+ loadSingleRegion(new FXMLLoader(resource), resetObserver)
+ );
+ }
+
+ private static Region loadSingleRegion(FXMLLoader loader, ResetObserver resetObserver)
+ throws IllegalArgumentException {
+ Region output = FacadeFX.load(loader);
+ String location = loader.getLocation().toString();
+
+ if (!location.endsWith(WIDGET_FILE)) resetObserver.addController(loader);
+
+ if (location.endsWith(SOUVENIR_FILE)) loadSouvenirController(loader.getController());
+ else if (location.endsWith(BLIND_ALLEY_FILE)) loadBlindAlleyController(loader.getController());
+ return output;
+ }
+
+ private static void loadBlindAlleyController(BlindAlleyController controller) {
+ ObserverHub.addObserver(BLIND_ALLEY_PANE, new BlindAlleyPaneObserver(controller));
+ }
+
+ private static void loadSouvenirController(SouvenirController controller) {
+ ObserverHub.addObserver(SOUVENIR_PANE, new SouvenirPaneObserver(controller));
+ }
+
+ private static String extractAssociatedFile(Class> clazz) {
+ return clazz.getAnnotation(DisplayComponent.class)
+ .resource();
+ }
+}
diff --git a/src/main/java/bomb/tools/boot/StandardFxmlBootDrive.java b/src/main/java/bomb/tools/boot/StandardFxmlBootDrive.java
new file mode 100644
index 00000000..d1693176
--- /dev/null
+++ b/src/main/java/bomb/tools/boot/StandardFxmlBootDrive.java
@@ -0,0 +1,31 @@
+package bomb.tools.boot;
+
+import bomb.tools.pattern.observer.ResetObserver;
+import javafx.scene.layout.Region;
+import org.javatuples.Pair;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.LinkedHashMap;
+import java.util.SequencedMap;
+
+import static java.util.stream.Collectors.toMap;
+
+public final class StandardFxmlBootDrive implements FxmlBootDrive {
+ @SuppressWarnings("DataFlowIssue")
+ @Contract("_ -> new")
+ @Override
+ public @NotNull SequencedMap createFXMLMap(ResetObserver resetObserver) {
+ var displayClassStream = FxmlBootDrive.getAnnotatedClasses().parallelStream();
+
+ if (System.getProperty("os.name").toLowerCase().contains("linux")) {
+ displayClassStream = displayClassStream.sequential();
+ }
+
+ return new LinkedHashMap<>(displayClassStream
+ .map(cls -> FxmlBootDrive.mapClassToRegion(cls, resetObserver))
+ .collect(toMap(Pair::getValue0, Pair::getValue1)));
+ }
+
+ StandardFxmlBootDrive(){}
+}
diff --git a/src/main/java/bomb/tools/boot/VirtualThreadFxmlBootDrive.java b/src/main/java/bomb/tools/boot/VirtualThreadFxmlBootDrive.java
new file mode 100644
index 00000000..15a8e7ab
--- /dev/null
+++ b/src/main/java/bomb/tools/boot/VirtualThreadFxmlBootDrive.java
@@ -0,0 +1,47 @@
+package bomb.tools.boot;
+
+import bomb.tools.pattern.observer.ResetObserver;
+import javafx.scene.layout.Region;
+import org.javatuples.Pair;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.SequencedMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import static java.util.stream.Collectors.toMap;
+
+public final class VirtualThreadFxmlBootDrive implements FxmlBootDrive {
+ private static Pair extractFromFuture(Future> future) {
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ LOG.error("", e);
+ throw new IllegalStateException("Unexpected Boot Exception");
+ }
+ }
+
+ @Contract("_ -> new")
+ @Override
+ public @NotNull SequencedMap createFXMLMap(ResetObserver resetObserver) {
+ var annotatedClasses = FxmlBootDrive.getAnnotatedClasses();
+ var virtualThreadList = new ArrayList>>(annotatedClasses.size());
+
+ try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
+ for (var annotatedClass : annotatedClasses) {
+ var future = executor.submit(() -> FxmlBootDrive.mapClassToRegion(annotatedClass, resetObserver));
+ virtualThreadList.add(future);
+ }
+ }
+
+ return new LinkedHashMap<>(virtualThreadList.stream()
+ .map(VirtualThreadFxmlBootDrive::extractFromFuture)
+ .collect(toMap(Pair::getValue0, Pair::getValue1)));
+ }
+
+ VirtualThreadFxmlBootDrive(){}
+}
diff --git a/src/main/java/bomb/tools/data/structures/graph/list/ListGraph.java b/src/main/java/bomb/tools/data/structures/graph/list/ListGraph.java
index 92fa3f48..5dfb7851 100644
--- a/src/main/java/bomb/tools/data/structures/graph/list/ListGraph.java
+++ b/src/main/java/bomb/tools/data/structures/graph/list/ListGraph.java
@@ -2,30 +2,33 @@
import java.util.ArrayList;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.SequencedMap;
+import java.util.SequencedSet;
-public class ListGraph {
- private final LinkedHashMap> list;
- private final boolean biDirectional;
+public final class ListGraph {
+ private final SequencedMap> list;
+ private final boolean isBidirectional;
- public ListGraph(boolean biDirectional) {
- this.biDirectional = biDirectional;
+ public ListGraph(boolean isBidirectional) {
+ this.isBidirectional = isBidirectional;
list = new LinkedHashMap<>();
}
public void addVertex(E vertex) {
if (containsVertex(vertex)) return;
- list.put(vertex, new ArrayList<>());
+ list.put(vertex, new LinkedHashSet<>());
}
public void addEdge(E vertex, E edge) {
if (!containsVertex(vertex))
addVertex(vertex);
- if (biDirectional && !containsVertex(edge))
+ if (isBidirectional && !containsVertex(edge))
addVertex(edge);
if (isNotDuplicate(vertex, edge))
list.get(vertex).add(edge);
- if (biDirectional && isNotDuplicate(edge, vertex))
+ if (isBidirectional && isNotDuplicate(edge, vertex))
list.get(edge).add(vertex);
}
@@ -34,20 +37,20 @@ public boolean containsVertex(E vertex) {
}
public List getTargetVertices(E vertex) {
- return list.get(vertex);
+ return new ArrayList<>(list.get(vertex));
}
private boolean isNotDuplicate(E vertex, E edge) {
return !list.get(vertex).contains(edge);
}
- public List removeVertex(E vertex) {
+ public SequencedSet removeVertex(E vertex) {
if (!containsVertex(vertex)) return null;
- if (biDirectional) removeReferences(vertex, list.get(vertex));
+ if (isBidirectional) removeReferences(vertex, list.get(vertex));
return list.remove(vertex);
}
- private void removeReferences(E vertex, List refList) {
+ private void removeReferences(E vertex, SequencedSet refList) {
for (E reference : refList)
list.get(reference).remove(vertex);
}
diff --git a/src/main/java/bomb/tools/data/structures/queue/BufferedQueue.java b/src/main/java/bomb/tools/data/structures/queue/BufferedQueue.java
index 02db57c9..2fde5ccc 100644
--- a/src/main/java/bomb/tools/data/structures/queue/BufferedQueue.java
+++ b/src/main/java/bomb/tools/data/structures/queue/BufferedQueue.java
@@ -1,5 +1,6 @@
package bomb.tools.data.structures.queue;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.WeakReference;
@@ -14,7 +15,7 @@
import java.util.stream.Stream;
@SuppressWarnings({"unchecked", "NullableProblems"})
-public class BufferedQueue implements List, Iterable, RandomAccess {
+public final class BufferedQueue implements List, Iterable, RandomAccess {
private final int capacity;
private final ArrayDeque dataDeque;
@@ -39,6 +40,18 @@ public E get(int index) throws ArrayIndexOutOfBoundsException {
throw new ArrayIndexOutOfBoundsException();
}
+ @Contract(pure = true)
+ @Override
+ public @NotNull E getFirst() {
+ return dataDeque.getFirst();
+ }
+
+ @Contract(pure = true)
+ @Override
+ public @NotNull E getLast() {
+ return dataDeque.getLast();
+ }
+
public int size() {
return dataDeque.size();
}
diff --git a/src/main/java/bomb/tools/data/structures/ring/ArrayRing.java b/src/main/java/bomb/tools/data/structures/ring/ArrayRing.java
index 2943632b..4c269c9b 100644
--- a/src/main/java/bomb/tools/data/structures/ring/ArrayRing.java
+++ b/src/main/java/bomb/tools/data/structures/ring/ArrayRing.java
@@ -10,7 +10,7 @@
import static java.util.Arrays.asList;
-public class ArrayRing implements Iterable {
+public final class ArrayRing implements Iterable {
private final List internalStructure;
private int headIndex;
@@ -29,7 +29,7 @@ public ArrayRing(E @NotNull ... elements) {
}
public ArrayRing(@NotNull Collection c) {
- if (c.size() < 1)
+ if (c.isEmpty())
throw new IllegalArgumentException();
internalStructure = c instanceof ArrayList ?
(List) c :
@@ -87,7 +87,7 @@ public void rotateCounterClockwise(int rotations) {
}
@Override
- public Iterator iterator() {
+ public @NotNull Iterator iterator() {
return headIndex == 0 ?
internalStructure.iterator() :
reorderList().iterator();
diff --git a/src/main/java/bomb/tools/data/structures/trie/Trie.java b/src/main/java/bomb/tools/data/structures/trie/Trie.java
index 075e4f92..d2051b27 100644
--- a/src/main/java/bomb/tools/data/structures/trie/Trie.java
+++ b/src/main/java/bomb/tools/data/structures/trie/Trie.java
@@ -7,11 +7,11 @@
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Map;
+import java.util.SequencedMap;
import java.util.Set;
import java.util.TreeMap;
-public class Trie {
+public final class Trie {
private final TrieNode root;
public Trie() {
@@ -117,8 +117,8 @@ public String toString() {
return getWordsStartingWith("").toString();
}
- private static class TrieNode {
- private final Map children;
+ private static final class TrieNode {
+ private final SequencedMap children;
private boolean isEndOfWord;
public TrieNode() {
@@ -151,7 +151,7 @@ public boolean hasNoChild() {
}
public Character firstChild() {
- return children.keySet().iterator().next();
+ return children.sequencedKeySet().getFirst();
}
public void setEndOfWord(boolean isEndOfWord) {
diff --git a/src/main/java/bomb/tools/filter/Regex.java b/src/main/java/bomb/tools/filter/Regex.java
index 7f66deaa..b672d2cc 100644
--- a/src/main/java/bomb/tools/filter/Regex.java
+++ b/src/main/java/bomb/tools/filter/Regex.java
@@ -1,6 +1,7 @@
package bomb.tools.filter;
import org.intellij.lang.annotations.Language;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -126,8 +127,9 @@ public void reset() {
textMatcher.reset();
}
+ @Contract(pure = true)
@Override
- public String toString() {
+ public @NotNull String toString() {
return "Regex: " + regPattern.pattern();
}
@@ -136,11 +138,12 @@ public Stream stream() {
}
@Override
- public Iterator iterator() {
+ public @NotNull Iterator iterator() {
return RESULT_STREAM.apply(textMatcher).iterator();
}
- public Regex appendToPattern(@Language("regexp") @NotNull String pattern) {
+ @Contract("_ -> new")
+ public @NotNull Regex appendToPattern(@Language("regexp") @NotNull String pattern) {
return new Regex(this.regPattern.pattern() + pattern, regPattern.flags());
}
diff --git a/src/main/java/bomb/tools/note/NoteController.java b/src/main/java/bomb/tools/note/NoteController.java
index 2f4b851b..37578d0b 100644
--- a/src/main/java/bomb/tools/note/NoteController.java
+++ b/src/main/java/bomb/tools/note/NoteController.java
@@ -33,8 +33,9 @@ private void addNoteWindow() {
@Override
public void reset() {
- for (int i = extraNotes.size() - 1; i >= 0; i--)
- extraNotes.get(i).close();
+ for (var notePageController : extraNotes.reversed()) {
+ notePageController.close();
+ }
extraNotes.clear();
FacadeFX.clearMultipleTextFields(firstNote, secondNote, thirdNote, fourthNote, fifthNote);
}
diff --git a/src/main/java/bomb/tools/pattern/observer/ObserverHub.java b/src/main/java/bomb/tools/pattern/observer/ObserverHub.java
index c4028c29..518b5c8d 100644
--- a/src/main/java/bomb/tools/pattern/observer/ObserverHub.java
+++ b/src/main/java/bomb/tools/pattern/observer/ObserverHub.java
@@ -1,24 +1,58 @@
package bomb.tools.pattern.observer;
+import bomb.annotation.DisplayComponent;
+import bomb.modules.ab.blind.alley.BlindAlley;
+import bomb.modules.s.souvenir.Souvenir;
import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.EnumMap;
+import java.util.Map;
+
+import static bomb.tools.pattern.observer.ObserverHub.ObserverIndex.BLIND_ALLEY_PANE;
+import static bomb.tools.pattern.observer.ObserverHub.ObserverIndex.SOUVENIR_PANE;
public final class ObserverHub {
public enum ObserverIndex {
FORGET_ME_NOT_TOGGLE, SOUVENIR_TOGGLE, BLIND_ALLEY_PANE, SOUVENIR_PANE, RESET
}
+ private static final Logger LOG = LoggerFactory.getLogger(ObserverHub.class);
private static final EnumMap OBSERVER_MAP = new EnumMap<>(ObserverIndex.class);
+ private static final Map BUTTON_NAME_MAP = Map.of(
+ extractButtonLinkerName(BlindAlley.class), BLIND_ALLEY_PANE,
+ extractButtonLinkerName(Souvenir.class), SOUVENIR_PANE
+ );
+
+ private static String extractButtonLinkerName(Class> clazz) {
+ return clazz.getAnnotation(DisplayComponent.class)
+ .buttonLinkerName();
+ }
private ObserverHub() {
}
public static void addObserver(ObserverIndex index, Observer observer) {
+ if (OBSERVER_MAP.containsKey(index)) {
+ LOG.warn("{} value will be overwritten", index);
+ }
OBSERVER_MAP.put(index, observer);
}
public static void updateAtIndex(@NotNull ObserverIndex index) {
OBSERVER_MAP.get(index).update();
}
+
+ public static void scanButtonName(@NotNull String buttonName) {
+ if (BUTTON_NAME_MAP.containsKey(buttonName)) {
+ updateAtIndex(BUTTON_NAME_MAP.get(buttonName));
+ }
+ }
+
+ public static void ensureMapIsPopulated() {
+ if (ObserverIndex.values().length != OBSERVER_MAP.size()) {
+ LOG.warn("Observers not fully populated: {}", OBSERVER_MAP);
+ }
+ }
}
diff --git a/src/main/java/bomb/tools/pattern/observer/ResetObserver.java b/src/main/java/bomb/tools/pattern/observer/ResetObserver.java
index d37193d3..6e8beb32 100644
--- a/src/main/java/bomb/tools/pattern/observer/ResetObserver.java
+++ b/src/main/java/bomb/tools/pattern/observer/ResetObserver.java
@@ -3,11 +3,14 @@
import bomb.abstractions.Resettable;
import javafx.fxml.FXMLLoader;
import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public final class ResetObserver implements Observer {
+ private static final Logger LOG = LoggerFactory.getLogger(ResetObserver.class);
private final List controllerList;
public ResetObserver() {
@@ -19,6 +22,7 @@ public void addController(@NotNull FXMLLoader loader) {
Object controller = loader.getController();
if (controller == null) return;
controllerList.add((Resettable) controller);
+ LOG.debug("View of ResetObserver: {}", controllerList);
}
@Override
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 9a4e3da3..0588c4fb 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -5,6 +5,7 @@
requires com.opencsv;
requires com.jfoenix;
requires org.jgrapht.core;
+ requires org.slf4j;
requires javatuples;
requires MaterialFX;
requires org.jetbrains.annotations;
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 00000000..f34bcbcd
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+ %d{yyyy-MM-dd | HH:mm:ss} [%thread] %p | %logger{25} %m%n
+ utf8
+
+
+
+
+ logs/gradle-centurion.log
+
+ logs/gradle-centurion-%d{yyyy-MM-dd+HH:mm:ss}.log
+ 7
+
+
+ %d{yyyy-MM-dd | HH:mm:ss} %p [%t] %c{2} - %m%n
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/bomb/modules/ab/bitwise/BitwiseTest.java b/src/test/java/bomb/modules/ab/bitwise/BitwiseTest.java
index 9161d1f7..1f4248d5 100644
--- a/src/test/java/bomb/modules/ab/bitwise/BitwiseTest.java
+++ b/src/test/java/bomb/modules/ab/bitwise/BitwiseTest.java
@@ -88,19 +88,19 @@ public void maximumConditionTest(String expected, LogicOperator operation) {
assertEquals(Bitwise.getByte(operation), expected);
}
- private void setEssentialTrueConditions() {
+ private static void setEssentialTrueConditions() {
Widget.setSerialCode(LAST_DIGIT_ODD);
Widget.setStartTime(DEFAULT_START_TIME);
Widget.setNumModules(6);
}
- private void setEssentialFalseConditions() {
+ private static void setEssentialFalseConditions() {
Widget.setSerialCode(LAST_DIGIT_EVEN);
Widget.setStartTime(DEFAULT_START_TIME);
Widget.setNumModules(1);
}
- private void maximizeConditions() {
+ private static void maximizeConditions() {
Widget.setPortValue(PARALLEL, 3);
Widget.setIndicator(ON, BOB);
Widget.setIndicator(ON, NSA);
diff --git a/src/test/java/bomb/modules/il/laundry/LaundryTest.java b/src/test/java/bomb/modules/il/laundry/LaundryTest.java
index aa882921..a507e3f2 100644
--- a/src/test/java/bomb/modules/il/laundry/LaundryTest.java
+++ b/src/test/java/bomb/modules/il/laundry/LaundryTest.java
@@ -22,7 +22,7 @@ public void methodSetup() {
}
@DataProvider
- public Object[][] exceptionProvider() {
+ public Object[][] illegalArgExceptionProvider() {
ConditionSetter setSerial = () -> Widget.setSerialCode("ajwf45");
return new Object[][]{
{EMPTY_SETTER, "1", "1"}, {setSerial, "", "1"}, {EMPTY_SETTER, "1", ""},
@@ -30,8 +30,23 @@ public Object[][] exceptionProvider() {
};
}
- @Test(dataProvider = "exceptionProvider", expectedExceptions = IllegalArgumentException.class)
- public void exceptionTest(ConditionSetter setter, String solved, String needy) {
+ @Test(dataProvider = "illegalArgExceptionProvider", expectedExceptions = IllegalArgumentException.class)
+ public void illegalArgExceptionTest(ConditionSetter setter, String solved, String needy) {
+ setter.setCondition();
+ Laundry.clean(solved, needy);
+ }
+
+ @DataProvider
+ public Object[][] numberFormatExceptionProvider() {
+ ConditionSetter setSerial = () -> Widget.setSerialCode("ajwf45");
+ return new Object[][]{
+ {setSerial, "abc", "1"},
+ {setSerial, "1", "abc"}
+ };
+ }
+
+ @Test(dataProvider = "numberFormatExceptionProvider", expectedExceptions = NumberFormatException.class)
+ public void numberFormatExceptionTest(ConditionSetter setter, String solved, String needy) {
setter.setCondition();
Laundry.clean(solved, needy);
}
diff --git a/src/test/java/bomb/modules/t/the/bulb/TheBulbTest.java b/src/test/java/bomb/modules/t/the/bulb/TheBulbTest.java
index f3edf8c8..c708ccd9 100644
--- a/src/test/java/bomb/modules/t/the/bulb/TheBulbTest.java
+++ b/src/test/java/bomb/modules/t/the/bulb/TheBulbTest.java
@@ -19,17 +19,17 @@
import static bomb.enumerations.Indicator.IND;
import static bomb.enumerations.Indicator.NSA;
import static bomb.enumerations.Indicator.SIG;
-import static bomb.modules.t.the.bulb.Bulb.Color.BLUE;
-import static bomb.modules.t.the.bulb.Bulb.Color.GREEN;
-import static bomb.modules.t.the.bulb.Bulb.Color.PURPLE;
-import static bomb.modules.t.the.bulb.Bulb.Color.WHITE;
-import static bomb.modules.t.the.bulb.Bulb.Color.YELLOW;
-import static bomb.modules.t.the.bulb.Bulb.Light.OFF;
-import static bomb.modules.t.the.bulb.Bulb.Light.ON;
-import static bomb.modules.t.the.bulb.Bulb.Opacity.OPAQUE;
-import static bomb.modules.t.the.bulb.Bulb.Opacity.TRANSLUCENT;
-import static bomb.modules.t.the.bulb.Bulb.Position.SCREWED;
-import static bomb.modules.t.the.bulb.Bulb.Position.UNSCREWED;
+import static bomb.modules.t.the.bulb.BulbModel.Color.BLUE;
+import static bomb.modules.t.the.bulb.BulbModel.Color.GREEN;
+import static bomb.modules.t.the.bulb.BulbModel.Color.PURPLE;
+import static bomb.modules.t.the.bulb.BulbModel.Color.WHITE;
+import static bomb.modules.t.the.bulb.BulbModel.Color.YELLOW;
+import static bomb.modules.t.the.bulb.BulbModel.Light.OFF;
+import static bomb.modules.t.the.bulb.BulbModel.Light.ON;
+import static bomb.modules.t.the.bulb.BulbModel.Opacity.OPAQUE;
+import static bomb.modules.t.the.bulb.BulbModel.Opacity.TRANSLUCENT;
+import static bomb.modules.t.the.bulb.BulbModel.Position.SCREWED;
+import static bomb.modules.t.the.bulb.BulbModel.Position.UNSCREWED;
import static bomb.modules.t.the.bulb.TheBulb.PRESS_I;
import static bomb.modules.t.the.bulb.TheBulb.PRESS_O;
import static bomb.modules.t.the.bulb.TheBulb.SCREW;
@@ -51,15 +51,15 @@ public Object[][] exceptionTestProvider() {
}
@Test(dataProvider = "exceptionTestProvider", expectedExceptions = IllegalArgumentException.class)
- public void exceptionTest(Bulb.Position position, Bulb.Light inputLight,
- Bulb.Color inputColor, Bulb.Opacity inputOpacity) {
- Bulb testBulb = new Bulb();
- testBulb.setPosition(position);
- testBulb.setOpacity(inputOpacity);
- testBulb.setLight(inputLight);
- testBulb.setColor(inputColor);
-
- TheBulb.solve(testBulb);
+ public void exceptionTest(BulbModel.Position position, BulbModel.Light inputLight,
+ BulbModel.Color inputColor, BulbModel.Opacity inputOpacity) {
+ BulbModel testBulbModel = new BulbModel();
+ testBulbModel.setPosition(position);
+ testBulbModel.setOpacity(inputOpacity);
+ testBulbModel.setLight(inputLight);
+ testBulbModel.setColor(inputColor);
+
+ TheBulb.solve(testBulbModel);
}
@DataProvider
@@ -87,20 +87,20 @@ public Object[][] trainingVideoTestProvider() {
}
@Test(dataProvider = "trainingVideoTestProvider")
- public void trainingVideoTest(ConditionSetter bombConditions, Bulb.Light inputLight,
- Bulb.Color inputColor, Bulb.Opacity inputOpacity,
+ public void trainingVideoTest(ConditionSetter bombConditions, BulbModel.Light inputLight,
+ BulbModel.Color inputColor, BulbModel.Opacity inputOpacity,
String[] expectedResults) {
bombConditions.setCondition();
- Bulb testBulb = new Bulb();
- testBulb.setPosition(SCREWED);
- testBulb.setOpacity(inputOpacity);
- testBulb.setLight(inputLight);
- testBulb.setColor(inputColor);
+ BulbModel testBulbModel = new BulbModel();
+ testBulbModel.setPosition(SCREWED);
+ testBulbModel.setOpacity(inputOpacity);
+ testBulbModel.setLight(inputLight);
+ testBulbModel.setColor(inputColor);
List convertedResults = Arrays.asList(expectedResults);
- assertEquals(TheBulb.solve(testBulb), convertedResults);
+ assertEquals(TheBulb.solve(testBulbModel), convertedResults);
}
@DataProvider
@@ -133,20 +133,20 @@ public Object[][] writtenTestProvider() {
}
@Test(dataProvider = "writtenTestProvider")
- public void writtenTest(ConditionSetter bombConditions, Bulb.Light inputLight,
- Bulb.Color inputColor, Bulb.Opacity inputOpacity,
+ public void writtenTest(ConditionSetter bombConditions, BulbModel.Light inputLight,
+ BulbModel.Color inputColor, BulbModel.Opacity inputOpacity,
String[] expectedResults) {
bombConditions.setCondition();
- Bulb testBulb = new Bulb();
- testBulb.setPosition(SCREWED);
- testBulb.setOpacity(inputOpacity);
- testBulb.setLight(inputLight);
- testBulb.setColor(inputColor);
+ BulbModel testBulbModel = new BulbModel();
+ testBulbModel.setPosition(SCREWED);
+ testBulbModel.setOpacity(inputOpacity);
+ testBulbModel.setLight(inputLight);
+ testBulbModel.setColor(inputColor);
List convertedResults = Arrays.asList(expectedResults);
- assertEquals(TheBulb.solve(testBulb), convertedResults);
+ assertEquals(TheBulb.solve(testBulbModel), convertedResults);
}
@AfterClass