diff --git a/assignments/nbproject/project.properties b/assignments/nbproject/project.properties
index 8423aa450053a37e372c3f6f2c9c2f5dd69ed33d..07acdd81b4036da91bc4dfdfba023dd979b93e8c 100644
--- a/assignments/nbproject/project.properties
+++ b/assignments/nbproject/project.properties
@@ -1,135 +1,135 @@
-annotation.processing.enabled=true
-annotation.processing.enabled.in.editor=false
-annotation.processing.processors.list=
-annotation.processing.run.all.processors=true
-annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
-application.desc=Student assignments performed as part of NPS course Networked Graphics MV3500.  This course is an introduction to network communications in simulation applications. Topics include an introduction to the TCP/IP protocol stack; TCP/IP socket communications, including TCP, UDP, and multicast; and protocol design issues, with emphasis on Distributed Interactive Simulation (DIS) Protocol and High Level Architecture (HLA). Course emphasis is on creation and testing of network programming network code and web-browser applications.
-application.homepage=https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/assignments
-application.splash=../..\\NetworkedGraphicsMV3500\\documentation\\images\\OpenDisSurferDude.png
-application.title=NPS Networked Graphics MV3500 assignments
-application.vendor=Don Brutzman
-auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml
-build.classes.dir=${build.dir}/classes
-build.classes.excludes=**/*.java,**/*.form
-# This directory is removed when the project is cleaned:
-build.dir=build
-build.generated.dir=${build.dir}/generated
-build.generated.sources.dir=${build.dir}/generated-sources
-# Only compile against the classpath explicitly listed here:
-build.sysclasspath=ignore
-build.test.classes.dir=${build.dir}/test/classes
-build.test.results.dir=${build.dir}/test/results
-# Uncomment to specify the preferred debugger connection transport:
-#debug.transport=dt_socket
-debug.classpath=\
-    ${run.classpath}
-debug.modulepath=\
-    ${run.modulepath}
-debug.test.classpath=\
-    ${run.test.classpath}
-debug.test.modulepath=\
-    ${run.test.modulepath}
-# Files in build.classes.dir which should be excluded from distribution jar
-# Avoid compilation or inclusion of student project depending on mutex libraries only available in JDK8
-# https://stackoverflow.com/questions/27906896/exclude-package-from-build-but-not-from-view-in-netbeans-8
-excludes=**/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/**
-dist.archive.excludes=**/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/**
-
-# This directory is removed when the project is cleaned:
-dist.dir=dist
-dist.jar=${dist.dir}/Networked_Graphics_MV3500_assignments.jar
-dist.javadoc.dir=${dist.dir}/javadoc
-endorsed.classpath=
-file.reference.dis-enums-1.3.jar=../lib/dis-enums-1.3.jar
-file.reference.opendis7-full.jar=../lib/opendis7-full.jar
-file.reference.open-dis_4.16.jar=../lib/open-dis_4.16.jar
-file.reference.simkit-doc.zip=../lib/simkit-doc.zip
-file.reference.simkit-src.zip=../lib/simkit-src.zip
-file.reference.simkit.jar=../lib/simkit.jar
-#file.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-classes.jar
-#file.reference.opendis7-pdus-classes.jar=../lib/opendis7-pdus-classes.jar
-includes=**
-jar.archive.disabled=${jnlp.enabled}
-jar.compress=false
-jar.index=${jnlp.enabled}
-javac.classpath=\
-    ${file.reference.opendis7-full.jar}:\
-    ${file.reference.dis-enums-1.3.jar}:\
-    ${file.reference.open-dis_4.16.jar}:\
-    ${file.reference.simkit-doc.zip}:\
-    ${file.reference.simkit-src.zip}:\
-    ${file.reference.simkit.jar}
-#   ${file.reference.opendis7-enumerations-classes.jar}:\
-#   ${file.reference.opendis7-pdus-classes.jar}:\
-
-# Space-separated list of extra javac options
-javac.compilerargs=-Xlint:deprecation -Xlint:unchecked
-javac.deprecation=false
-javac.external.vm=true
-javac.modulepath=
-javac.processormodulepath=
-javac.processorpath=\
-    ${javac.classpath}
-javac.source=20
-javac.target=20
-javac.test.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}
-javac.test.modulepath=\
-    ${javac.modulepath}
-javac.test.processorpath=\
-    ${javac.test.classpath}
-javadoc.additionalparam=-header "NPS Networked Graphics MV3500 Assignments"
-javadoc.author=true
-javadoc.encoding=${source.encoding}
-javadoc.html5=false
-javadoc.noindex=false
-javadoc.nonavbar=false
-javadoc.notree=false
-javadoc.private=false
-#javadoc.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-javadoc.jar
-javadoc.splitindex=true
-javadoc.use=true
-javadoc.version=false
-javadoc.windowtitle=MV3500 Assignments
-jlink.launcher=false
-jlink.launcher.name=Networked_Graphics_MV3500_assignments
-jnlp.codebase.type=no.codebase
-jnlp.descriptor=application
-jnlp.enabled=false
-jnlp.mixed.code=default
-jnlp.offline-allowed=false
-jnlp.signed=false
-jnlp.signing=
-jnlp.signing.alias=
-jnlp.signing.keystore=
-# Optional override of default Application-Library-Allowable-Codebase attribute identifying the locations where your signed RIA is expected to be found.
-manifest.custom.application.library.allowable.codebase=
-# Optional override of default Caller-Allowable-Codebase attribute identifying the domains from which JavaScript code can make calls to your RIA without security prompts.
-manifest.custom.caller.allowable.codebase=
-# Optional override of default Codebase manifest attribute, use to prevent RIAs from being repurposed
-manifest.custom.codebase=
-# Optional override of default Permissions manifest attribute (supported values: sandbox, all-permissions)
-manifest.custom.permissions=
-meta.inf.dir=${src.dir}/META-INF
-mkdist.disabled=false
-platform.active=JDK_22
-project.licensePath=../license.txt
-run.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}
-# Space-separated list of JVM arguments used when running the project.
-# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
-# To set system properties for unit tests define test-sys-prop.name=value:
-run.jvmargs=
-run.modulepath=\
-    ${javac.modulepath}
-run.test.classpath=\
-    ${javac.test.classpath}:\
-    ${build.test.classes.dir}
-run.test.modulepath=\
-    ${javac.test.modulepath}
-source.encoding=UTF-8
-#source.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-source.jar
-src.dir=src
-test.src.dir=test
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+application.desc=Student assignments performed as part of NPS course Networked Graphics MV3500.  This course is an introduction to network communications in simulation applications. Topics include an introduction to the TCP/IP protocol stack; TCP/IP socket communications, including TCP, UDP, and multicast; and protocol design issues, with emphasis on Distributed Interactive Simulation (DIS) Protocol and High Level Architecture (HLA). Course emphasis is on creation and testing of network programming network code and web-browser applications.
+application.homepage=https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/assignments
+application.splash=../..\\NetworkedGraphicsMV3500\\documentation\\images\\OpenDisSurferDude.png
+application.title=NPS Networked Graphics MV3500 assignments
+application.vendor=Don Brutzman
+auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+    ${run.classpath}
+debug.modulepath=\
+    ${run.modulepath}
+debug.test.classpath=\
+    ${run.test.classpath}
+debug.test.modulepath=\
+    ${run.test.modulepath}
+# Files in build.classes.dir which should be excluded from distribution jar
+# Avoid compilation or inclusion of student project depending on mutex libraries only available in JDK8
+# https://stackoverflow.com/questions/27906896/exclude-package-from-build-but-not-from-view-in-netbeans-8
+excludes=**/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/**
+dist.archive.excludes=**/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/**
+
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/Networked_Graphics_MV3500_assignments.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+endorsed.classpath=
+file.reference.dis-enums-1.3.jar=../lib/dis-enums-1.3.jar
+file.reference.opendis7-full.jar=../lib/opendis7-full.jar
+file.reference.open-dis_4.16.jar=../lib/open-dis_4.16.jar
+file.reference.simkit-doc.zip=../lib/simkit-doc.zip
+file.reference.simkit-src.zip=../lib/simkit-src.zip
+file.reference.simkit.jar=../lib/simkit.jar
+#file.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-classes.jar
+#file.reference.opendis7-pdus-classes.jar=../lib/opendis7-pdus-classes.jar
+includes=**
+jar.archive.disabled=${jnlp.enabled}
+jar.compress=false
+jar.index=${jnlp.enabled}
+javac.classpath=\
+    ${file.reference.opendis7-full.jar}:\
+    ${file.reference.dis-enums-1.3.jar}:\
+    ${file.reference.open-dis_4.16.jar}:\
+    ${file.reference.simkit-doc.zip}:\
+    ${file.reference.simkit-src.zip}:\
+    ${file.reference.simkit.jar}
+#   ${file.reference.opendis7-enumerations-classes.jar}:\
+#   ${file.reference.opendis7-pdus-classes.jar}:\
+
+# Space-separated list of extra javac options
+javac.compilerargs=-Xlint:deprecation -Xlint:unchecked
+javac.deprecation=false
+javac.external.vm=true
+javac.modulepath=
+javac.processormodulepath=
+javac.processorpath=\
+    ${javac.classpath}
+javac.source=20
+javac.target=20
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+javac.test.modulepath=\
+    ${javac.modulepath}
+javac.test.processorpath=\
+    ${javac.test.classpath}
+javadoc.additionalparam=-header "NPS Networked Graphics MV3500 Assignments"
+javadoc.author=true
+javadoc.encoding=${source.encoding}
+javadoc.html5=false
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+#javadoc.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-javadoc.jar
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=MV3500 Assignments
+jlink.launcher=false
+jlink.launcher.name=Networked_Graphics_MV3500_assignments
+jnlp.codebase.type=no.codebase
+jnlp.descriptor=application
+jnlp.enabled=false
+jnlp.mixed.code=default
+jnlp.offline-allowed=false
+jnlp.signed=false
+jnlp.signing=
+jnlp.signing.alias=
+jnlp.signing.keystore=
+# Optional override of default Application-Library-Allowable-Codebase attribute identifying the locations where your signed RIA is expected to be found.
+manifest.custom.application.library.allowable.codebase=
+# Optional override of default Caller-Allowable-Codebase attribute identifying the domains from which JavaScript code can make calls to your RIA without security prompts.
+manifest.custom.caller.allowable.codebase=
+# Optional override of default Codebase manifest attribute, use to prevent RIAs from being repurposed
+manifest.custom.codebase=
+# Optional override of default Permissions manifest attribute (supported values: sandbox, all-permissions)
+manifest.custom.permissions=
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+project.licensePath=../license.txt
+run.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.modulepath=\
+    ${javac.modulepath}
+run.test.classpath=\
+    ${javac.test.classpath}:\
+    ${build.test.classes.dir}
+run.test.modulepath=\
+    ${javac.test.modulepath}
+source.encoding=UTF-8
+#source.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-source.jar
+src.dir=src
+test.src.dir=test
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java
index 06a372d9f6394cac53da5640e4daac81681defc9..5a98f34dc5bb592ce709d0c6f2bd9e3f6e8c75a1 100644
--- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java
@@ -7,7 +7,7 @@ import java.time.DayOfWeek;
 //import java.time.LocalTime; // conversion?
 
 /**
- * This client program establishes a socket connection to the {@link RomeroServerHW2},
+ * This client program establishes a socket connection to the RomeroServerHW2,
  * then checks how long it takes to read the single line it expects as a server response.
  * 
  * @author Don McGregor
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroHandlerThreadHW2.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroHandlerThreadHW2.java
index dfbaa2e74887ade019c42dc1c963b2d5ee310770..7094cce19dbf87198ef6421cf91fbabcd3a3e782 100644
--- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroHandlerThreadHW2.java
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroHandlerThreadHW2.java
@@ -5,7 +5,7 @@ import java.net.*;
 
 /**
  * <p>
- * This utility class supports the {@link RomeroServerHW2} program,
+ * This utility class supports the RomeroServerHW2 program,
  * handling all programming logic needed for a new socket connection
  * to run in a thread of its own. This is the server
  * portion as well, so we artificially invent what happens
@@ -43,7 +43,6 @@ public class RomeroHandlerThreadHW2 extends Thread
     }
     
     /** Handles one connection
-     * @overriding run() method in Java Thread class is deliberate
      */
     @Override
     public void run()
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/ExampleSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/BavlsikSimulationProgram.java
similarity index 98%
rename from assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/ExampleSimulationProgram.java
rename to assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/BavlsikSimulationProgram.java
index 6372a714e6a04a55eb71c38868c54acfa5ec9a21..21463b4b64c6d4eb2a053c2a1898c19a55037271 100644
--- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/ExampleSimulationProgram.java
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/BavlsikSimulationProgram.java
@@ -3,7 +3,7 @@
  * This work is provided under a BSD open-source license, see project license.html or license.txt
  * @author brutzman@nps.edu
  */
-package MV3500Cohort2024JulySeptember.homework3.Romero;
+package MV3500Cohort2024JulySeptember.homework3.Bavlsik;
 
 import edu.nps.moves.dis7.entities.swe.platform.surface._001Poseidon;
 import edu.nps.moves.dis7.entities.swe.platform.surface._002Triton;
@@ -25,7 +25,7 @@ import java.util.logging.Logger;
  *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramWireshark.png" target="_blank">ExampleSimulationProgramWireshark.png</a>
  *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramSequenceDiagram.png" target="_blank">ExampleSimulationProgramSequenceDiagram.png</a>
  */
-public class ExampleSimulationProgram
+public class BavlsikSimulationProgram
 {
     /* **************************** infrastructure code, modification is seldom needed ************************* */
                  
@@ -72,7 +72,7 @@ public class ExampleSimulationProgram
      */
     // base constructor is not invoked automatically by other constructors
     // https://stackoverflow.com/questions/581873/best-way-to-handle-multiple-constructors-in-java
-    public ExampleSimulationProgram()
+    public BavlsikSimulationProgram()
     {
         initialize();
     }
@@ -80,7 +80,7 @@ public class ExampleSimulationProgram
      * Constructor to create an instance of this class.
      * @param newDescriptor describes this program, useful for logging and debugging
      */
-    public ExampleSimulationProgram(String newDescriptor)
+    public BavlsikSimulationProgram(String newDescriptor)
     {
         descriptor = newDescriptor;
         initialize();
@@ -90,7 +90,7 @@ public class ExampleSimulationProgram
      * @param address network address to use
      * @param port corresponding network port to use
      */
-    public ExampleSimulationProgram(String address, int port)
+    public BavlsikSimulationProgram(String address, int port)
     {
         disChannel.setNetworkAddress            (address);
         disChannel.setNetworkPort               (port);
@@ -299,7 +299,7 @@ public class ExampleSimulationProgram
       } 
       catch (InterruptedException iex) // handle any exception that your code might choose to provoke!
       {
-        Logger.getLogger(ExampleSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
+        Logger.getLogger(BavlsikSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
       }
     }
 
@@ -386,7 +386,7 @@ public class ExampleSimulationProgram
     }
     
     /** Locally instantiable copy of program, can be subclassed. */
-    protected static ExampleSimulationProgram thisProgram;
+    protected static BavlsikSimulationProgram thisProgram;
   
     /**
      * Main method is first executed when a program instance is loaded.
@@ -396,7 +396,7 @@ public class ExampleSimulationProgram
      */
     public static void main(String[] args)
     {
-        thisProgram = new ExampleSimulationProgram("test constructor"); // create instance of self within static main() method
+        thisProgram = new BavlsikSimulationProgram("test constructor"); // create instance of self within static main() method
         
         thisProgram.disChannel.printlnTRACE("main() started...");
         
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c5aadebfdcbc089649b153eb705bb84c6286336b
--- /dev/null
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/README.md
@@ -0,0 +1,38 @@
+## Homework 3: Example Simulation Recording using OpenDIS Network Streams
+
+<!-- Viewable at https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/assignments/src/MV3500Cohort2024JulySeptember/homework3/README.md -->
+
+### Assignment
+
+1. Adapt the functionality for [OpenDIS ExampleSimulationProgram](../../../../examples/src/OpenDis7Examples/ExampleSimulationProgram.java), modifying provided code
+2. Experiment with the enumeration values that set up each entity and PDU.  What works for you?  What makes sense for your future work?
+3. Adapt or replace the UML diagrams to describe what you have going on.
+4. Record, save and replay your result stream using [PduRecorder](https://savage.nps.edu/opendis7-java/javadoc/edu/nps/moves/dis7/utilities/stream/PduRecorder.html) or [Wireshark](https://www.wireshark.org)
+   * see local [assignments/src/pduLog](../../../pduLog) subdirectory for latest opendis log files
+   * Coming soon, we will also (again have) [X3D-Edit](https://savage.nps.edu/X3D-Edit) for DIS stream recording/replay
+5. Observe good-practice conventions in the [assignments README](../../../README.md) and [current-course README](../README.md) instructions.
+
+This assignment  presents a Problem Prototyping opportunity.
+While some minimal functionality is expected, the general outline of
+a networking problem and proposed solution holds great interest.
+Think of it as warmup preparation for your future work.
+
+This is also a freeplay opportunity. 
+You have the option to pick one or more of the provided course example programs 
+and adapt the source to demonstrate a new client-server handshake protocol of interest.
+
+Be sure to provide a rationale that justifies why the networking choices you made
+(TCP/UDP, unicast/multicast, etc.) are the best for the problem you are addressing.
+
+You may find that the prior [homework2 README](../homework2/README.md) still provides
+helpful details on what specific deliverables are expected in each homework assignment.
+
+Team efforts are encouraged, though if you choose a team approach be sure to justify why.
+This is a good warmup prior to final projects. Have fun with Java networking!
+
+### Prior Assignment, August 2019
+
+In 2019, students worked together on a single project to check wireless multicast connectivity recently deployed on NPS campus.  
+
+See their experimental results in the [NPS Multicast Connectivity Report](../../MV3500Cohort2019JulySeptember/homework3).
+
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/package-info.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..60e975bc003dc076eb78b534de856d790eac1561
--- /dev/null
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Bavlsik/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * Final project assignments supporting the NPS MOVES MV3500 Networked Graphics course.
+ * 
+ * @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/assignments" target="_blank">networkedGraphicsMV3500 assignments</a>
+ * @see java.lang.Package
+ * @see <a href="https://stackoverflow.com/questions/22095487/why-is-package-info-java-useful" target="_blank">StackOverflow: why-is-package-info-java-useful</a>
+ * @see <a href="https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java" target="_blank">StackOverflow: how-do-i-document-packages-in-java</a>
+ */
+
+package MV3500Cohort2024JulySeptember.homework3.Bavlsik;
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/LennonSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/LennonSimulationProgram.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e5c65a0b2f97634f6b851f69af48c13eec3e490
--- /dev/null
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/LennonSimulationProgram.java
@@ -0,0 +1,491 @@
+/**
+ * Copyright (c) 2008-2023, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
+ * This work is provided under a BSD open-source license, see project license.html or license.txt
+ * @author brutzman@nps.edu
+ */
+package MV3500Cohort2024JulySeptember.homework3.Lennon;
+
+import edu.nps.moves.dis7.entities.swe.platform.surface._001Poseidon;
+import edu.nps.moves.dis7.entities.swe.platform.surface._002Triton;
+import edu.nps.moves.dis7.enumerations.*;
+import edu.nps.moves.dis7.pdus.*;
+import edu.nps.moves.dis7.utilities.DisChannel;
+import edu.nps.moves.dis7.utilities.PduFactory;
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.Scanner;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/** The purpose of this inheritable class is to provide an easily modifiable 
+ *  example simulation program that includes DIS-capable entities performing 
+ *  tasks of interest, and then reporting activity via PDUs to the network.
+ *  Default program initialization includes PDU recording turned on by default.
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramLog.txt" target="_blank">ExampleSimulationProgramLog.txt</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramPduCaptureLog.dislog" target="_blank">ExampleSimulationProgramPduCaptureLog.dislog</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramFlowDiagram.pdf" target="_blank">ExampleSimulationProgramFlowDiagram.pdf</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramWireshark.png" target="_blank">ExampleSimulationProgramWireshark.png</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramSequenceDiagram.png" target="_blank">ExampleSimulationProgramSequenceDiagram.png</a>
+ */
+public class LennonSimulationProgram
+{
+    /* **************************** infrastructure code, modification is seldom needed ************************* */
+                 
+    private   String     descriptor = this.getClass().getSimpleName();
+    /** DIS channel defined by network address/port combination includes multiple utility capabilities */
+    protected DisChannel disChannel;
+    /** Factory object used to create new PDU instances */
+    protected PduFactory pduFactory;
+    
+    /** seconds per loop for real-time or simulation execution */
+    private double  simulationTimeStepDuration  =  1.0; // seconds TODO encapsulate
+    /** initial simulation time in seconds */
+    double  simulationTimeInitial = 0.0;
+    /** current simulation time in seconds */
+    double  simulationTimeSeconds = simulationTimeInitial;
+    /** Maximum number of simulation loops */
+    int MAX_LOOP_COUNT = 4;
+    
+    String narrativeMessage1 = new String();
+    String narrativeMessage2 = new String();
+    String narrativeMessage3 = new String();
+    
+    /** EntityID settings for entity 1 */
+    protected EntityID           entityID_1          = new EntityID();
+    /** EntityID settings for entity 2 */
+    protected EntityID           entityID_2          = new EntityID();
+    /** ESPDU for entity 1 */
+    protected EntityStatePdu     entityStatePdu_1;
+    /** ESPDU for entity 2 */
+    protected EntityStatePdu     entityStatePdu_2;
+    /** FirePdu for entity 1 first  weapon (if any) */
+    protected FirePdu            firePdu_1a;
+    /** FirePdu for entity 1 second weapon (if any) */
+    protected FirePdu            firePdu_1b;
+    /** MunitionDescriptor for these weapons */
+    protected MunitionDescriptor munitionDescriptor1;
+    
+    // hey programmer, what other state do you want?  this is a good place to declare it...
+    
+    /**
+     * Constructor to create an instance of this class.
+     * Design goal: additional built-in initialization conveniences can go here
+     * to keep your efforts focused on the runSimulation() method.
+     */
+    // base constructor is not invoked automatically by other constructors
+    // https://stackoverflow.com/questions/581873/best-way-to-handle-multiple-constructors-in-java
+    public LennonSimulationProgram()
+    {
+        initialize();
+    }
+    /**
+     * Constructor to create an instance of this class.
+     * @param newDescriptor describes this program, useful for logging and debugging
+     */
+    public LennonSimulationProgram(String newDescriptor)
+    {
+        descriptor = newDescriptor;
+        initialize();
+    }
+    /**
+     * Utility Constructor that allows your example simulation program to override default network address and port
+     * @param address network address to use
+     * @param port corresponding network port to use
+     */
+    public LennonSimulationProgram(String address, int port)
+    {
+        disChannel.setNetworkAddress            (address);
+        disChannel.setNetworkPort               (port);
+        disChannel.setVerboseComments           (true);       // TODO rename library method to disambiguate CommentPDU
+                                                                            // TODO still seems really chatty... add silent mode?
+        disChannel.setVerboseDisNetworkInterface(true);  // Default false
+        disChannel.setVerbosePduRecorder        (true);       // default false
+        initialize();
+    }
+    
+    /** Initialize channel setup for OpenDis7 and report a test PDU
+     * @see initializeDisChannel
+     * @see initializeSimulationEntities */
+    private void initialize()
+    {
+        initializeDisChannel(); // must come first, uses PduFactory
+        
+        initializeSimulationEntities(); // set unchanging parameters
+        
+        disChannel.join(); // TODO further functionality expected
+        
+        String timeStepMessage = "Simulation timestep duration " + getSimulationTimeStepDuration() + " seconds";
+        disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_SIMULATION_TIMESTEP, timeStepMessage);
+        // additional constructor initialization can go here
+    }
+    
+    /** Initialize channel setup for OpenDis7 and report a test PDU */
+    private void initializeDisChannel()
+    {
+        if (disChannel == null)
+            disChannel = new DisChannel();
+        else
+        {
+            disChannel.printlnTRACE ("*** warning, duplicate invocation of initializeDisChannel() ignored");
+            return;
+        }
+        pduFactory     = disChannel.getPduFactory();
+        disChannel.setDescriptor(this.getClass().getSimpleName()); // ExampleSimulationProgram might be a superclass
+        disChannel.setUpNetworkInterface();
+        disChannel.printlnTRACE ("just checking: disChannel.getNetworkAddress()=" + disChannel.getNetworkAddress() +
+                                                         ", getNetworkPort()="    + disChannel.getNetworkPort());
+        disChannel.getDisNetworkInterface().setVerbose(true); // sending and receipt
+        disChannel.printlnTRACE ("just checking: hasVerboseSending()=" + disChannel.getDisNetworkInterface().hasVerboseSending() +
+                                              ", hasVerboseReceipt()=" + disChannel.getDisNetworkInterface().hasVerboseReceipt());
+        disChannel.getPduRecorder().setVerbose(false);
+
+        // TODO confirm whether recorder is explicitly started by programmer (or not)
+        
+//      disChannel.sendCommentPdu(VariableRecordType.OTHER, "DisThreadedNetworkInterface.initializeDisChannel() complete"); // hello channel, debug
+    }
+    
+    /** Get ready, get set... initialize simulation entities.  Who's who in the zoo?
+     */
+    public void initializeSimulationEntities()
+    {        
+        if (pduFactory == null)
+            pduFactory      = disChannel.getPduFactory();
+        entityStatePdu_1    = pduFactory.makeEntityStatePdu();
+        entityStatePdu_2    = pduFactory.makeEntityStatePdu();
+        firePdu_1a          = pduFactory.makeFirePdu();
+        firePdu_1b          = pduFactory.makeFirePdu();
+        munitionDescriptor1 = new MunitionDescriptor();
+        
+        // Your model setup: define participants.  who's who in this zoo?
+        // Assuming you keep track of entity objects...  here is some support for for Entity 1.
+        
+        // PDU objects are already declared and instances created, so now set their values.
+        // who is who in our big zoo, sufficient for global participation if we need it
+        entityID_1.setSiteID(1).setApplicationID(2).setEntityID(3); // made-up example ID;
+        disChannel.addEntity(entityID_1);
+        
+        entityID_2.setSiteID(1).setApplicationID(2).setEntityID(4); // made-up example ID; 
+        disChannel.addEntity(entityID_2);
+        // TODO someday, use enumerations for sites as part of a SimulationManager object; e.g. is there a unique site triplet for MOVES Institute?
+
+        entityStatePdu_1.setEntityID(entityID_1);
+        entityStatePdu_1.setForceId(ForceID.FRIENDLY);
+        entityStatePdu_1.setEntityType(new _001Poseidon());       // note import statement above
+//      entityStatePdu_1.setMarking("Entity #1");
+        entityStatePdu_1.setEntityType(new edu.nps.moves.dis7.entities.usa.platform.air.MV22B()); // note import statement at top
+        entityStatePdu_1.setMarking("Entity #53");
+        entityStatePdu_1.getMarkingString(); // use Netbeans Debug breakpoint here to check left justified...
+
+        entityStatePdu_2.setEntityID(entityID_2);
+        entityStatePdu_2.setForceId(ForceID.OPPOSING);
+        entityStatePdu_2.setEntityType(new _002Triton()); // note import statement above
+        entityStatePdu_2.setMarking("Entity #2");
+
+        // TODO how should we customize this munition?  what are key parameters for your simulation? 
+        // more is needed here by scenario authors...
+        munitionDescriptor1.setQuantity(1);
+        firePdu_1a.setDescriptor(munitionDescriptor1).setRange(1000.0f);
+    }
+                 
+    /**
+     * This runSimulationLoops() method is for you, a customizable programmer-modifiable
+     * code block for defining and running a new simulation of interest.
+     * 
+     * Welcome! Other parts of this program handle bookkeeping and plumbing tasks so that
+     * you can focus on your model entities and activities.
+     * Expandable support includes DIS EntityStatePdu, FirePdu and CommentPdu all available for 
+     * modification and sending in a simulation loop.
+     * Continuous improvement efforts seek to make this program as easy and straightforward
+     * as possible for DIS simulationists to use and adapt.
+     * All of the other methods are setup, teardown and configuration that you may find
+     * interesting, even helpful, but don't really have to worry about.
+     */
+    @SuppressWarnings("SleepWhileInLoop") // yes we might do that
+    public void runSimulationLoops ()
+    {
+      try
+      {              
+        final int     SIMULATION_MAX_LOOP_COUNT = 20; // set number of turns in the game;  also avoid infinite loops.
+              int     simulationLoopCount = 0;        // variable, initialized at 0
+              boolean simulationComplete = false;     // sentinel variable as termination condition, are we done yet?
+        final int     NUMBER_MINES = 30;               // preset number of mines to be placed
+        // TODO reset Clock Time for today's date and timestamp to zero, providing consistent outputs for each simulation run
+        String timeMessage = "Simulation time " + simulationTimeSeconds + " at LocalDateTime " + LocalDateTime.now();
+        disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_TIME, timeMessage);
+        // TODO replace enumeration with disChannel.COMMENTPDU_TIME
+        // TODO fix VariableRecordType.TIME_AMP_DATE_VALID
+        
+        // ===================================================================================================
+        // loop the simulation while allowed, programmer can set additional conditions to break out and finish
+        Random random = new Random();
+        Scanner scanner = new Scanner(System.in);
+        List<double[]> minefield = new ArrayList<>();
+        
+        //set start point at (0,0)
+        entityStatePdu_1.getEntityLocation().setX(0.0);
+        entityStatePdu_1.getEntityLocation().setY(0.0);
+        double[] start = {entityStatePdu_1.getEntityLocation().getX(), entityStatePdu_1.getEntityLocation().getY()};
+        
+        //exit square is somewhere on the middle third of the far right edge of the minefield (space 3-6)
+        double exitY = random.nextInt(4)+3; 
+        double[] exit = {9, exitY};
+        
+        for (int i = 0; i < NUMBER_MINES; i++){
+            //random placement of the mines within the 10x10 grid
+            double x = random.nextInt(10);
+            double y = random.nextInt(10) ;
+            double[] mine = {x,y}; 
+            //No mine placed at the start position or on the exit space
+            if ((mine[0] == start[0] && mine[1] == start[1]) || (mine[0] == exit[0] && mine[1] == exit[1])){
+                continue;
+            }
+            //add mines to the minefield list
+            minefield.add(mine);
+        }
+        
+        System.out.println("\nYou are in a minefield. The exit is at (" + exit[0] + ", " + exit[1] + 
+                "). \nWhen prompted, use the WASD keys to pick a move. \nCareful, you only have so many moves, and there are plenty of mines!");
+        System.out.flush();
+        
+        while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT)  // are we done yet?
+        {
+            simulationLoopCount++; // good practice: increment loop counter as first action in that loop
+            
+            // =============================================================================================
+            // * your own simulation code starts here! *****************************************************
+            // =============================================================================================
+            System.out.println("==========================================================================");
+            System.out.println("\nMove "+ simulationLoopCount+ " of " + SIMULATION_MAX_LOOP_COUNT);
+            System.out.println("Current Location: (" + entityStatePdu_1.getEntityLocation().getX()+","+ entityStatePdu_1.getEntityLocation().getY() + "); Exit: (" + exit[0] + ", " + exit[1] + ").");
+            System.out.println("Where would you like to move now?" );
+            //  are there any other variables to modify at the beginning of your loop?
+            boolean validMove = false;
+            String move = null;
+            while (!validMove){
+                move = scanner.nextLine().toUpperCase();
+                switch(move){
+                    case("W") -> {
+                        entityStatePdu_1.getEntityLocation().setY(min(9.0, entityStatePdu_1.getEntityLocation().getY() + 1.0));
+                        validMove = true;
+                    }
+                    case("A") -> {
+                        entityStatePdu_1.getEntityLocation().setX(max(0.0, entityStatePdu_1.getEntityLocation().getX() - 1.0));
+                        validMove = true;
+                    }
+                    case("S") -> {
+                        entityStatePdu_1.getEntityLocation().setY(max(0.0, entityStatePdu_1.getEntityLocation().getY() - 1.0));
+                        validMove = true;
+                    }
+                    case("D") -> {
+                        entityStatePdu_1.getEntityLocation().setX(min(9.0, entityStatePdu_1.getEntityLocation().getX() + 1.0));
+                        validMove = true;
+                    }
+                    default -> System.out.println("Not a valid move. Try again");
+                }
+            }
+            
+            // compute a track, update an ESPDU, whatever it is that your model is doing...
+            
+            
+            
+            // decide whether to fire, and then update the firePdu.  Hmmm, you might want a target to shoot at!
+            
+            // etc. etc. your code goes here for your simulation of interest
+                
+            System.out.flush(); // make sure this arrives to user even if other threads somehow become deadlocked
+            
+            
+            // make your reports: narrative code for CommentPdu here (set all to empty strings to avoid sending)
+            narrativeMessage1 = "MV3500 LennonSimulationProgram";
+            narrativeMessage2 = "runSimulation() loop " + simulationLoopCount;
+            narrativeMessage3 = ""; // intentionally blank for testing
+
+            // your loop termination condition goes here
+            
+            //Check for entity to reach exit
+            if (entityStatePdu_1.getEntityLocation().getX() == exit[0] && entityStatePdu_1.getEntityLocation().getY() == exit[1]){
+                System.out.println("You've escaped the minefield. Good job.");
+                narrativeMessage3 = "Entity escaped successfully.";
+                simulationComplete = true;
+            }
+            //Check for turn limit reached
+            else if (simulationLoopCount >= SIMULATION_MAX_LOOP_COUNT) 
+            {
+                System.out.println("You've run out of time. You lose.");
+                narrativeMessage3 = "Entity ran out of time.";
+                simulationComplete = true;
+            } 
+            
+            //Check for entity to hit mine
+            for (double[] mine : minefield){
+                if (entityStatePdu_1.getEntityLocation().getX() == mine[0]&& entityStatePdu_1.getEntityLocation().getY() == mine[1]){
+                    System.out.println("BOOM! you hit a mine. You're dead.");
+                    narrativeMessage3 = "Entity hit a mine and was destroyed.";
+                    simulationComplete = true; 
+                }
+            }
+            System.out.println("");
+            // =============================================================================================
+            // * your own simulation code is finished here! ************************************************
+            // =============================================================================================
+            
+            // staying synchronized with timestep: wait duration for elapsed time in this loop
+            // Thread.sleep needs a (long) parameter for milliseconds, which are clumsy to use sometimes
+            Thread.sleep((long)(getSimulationTimeStepDuration() * 1000)); // units of seconds * (1000 msec/sec) = milliseconds
+            //System.out.println ("... [Pausing for " + getSimulationTimeStepDuration() + " seconds]");
+            
+            // OK now send the status PDUs for this loop, and then continue
+            System.out.println ("... sending PDUs of interest for simulation step " + simulationLoopCount + ", monitor loopback to confirm sent");
+            System.out.flush();
+            
+            // TODO set timesteps in PDUs
+            
+            sendAllPdusForLoopTimestep(simulationTimeSeconds,
+                                       entityStatePdu_1, 
+                                            firePdu_1a, 
+                                         DisChannel.COMMENTPDU_APPLICATION_STATUS, 
+                                           narrativeMessage1, narrativeMessage2, narrativeMessage3);
+            disChannel.sendSinglePdu(simulationTimeSeconds, entityStatePdu_2); // me too i.e. 2!
+            
+            System.out.println ("... [PDUs of interest successfully sent for this loop]");
+            System.out.flush();
+            
+            // ===============================
+            // current loop now finished, check whether to terminate if simulation complete, otherwise continue
+            if (simulationComplete || (simulationLoopCount > 10000)) // for example; including fail-safe condition is good
+            {
+                System.out.println ("... [loop termination condition met, simulationComplete=" + simulationComplete + "]"); // ", final loopCount=" + loopCount + 
+                System.out.flush();
+                break;
+            }
+            simulationTimeSeconds += getSimulationTimeStepDuration(); // good practice: increment simulationTime as lastst action in that loop
+                    
+        }   // end of simulation loop, continue until done
+        // ===================================================================================================// ===================================================================================================// ===================================================================================================// ===================================================================================================
+
+        narrativeMessage2 = "runSimulation() completed successfully"; // all done, so tell everyone else on the channel
+        // TODO better javadoc needs to be autogenerated for VariableRecordType enumerations
+        disChannel.sendCommentPdu(DisChannel.COMMENTPDU_NARRATIVE, narrativeMessage1, narrativeMessage2, narrativeMessage3);
+        System.out.println ("... [final=completion CommentPdu successfully sent for simulation]");
+        
+//        disChannel.getPduRecorder(). TODO record XML as well
+        disChannel.leave(); // embedded SimulationManager is expected to send appropriate PDUs for entity, application shutdown
+      } 
+      catch (InterruptedException iex) // handle any exception that your code might choose to provoke!
+      {
+        Logger.getLogger(LennonSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
+      }
+    }
+
+    /**
+     * Send EntityState, Fire, Comment PDUs that got updated for this loop, reflecting state of current simulation timestep.
+     * @param simTimeSeconds simulation time in second, applied to PDU as timestamp
+     * @param entityStatePdu the ESPDU to send, if any
+     * @param firePdu        the FirePDU to send, if any
+     * @param commentType    enumeration value describing purpose of the narrative comment PDU
+     * @param comments       String array of narrative comments
+     * @see DisChannel
+//   * @see DisTime // TODO find renamed version
+     * @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html" target="_blank">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
+     */
+    public void sendAllPdusForLoopTimestep(double simTimeSeconds,
+                                   EntityStatePdu entityStatePdu,
+                                          FirePdu firePdu,
+                               VariableRecordType commentType,
+                                     // vararg... variable-length set of String comments can optionally follow
+                                        String... comments)
+    {
+        if (entityStatePdu != null)
+            disChannel.sendSinglePdu(simTimeSeconds, entityStatePdu);
+            
+        if (firePdu != null)
+            disChannel.sendSinglePdu(simTimeSeconds, firePdu); // bang
+        
+        disChannel.sendCommentPdu(simTimeSeconds, commentType, comments); // empty comments are filtered
+    }
+    
+    /**
+     * Initial execution via main() method: handle args array of command-line initialization (CLI) arguments here
+     * @param args command-line parameters: network address and port
+     */
+    protected void handleArguments (String[] args)
+    {
+        // initial execution: handle args array of initialization arguments here
+        if (args.length == 2) 
+        {
+            if ((args[0] != null) && !args[0].isEmpty())
+                thisProgram.disChannel.setNetworkAddress(args[0]);
+            if ((args[1] != null) && !args[1].isEmpty())
+                thisProgram.disChannel.setNetworkPort(Integer.parseInt(args[1]));
+        }
+        else if (args.length != 0) 
+        {
+            System.err.println("Usage: " + thisProgram.getClass().getSimpleName() + " [address port]");
+            System.exit(-1);
+        }
+    }
+
+    /**
+     * Get simple descriptor (such as parent class name) for this network interface, used in trace statements
+     * @return simple descriptor name
+     */
+    public String getDescriptor() {
+        return descriptor;
+    }
+
+    /**
+     * Set new simple descriptor (such as parent class name) for this network interface, used in trace statements
+     * @param newDescriptor simple descriptor name for this interface
+     */
+    public void setDescriptor(String newDescriptor) {
+        if (newDescriptor == null)
+            newDescriptor = "";
+        this.descriptor = newDescriptor;
+    }
+
+    /**
+     * parameter accessor method
+     * @return the simulationTimeStepDuration in seconds
+     */
+    public double getSimulationTimeStepDuration() {
+        return simulationTimeStepDuration;
+    }
+
+    /**
+     * parameter accessor method
+     * @param timeStepDurationSeconds the simulationTimeStepDuration in seconds to set
+     */
+    public void setSimulationTimeStepDuration(double timeStepDurationSeconds) {
+        this.simulationTimeStepDuration = timeStepDurationSeconds;
+    }
+    
+    /** Locally instantiable copy of program, can be subclassed. */
+    protected static LennonSimulationProgram thisProgram;
+  
+    /**
+     * Main method is first executed when a program instance is loaded.
+     * @see <a href="https://docs.oracle.com/javase/tutorial/getStarted/application/index.html" target="_blank">Java Tutorials: A Closer Look at the "Hello World!" Application</a>
+     * @param args command-line parameters: network address and port.
+     *    Command-line arguments are an array of optional String parameters that are passed from execution environment during invocation
+     */
+    public static void main(String[] args)
+    {
+        thisProgram = new LennonSimulationProgram("test constructor"); // create instance of self within static main() method
+        
+        thisProgram.disChannel.printlnTRACE("main() started...");
+        
+        thisProgram.handleArguments(args); // process any command-line invocation arguments
+
+        thisProgram.runSimulationLoops(); // ... your simulation execution code goes in there ...
+        
+        thisProgram.disChannel.tearDownNetworkInterface(); // make sure no processes are left lingering
+        
+        thisProgram.disChannel.printlnTRACE("complete."); // report successful completion
+        
+        System.exit(0); // ensure all threads and sockets released
+    }
+}
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c5aadebfdcbc089649b153eb705bb84c6286336b
--- /dev/null
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/README.md
@@ -0,0 +1,38 @@
+## Homework 3: Example Simulation Recording using OpenDIS Network Streams
+
+<!-- Viewable at https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/assignments/src/MV3500Cohort2024JulySeptember/homework3/README.md -->
+
+### Assignment
+
+1. Adapt the functionality for [OpenDIS ExampleSimulationProgram](../../../../examples/src/OpenDis7Examples/ExampleSimulationProgram.java), modifying provided code
+2. Experiment with the enumeration values that set up each entity and PDU.  What works for you?  What makes sense for your future work?
+3. Adapt or replace the UML diagrams to describe what you have going on.
+4. Record, save and replay your result stream using [PduRecorder](https://savage.nps.edu/opendis7-java/javadoc/edu/nps/moves/dis7/utilities/stream/PduRecorder.html) or [Wireshark](https://www.wireshark.org)
+   * see local [assignments/src/pduLog](../../../pduLog) subdirectory for latest opendis log files
+   * Coming soon, we will also (again have) [X3D-Edit](https://savage.nps.edu/X3D-Edit) for DIS stream recording/replay
+5. Observe good-practice conventions in the [assignments README](../../../README.md) and [current-course README](../README.md) instructions.
+
+This assignment  presents a Problem Prototyping opportunity.
+While some minimal functionality is expected, the general outline of
+a networking problem and proposed solution holds great interest.
+Think of it as warmup preparation for your future work.
+
+This is also a freeplay opportunity. 
+You have the option to pick one or more of the provided course example programs 
+and adapt the source to demonstrate a new client-server handshake protocol of interest.
+
+Be sure to provide a rationale that justifies why the networking choices you made
+(TCP/UDP, unicast/multicast, etc.) are the best for the problem you are addressing.
+
+You may find that the prior [homework2 README](../homework2/README.md) still provides
+helpful details on what specific deliverables are expected in each homework assignment.
+
+Team efforts are encouraged, though if you choose a team approach be sure to justify why.
+This is a good warmup prior to final projects. Have fun with Java networking!
+
+### Prior Assignment, August 2019
+
+In 2019, students worked together on a single project to check wireless multicast connectivity recently deployed on NPS campus.  
+
+See their experimental results in the [NPS Multicast Connectivity Report](../../MV3500Cohort2019JulySeptember/homework3).
+
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/package-info.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..0182f9f08eac81459c1925c4695b44789f5bb82a
--- /dev/null
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * Final project assignments supporting the NPS MOVES MV3500 Networked Graphics course.
+ * 
+ * @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/assignments" target="_blank">networkedGraphicsMV3500 assignments</a>
+ * @see java.lang.Package
+ * @see <a href="https://stackoverflow.com/questions/22095487/why-is-package-info-java-useful" target="_blank">StackOverflow: why-is-package-info-java-useful</a>
+ * @see <a href="https://stackoverflow.com/questions/624422/how-do-i-document-packages-in-java" target="_blank">StackOverflow: how-do-i-document-packages-in-java</a>
+ */
+
+package MV3500Cohort2024JulySeptember.homework3.Lennon;
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/README.md
index a1f900c417af2114b2bd482ba58370ab58a1c751..2d70b8de0eee2fd32ebe9532f5a343ebd070c4dc 100644
--- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/README.md
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/README.md
@@ -4,9 +4,24 @@
 
 ## Description
 
-Modification to ... 
+Assigment 3, show a simple Modeling & Simulation loop.
+
+- "Add DIS outputs (general skills)"
+
+
+<!-- 
+
+Assigment 4
+
+- Show use of Simkit, DIS and Viskit together.
+
+Final essay
+
+- What do you think?
+
+    "And you get to use the word networking and combination, whatever else interest you, 
+    you know, thesis, challenging for my warfare community cell phone, thinking about international partnerships".
 
-<!--
 
 Phrases taken from: <b>https://www.divein.com/everyday/monday-motivation-quotes/</b>
 
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/RomeroSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/RomeroSimulationProgram.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c3664dfb408fe2a5bfe73f548320cda92ed25cd
--- /dev/null
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/RomeroSimulationProgram.java
@@ -0,0 +1,413 @@
+/**
+ * Copyright (c) 2008-2023, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
+ * This work is provided under a BSD open-source license, see project license.html or license.txt
+ * @author brutzman@nps.edu
+ */
+package MV3500Cohort2024JulySeptember.homework3.Romero;
+
+import edu.nps.moves.dis7.entities.swe.platform.surface._001Poseidon;
+import edu.nps.moves.dis7.entities.swe.platform.surface._002Triton;
+import edu.nps.moves.dis7.enumerations.*;
+import edu.nps.moves.dis7.pdus.*;
+import edu.nps.moves.dis7.utilities.DisChannel;
+import edu.nps.moves.dis7.utilities.PduFactory;
+import java.time.LocalDateTime;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/** The purpose of this inheritable class is to provide an easily modifiable 
+ *  example simulation program that includes DIS-capable entities performing 
+ *  tasks of interest, and then reporting activity via PDUs to the network.
+ *  Default program initialization includes PDU recording turned on by default.
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramLog.txt" target="_blank">ExampleSimulationProgramLog.txt</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramPduCaptureLog.dislog" target="_blank">ExampleSimulationProgramPduCaptureLog.dislog</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramFlowDiagram.pdf" target="_blank">ExampleSimulationProgramFlowDiagram.pdf</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramWireshark.png" target="_blank">ExampleSimulationProgramWireshark.png</a>
+ *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramSequenceDiagram.png" target="_blank">ExampleSimulationProgramSequenceDiagram.png</a>
+ */
+public class RomeroSimulationProgram
+{
+    /* **************************** infrastructure code, modification is seldom needed ************************* */
+                 
+    private   String     descriptor = this.getClass().getSimpleName();
+    /** DIS channel defined by network address/port combination includes multiple utility capabilities */
+    protected DisChannel disChannel;
+    /** Factory object used to create new PDU instances */
+    protected PduFactory pduFactory;
+    
+    /** seconds per loop for real-time or simulation execution */
+    private double  simulationTimeStepDuration  =  1.0; // seconds TODO encapsulate
+    /** initial simulation time in seconds */
+    double  simulationTimeInitial = 0.0;
+    /** current simulation time in seconds */
+    double  simulationTimeSeconds = simulationTimeInitial;
+    /** Maximum number of simulation loops */
+    int MAX_LOOP_COUNT = 4;
+    
+    String narrativeMessage1 = new String();
+    String narrativeMessage2 = new String();
+    String narrativeMessage3 = new String();
+    
+    /** EntityID settings for entity 1 */
+    protected EntityID           entityID_1          = new EntityID();
+    /** EntityID settings for entity 2 */
+    protected EntityID           entityID_2          = new EntityID();
+    /** ESPDU for entity 1 */
+    protected EntityStatePdu     entityStatePdu_1;
+    /** ESPDU for entity 2 */
+    protected EntityStatePdu     entityStatePdu_2;
+    /** FirePdu for entity 1 first  weapon (if any) */
+    protected FirePdu            firePdu_1a;
+    /** FirePdu for entity 1 second weapon (if any) */
+    protected FirePdu            firePdu_1b;
+    /** MunitionDescriptor for these weapons */
+    protected MunitionDescriptor munitionDescriptor1;
+    
+    // hey programmer, what other state do you want?  this is a good place to declare it...
+    
+    /**
+     * Constructor to create an instance of this class.
+     * Design goal: additional built-in initialization conveniences can go here
+     * to keep your efforts focused on the runSimulation() method.
+     */
+    // base constructor is not invoked automatically by other constructors
+    // https://stackoverflow.com/questions/581873/best-way-to-handle-multiple-constructors-in-java
+    public RomeroSimulationProgram()
+    {
+        initialize();
+    }
+    /**
+     * Constructor to create an instance of this class.
+     * @param newDescriptor describes this program, useful for logging and debugging
+     */
+    public RomeroSimulationProgram(String newDescriptor)
+    {
+        descriptor = newDescriptor;
+        initialize();
+    }
+    /**
+     * Utility Constructor that allows your example simulation program to override default network address and port
+     * @param address network address to use
+     * @param port corresponding network port to use
+     */
+    public RomeroSimulationProgram(String address, int port)
+    {
+        disChannel.setNetworkAddress            (address);
+        disChannel.setNetworkPort               (port);
+        disChannel.setVerboseComments           (true);       // TODO rename library method to disambiguate CommentPDU
+                                                                            // TODO still seems really chatty... add silent mode?
+        disChannel.setVerboseDisNetworkInterface(true);  // Default false
+        disChannel.setVerbosePduRecorder        (true);       // default false
+        initialize();
+    }
+    
+    /** Initialize channel setup for OpenDis7 and report a test PDU
+     * @see initializeDisChannel
+     * @see initializeSimulationEntities */
+    private void initialize()
+    {
+        initializeDisChannel(); // must come first, uses PduFactory
+        
+        initializeSimulationEntities(); // set unchanging parameters
+        
+        disChannel.join(); // TODO further functionality expected
+        
+        String timeStepMessage = "Simulation timestep duration " + getSimulationTimeStepDuration() + " seconds";
+        disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_SIMULATION_TIMESTEP, timeStepMessage);
+        // additional constructor initialization can go here
+    }
+    
+    /** Initialize channel setup for OpenDis7 and report a test PDU */
+    private void initializeDisChannel()
+    {
+        if (disChannel == null)
+            disChannel = new DisChannel();
+        else
+        {
+            disChannel.printlnTRACE ("*** warning, duplicate invocation of initializeDisChannel() ignored");
+            return;
+        }
+        pduFactory     = disChannel.getPduFactory();
+        disChannel.setDescriptor(this.getClass().getSimpleName()); // ExampleSimulationProgram might be a superclass
+        disChannel.setUpNetworkInterface();
+        disChannel.printlnTRACE ("just checking: disChannel.getNetworkAddress()=" + disChannel.getNetworkAddress() +
+                                                         ", getNetworkPort()="    + disChannel.getNetworkPort());
+        disChannel.getDisNetworkInterface().setVerbose(true); // sending and receipt
+        disChannel.printlnTRACE ("just checking: hasVerboseSending()=" + disChannel.getDisNetworkInterface().hasVerboseSending() +
+                                              ", hasVerboseReceipt()=" + disChannel.getDisNetworkInterface().hasVerboseReceipt());
+        disChannel.getPduRecorder().setVerbose(true);
+
+        // TODO confirm whether recorder is explicitly started by programmer (or not)
+        
+//      disChannel.sendCommentPdu(VariableRecordType.OTHER, "DisThreadedNetworkInterface.initializeDisChannel() complete"); // hello channel, debug
+    }
+    
+    /** Get ready, get set... initialize simulation entities.  Who's who in the zoo?
+     */
+    public void initializeSimulationEntities()
+    {        
+        if (pduFactory == null)
+            pduFactory      = disChannel.getPduFactory();
+        entityStatePdu_1    = pduFactory.makeEntityStatePdu();
+        entityStatePdu_2    = pduFactory.makeEntityStatePdu();
+        firePdu_1a          = pduFactory.makeFirePdu();
+        firePdu_1b          = pduFactory.makeFirePdu();
+        munitionDescriptor1 = new MunitionDescriptor();
+        
+        // Your model setup: define participants.  who's who in this zoo?
+        // Assuming you keep track of entity objects...  here is some support for for Entity 1.
+        
+        // PDU objects are already declared and instances created, so now set their values.
+        // who is who in our big zoo, sufficient for global participation if we need it
+        entityID_1.setSiteID(1).setApplicationID(2).setEntityID(3); // made-up example ID;
+        disChannel.addEntity(entityID_1);
+        
+        entityID_2.setSiteID(1).setApplicationID(2).setEntityID(4); // made-up example ID; 
+        disChannel.addEntity(entityID_2);
+        // TODO someday, use enumerations for sites as part of a SimulationManager object; e.g. is there a unique site triplet for MOVES Institute?
+
+        entityStatePdu_1.setEntityID(entityID_1);
+        entityStatePdu_1.setForceId(ForceID.FRIENDLY);
+        entityStatePdu_1.setEntityType(new _001Poseidon());       // note import statement above
+//      entityStatePdu_1.setMarking("Entity #1");
+        entityStatePdu_1.setEntityType(new edu.nps.moves.dis7.entities.usa.platform.air.MV22B()); // note import statement at top
+        entityStatePdu_1.setMarking("Entity #53");
+        entityStatePdu_1.getMarkingString(); // use Netbeans Debug breakpoint here to check left justified...
+
+        entityStatePdu_2.setEntityID(entityID_2);
+        entityStatePdu_2.setForceId(ForceID.OPPOSING);
+        entityStatePdu_2.setEntityType(new _002Triton()); // note import statement above
+        entityStatePdu_2.setMarking("Entity #2");
+
+        // TODO how should we customize this munition?  what are key parameters for your simulation? 
+        // more is needed here by scenario authors...
+        munitionDescriptor1.setQuantity(1);
+        firePdu_1a.setDescriptor(munitionDescriptor1).setRange(1000.0f);
+    }
+                 
+    /**
+     * This runSimulationLoops() method is for you, a customizable programmer-modifiable
+     * code block for defining and running a new simulation of interest.
+     * 
+     * Welcome! Other parts of this program handle bookkeeping and plumbing tasks so that
+     * you can focus on your model entities and activities.
+     * Expandable support includes DIS EntityStatePdu, FirePdu and CommentPdu all available for 
+     * modification and sending in a simulation loop.
+     * Continuous improvement efforts seek to make this program as easy and straightforward
+     * as possible for DIS simulationists to use and adapt.
+     * All of the other methods are setup, teardown and configuration that you may find
+     * interesting, even helpful, but don't really have to worry about.
+     */
+    @SuppressWarnings("SleepWhileInLoop") // yes we might do that
+    public void runSimulationLoops ()
+    {
+      try
+      {              
+        final int     SIMULATION_MAX_LOOP_COUNT = 10; // be deliberate out there!  also avoid infinite loops.
+              int     simulationLoopCount = 0;        // variable, initialized at 0
+              boolean simulationComplete = false;     // sentinel variable as termination condition, are we done yet?
+        
+        // TODO reset Clock Time for today's date and timestamp to zero, providing consistent outputs for each simulation run
+        String timeMessage = "Simulation time " + simulationTimeSeconds + " at LocalDateTime " + LocalDateTime.now();
+        disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_TIME, timeMessage);
+        // TODO replace enumeration with disChannel.COMMENTPDU_TIME
+        // TODO fix VariableRecordType.TIME_AMP_DATE_VALID
+        
+        // ===================================================================================================
+        // loop the simulation while allowed, programmer can set additional conditions to break out and finish
+        while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT)  // are we done yet?
+        {
+            simulationLoopCount++; // good practice: increment loop counter as first action in that loop
+            
+            // =============================================================================================
+            // * your own simulation code starts here! *****************************************************
+            // =============================================================================================
+            
+            //  are there any other variables to modify at the beginning of your loop?
+            
+            // are your reading any DIS PDUs from the network?  check for them here
+            
+            // compute a track, update an ESPDU, whatever it is that your model is doing...
+            
+            // Where is my entity?  Insert changes in position; this sample only changes X position.
+            entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + 1.0); // 1m per timestep
+            
+            // decide whether to fire, and then update the firePdu.  Hmmm, you might want a target to shoot at!
+            
+            // etc. etc. your code goes here for your simulation of interest
+                
+            // something happens between my simulation entities, la de da de da...
+            System.out.println ("... My simulation just did something, no really...");
+            System.out.flush(); // make sure this arrives to user even if other threads somehow become deadlocked
+            
+            
+            // make your reports: narrative code for CommentPdu here (set all to empty strings to avoid sending)
+            narrativeMessage1 = "MV3500 ExampleSimulationProgram";
+            narrativeMessage2 = "runSimulation() loop " + simulationLoopCount;
+            narrativeMessage3 = ""; // intentionally blank for testing
+
+            // your loop termination condition goes here
+            if (simulationLoopCount > MAX_LOOP_COUNT) // for example
+            {
+                simulationComplete = true;
+            }      
+            // =============================================================================================
+            // * your own simulation code is finished here! ************************************************
+            // =============================================================================================
+            
+            // staying synchronized with timestep: wait duration for elapsed time in this loop
+            // Thread.sleep needs a (long) parameter for milliseconds, which are clumsy to use sometimes
+            Thread.sleep((long)(getSimulationTimeStepDuration() * 1000)); // units of seconds * (1000 msec/sec) = milliseconds
+            System.out.println ("... [Pausing for " + getSimulationTimeStepDuration() + " seconds]");
+            
+            // OK now send the status PDUs for this loop, and then continue
+            System.out.println ("... sending PDUs of interest for simulation step " + simulationLoopCount + ", monitor loopback to confirm sent");
+            System.out.flush();
+            
+            // TODO set timesteps in PDUs
+            
+            sendAllPdusForLoopTimestep(simulationTimeSeconds,
+                                       entityStatePdu_1, 
+                                            firePdu_1a, 
+                                         DisChannel.COMMENTPDU_APPLICATION_STATUS, 
+                                           narrativeMessage1, narrativeMessage2, narrativeMessage3);
+            disChannel.sendSinglePdu(simulationTimeSeconds, entityStatePdu_2); // me too i.e. 2!
+            
+            System.out.println ("... [PDUs of interest successfully sent for this loop]");
+            System.out.flush();
+            
+            // ===============================
+            // current loop now finished, check whether to terminate if simulation complete, otherwise continue
+            if (simulationComplete || (simulationLoopCount > 10000)) // for example; including fail-safe condition is good
+            {
+                System.out.println ("... [loop termination condition met, simulationComplete=" + simulationComplete + "]"); // ", final loopCount=" + loopCount + 
+                System.out.flush();
+                break;
+            }
+            simulationTimeSeconds += getSimulationTimeStepDuration(); // good practice: increment simulationTime as lastst action in that loop
+                    
+        }   // end of simulation loop, continue until done
+        // ===================================================================================================// ===================================================================================================// ===================================================================================================// ===================================================================================================
+
+        narrativeMessage2 = "runSimulation() completed successfully"; // all done, so tell everyone else on the channel
+        // TODO better javadoc needs to be autogenerated for VariableRecordType enumerations
+        disChannel.sendCommentPdu(DisChannel.COMMENTPDU_NARRATIVE, narrativeMessage1, narrativeMessage2, narrativeMessage3);
+        System.out.println ("... [final=completion CommentPdu successfully sent for simulation]");
+        
+//        disChannel.getPduRecorder(). TODO record XML as well
+        disChannel.leave(); // embedded SimulationManager is expected to send appropriate PDUs for entity, application shutdown
+      } 
+      catch (InterruptedException iex) // handle any exception that your code might choose to provoke!
+      {
+        Logger.getLogger(RomeroSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
+      }
+    }
+
+    /**
+     * Send EntityState, Fire, Comment PDUs that got updated for this loop, reflecting state of current simulation timestep.
+     * @param simTimeSeconds simulation time in second, applied to PDU as timestamp
+     * @param entityStatePdu the ESPDU to send, if any
+     * @param firePdu        the FirePDU to send, if any
+     * @param commentType    enumeration value describing purpose of the narrative comment PDU
+     * @param comments       String array of narrative comments
+     * @see DisChannel
+//   * @see DisTime // TODO find renamed version
+     * @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html" target="_blank">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
+     */
+    public void sendAllPdusForLoopTimestep(double simTimeSeconds,
+                                   EntityStatePdu entityStatePdu,
+                                          FirePdu firePdu,
+                               VariableRecordType commentType,
+                                     // vararg... variable-length set of String comments can optionally follow
+                                        String... comments)
+    {
+        if (entityStatePdu != null)
+            disChannel.sendSinglePdu(simTimeSeconds, entityStatePdu);
+            
+        if (firePdu != null)
+            disChannel.sendSinglePdu(simTimeSeconds, firePdu); // bang
+        
+        disChannel.sendCommentPdu(simTimeSeconds, commentType, comments); // empty comments are filtered
+    }
+    
+    /**
+     * Initial execution via main() method: handle args array of command-line initialization (CLI) arguments here
+     * @param args command-line parameters: network address and port
+     */
+    protected void handleArguments (String[] args)
+    {
+        // initial execution: handle args array of initialization arguments here
+        if (args.length == 2) 
+        {
+            if ((args[0] != null) && !args[0].isEmpty())
+                thisProgram.disChannel.setNetworkAddress(args[0]);
+            if ((args[1] != null) && !args[1].isEmpty())
+                thisProgram.disChannel.setNetworkPort(Integer.parseInt(args[1]));
+        }
+        else if (args.length != 0) 
+        {
+            System.err.println("Usage: " + thisProgram.getClass().getSimpleName() + " [address port]");
+            System.exit(-1);
+        }
+    }
+
+    /**
+     * Get simple descriptor (such as parent class name) for this network interface, used in trace statements
+     * @return simple descriptor name
+     */
+    public String getDescriptor() {
+        return descriptor;
+    }
+
+    /**
+     * Set new simple descriptor (such as parent class name) for this network interface, used in trace statements
+     * @param newDescriptor simple descriptor name for this interface
+     */
+    public void setDescriptor(String newDescriptor) {
+        if (newDescriptor == null)
+            newDescriptor = "";
+        this.descriptor = newDescriptor;
+    }
+
+    /**
+     * parameter accessor method
+     * @return the simulationTimeStepDuration in seconds
+     */
+    public double getSimulationTimeStepDuration() {
+        return simulationTimeStepDuration;
+    }
+
+    /**
+     * parameter accessor method
+     * @param timeStepDurationSeconds the simulationTimeStepDuration in seconds to set
+     */
+    public void setSimulationTimeStepDuration(double timeStepDurationSeconds) {
+        this.simulationTimeStepDuration = timeStepDurationSeconds;
+    }
+    
+    /** Locally instantiable copy of program, can be subclassed. */
+    protected static RomeroSimulationProgram thisProgram;
+  
+    /**
+     * Main method is first executed when a program instance is loaded.
+     * @see <a href="https://docs.oracle.com/javase/tutorial/getStarted/application/index.html" target="_blank">Java Tutorials: A Closer Look at the "Hello World!" Application</a>
+     * @param args command-line parameters: network address and port.
+     *    Command-line arguments are an array of optional String parameters that are passed from execution environment during invocation
+     */
+    public static void main(String[] args)
+    {
+        thisProgram = new RomeroSimulationProgram("test constructor"); // create instance of self within static main() method
+        
+        thisProgram.disChannel.printlnTRACE("main() started...");
+        
+        thisProgram.handleArguments(args); // process any command-line invocation arguments
+
+        thisProgram.runSimulationLoops(); // ... your simulation execution code goes in there ...
+        
+        thisProgram.disChannel.tearDownNetworkInterface(); // make sure no processes are left lingering
+        
+        thisProgram.disChannel.printlnTRACE("complete."); // report successful completion
+        
+        System.exit(0); // ensure all threads and sockets released
+    }
+}
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgram.java
index a5e42691d8d460162361a3b370617b601b204425..26419da18ec013dfd0790866944c8d64b44c0020 100644
--- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgram.java
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgram.java
@@ -1,413 +1,310 @@
-/**
- * Copyright (c) 2008-2023, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
- * This work is provided under a BSD open-source license, see project license.html or license.txt
- * @author tjsus
- */
 package MV3500Cohort2024JulySeptember.homework3.Smith;
 
-import edu.nps.moves.dis7.entities.swe.platform.surface._001Poseidon;
-import edu.nps.moves.dis7.entities.swe.platform.surface._002Triton;
-import edu.nps.moves.dis7.enumerations.*;
+import edu.nps.moves.dis7.enumerations.VariableRecordType;
 import edu.nps.moves.dis7.pdus.*;
 import edu.nps.moves.dis7.utilities.DisChannel;
 import edu.nps.moves.dis7.utilities.PduFactory;
-import java.time.LocalDateTime;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-/** The purpose of this inheritable class is to provide an easily modifiable 
- *  example simulation program that includes DIS-capable entities performing 
- *  tasks of interest, and then reporting activity via PDUs to the network.
- *  Default program initialization includes PDU recording turned on by default.
- *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramLog.txt" target="_blank">ExampleSimulationProgramLog.txt</a>
- *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramPduCaptureLog.dislog" target="_blank">ExampleSimulationProgramPduCaptureLog.dislog</a>
- *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramFlowDiagram.pdf" target="_blank">ExampleSimulationProgramFlowDiagram.pdf</a>
- *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramWireshark.png" target="_blank">ExampleSimulationProgramWireshark.png</a>
- *  @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramSequenceDiagram.png" target="_blank">ExampleSimulationProgramSequenceDiagram.png</a>
+/**
+ * The purpose of this inheritable class is to provide an easily modifiable
+ * example simulation program that includes DIS-capable entities performing
+ * tasks of interest, and then reporting activity via PDUs to the network.
+ * Default program initialization includes PDU recording turned on by default.
  */
-public class ExampleSimulationProgram
-{
-    /* **************************** infrastructure code, modification is seldom needed ************************* */
-                 
-    private   String     descriptor = this.getClass().getSimpleName();
-    /** DIS channel defined by network address/port combination includes multiple utility capabilities */
+public class ExampleSimulationProgram {
+
+    // Constants for the Battleship game
+    private static final int GRID_SIZE = 10; // 10x10 grid for Battleship
+    private static final int MAX_TURNS = 100; // Limit turns to avoid infinite games
+
+    // Grids for each player
+    private char[][] player1Grid = new char[GRID_SIZE][GRID_SIZE];
+    private char[][] player2Grid = new char[GRID_SIZE][GRID_SIZE];
+
+    // To track whose turn it is
+    private boolean isPlayer1Turn = true;
+
+    // Ship positions (simple example positions for each player's ships)
+    private final int[][] player1Ships = {{0, 0}, {0, 1}, {0, 2}}; // Positions for player 1's ships
+    private final int[][] player2Ships = {{5, 5}, {5, 6}, {5, 7}}; // Positions for player 2's ships
+
+    // DIS utilities
+    private String descriptor = this.getClass().getSimpleName();
     protected DisChannel disChannel;
-    /** Factory object used to create new PDU instances */
     protected PduFactory pduFactory;
-    
-    /** seconds per loop for real-time or simulation execution */
-    private double  simulationTimeStepDuration  =  1.0; // seconds TODO encapsulate
-    /** initial simulation time in seconds */
-    double  simulationTimeInitial = 0.0;
-    /** current simulation time in seconds */
-    double  simulationTimeSeconds = simulationTimeInitial;
-    /** Maximum number of simulation loops */
-    int MAX_LOOP_COUNT = 4;
-    
-    String narrativeMessage1 = new String();
-    String narrativeMessage2 = new String();
-    String narrativeMessage3 = new String();
-    
-    /** EntityID settings for entity 1 */
-    protected EntityID           entityID_1          = new EntityID();
-    /** EntityID settings for entity 2 */
-    protected EntityID           entityID_2          = new EntityID();
-    /** ESPDU for entity 1 */
-    protected EntityStatePdu     entityStatePdu_1;
-    /** ESPDU for entity 2 */
-    protected EntityStatePdu     entityStatePdu_2;
-    /** FirePdu for entity 1 first  weapon (if any) */
-    protected FirePdu            firePdu_1a;
-    /** FirePdu for entity 1 second weapon (if any) */
-    protected FirePdu            firePdu_1b;
-    /** MunitionDescriptor for these weapons */
-    protected MunitionDescriptor munitionDescriptor1;
-    
-    // hey programmer, what other state do you want?  this is a good place to declare it...
-    
+    protected CommentPdu gridStatusPdu;
+    protected FirePdu firePduPlayer1;
+    protected FirePdu firePduPlayer2;
+    protected MunitionDescriptor munitionDescriptor1 = new MunitionDescriptor();
+
+    // Simulation time settings
+    private double simulationTimeStepDuration = 1.0; // seconds
+    private double simulationTimeSeconds = 0.0;
+
+    // Tracking indices for Player 1's systematic search
+    private int player1SearchRow = 0;
+    private int player1SearchCol = 0;
+
     /**
-     * Constructor to create an instance of this class.
-     * Design goal: additional built-in initialization conveniences can go here
-     * to keep your efforts focused on the runSimulation() method.
+     * Constructor to create an instance of this class. Design goal: additional
+     * built-in initialization conveniences can go here to keep your efforts
+     * focused on the runSimulation() method.
      */
-    // base constructor is not invoked automatically by other constructors
-    // https://stackoverflow.com/questions/581873/best-way-to-handle-multiple-constructors-in-java
-    public ExampleSimulationProgram()
-    {
+    public ExampleSimulationProgram() {
         initialize();
     }
+
     /**
-     * Constructor to create an instance of this class.
-     * @param newDescriptor describes this program, useful for logging and debugging
+     * Initialize the simulation program, setting up the DIS channel, PDUs, and
+     * the Battleship game grids.
      */
-    public ExampleSimulationProgram(String newDescriptor)
-    {
-        descriptor = newDescriptor;
-        initialize();
+    private void initialize() {
+        initializeDisChannel();
+        initializeSimulationEntities();
+        setupGrids();
+        disChannel.join();
     }
+
     /**
-     * Utility Constructor that allows your example simulation program to override default network address and port
-     * @param address network address to use
-     * @param port corresponding network port to use
+     * Initialize the DIS channel for communication, setting verbose output for
+     * debugging and creating the PduFactory.
      */
-    public ExampleSimulationProgram(String address, int port)
-    {
-        disChannel.setNetworkAddress            (address);
-        disChannel.setNetworkPort               (port);
-        disChannel.setVerboseComments           (true);       // TODO rename library method to disambiguate CommentPDU
-                                                                            // TODO still seems really chatty... add silent mode?
-        disChannel.setVerboseDisNetworkInterface(true);  // Default false
-        disChannel.setVerbosePduRecorder        (true);       // default false
-        initialize();
-    }
-    
-    /** Initialize channel setup for OpenDis7 and report a test PDU
-     * @see initializeDisChannel
-     * @see initializeSimulationEntities */
-    private void initialize()
-    {
-        initializeDisChannel(); // must come first, uses PduFactory
-        
-        initializeSimulationEntities(); // set unchanging parameters
-        
-        disChannel.join(); // TODO further functionality expected
-        
-        String timeStepMessage = "Simulation timestep duration " + getSimulationTimeStepDuration() + " seconds";
-        disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_SIMULATION_TIMESTEP, timeStepMessage);
-        // additional constructor initialization can go here
-    }
-    
-    /** Initialize channel setup for OpenDis7 and report a test PDU */
-    private void initializeDisChannel()
-    {
-        if (disChannel == null)
-            disChannel = new DisChannel();
-        else
-        {
-            disChannel.printlnTRACE ("*** warning, duplicate invocation of initializeDisChannel() ignored");
-            return;
-        }
-        pduFactory     = disChannel.getPduFactory();
-        disChannel.setDescriptor(this.getClass().getSimpleName()); // ExampleSimulationProgram might be a superclass
+    private void initializeDisChannel() {
+        disChannel = new DisChannel();
+        pduFactory = disChannel.getPduFactory();
+        disChannel.setDescriptor(this.getClass().getSimpleName());
         disChannel.setUpNetworkInterface();
-        disChannel.printlnTRACE ("just checking: disChannel.getNetworkAddress()=" + disChannel.getNetworkAddress() +
-                                                         ", getNetworkPort()="    + disChannel.getNetworkPort());
         disChannel.getDisNetworkInterface().setVerbose(true); // sending and receipt
-        disChannel.printlnTRACE ("just checking: hasVerboseSending()=" + disChannel.getDisNetworkInterface().hasVerboseSending() +
-                                              ", hasVerboseReceipt()=" + disChannel.getDisNetworkInterface().hasVerboseReceipt());
         disChannel.getPduRecorder().setVerbose(true);
-
-        // TODO confirm whether recorder is explicitly started by programmer (or not)
-        
-//      disChannel.sendCommentPdu(VariableRecordType.OTHER, "DisThreadedNetworkInterface.initializeDisChannel() complete"); // hello channel, debug
     }
-    
-    /** Get ready, get set... initialize simulation entities.  Who's who in the zoo?
+
+    /**
+     * Initialize simulation entities by creating PDUs for firing events.
      */
-    public void initializeSimulationEntities()
-    {        
-        if (pduFactory == null)
-            pduFactory      = disChannel.getPduFactory();
-        entityStatePdu_1    = pduFactory.makeEntityStatePdu();
-        entityStatePdu_2    = pduFactory.makeEntityStatePdu();
-        firePdu_1a          = pduFactory.makeFirePdu();
-        firePdu_1b          = pduFactory.makeFirePdu();
-        munitionDescriptor1 = new MunitionDescriptor();
-        
-        // Your model setup: define participants.  who's who in this zoo?
-        // Assuming you keep track of entity objects...  here is some support for for Entity 1.
-        
-        // PDU objects are already declared and instances created, so now set their values.
-        // who is who in our big zoo, sufficient for global participation if we need it
-        entityID_1.setSiteID(1).setApplicationID(2).setEntityID(3); // made-up example ID;
-        disChannel.addEntity(entityID_1);
-        
-        entityID_2.setSiteID(1).setApplicationID(2).setEntityID(4); // made-up example ID; 
-        disChannel.addEntity(entityID_2);
-        // TODO someday, use enumerations for sites as part of a SimulationManager object; e.g. is there a unique site triplet for MOVES Institute?
-
-        entityStatePdu_1.setEntityID(entityID_1);
-        entityStatePdu_1.setForceId(ForceID.FRIENDLY);
-        entityStatePdu_1.setEntityType(new _001Poseidon());       // note import statement above
-//      entityStatePdu_1.setMarking("Entity #1");
-        entityStatePdu_1.setEntityType(new edu.nps.moves.dis7.entities.usa.platform.air.MV22B()); // note import statement at top
-        entityStatePdu_1.setMarking("Entity #53");
-        entityStatePdu_1.getMarkingString(); // use Netbeans Debug breakpoint here to check left justified...
-
-        entityStatePdu_2.setEntityID(entityID_2);
-        entityStatePdu_2.setForceId(ForceID.OPPOSING);
-        entityStatePdu_2.setEntityType(new _002Triton()); // note import statement above
-        entityStatePdu_2.setMarking("Entity #2");
-
-        // TODO how should we customize this munition?  what are key parameters for your simulation? 
-        // more is needed here by scenario authors...
-        munitionDescriptor1.setQuantity(1);
-        firePdu_1a.setDescriptor(munitionDescriptor1).setRange(1000.0f);
+    private void initializeSimulationEntities() {
+        firePduPlayer1 = pduFactory.makeFirePdu();
+        firePduPlayer2 = pduFactory.makeFirePdu();
+        gridStatusPdu = pduFactory.makeCommentPdu();
     }
-                 
+
     /**
-     * This runSimulationLoops() method is for you, a customizable programmer-modifiable
-     * code block for defining and running a new simulation of interest.
-     * 
-     * Welcome! Other parts of this program handle bookkeeping and plumbing tasks so that
-     * you can focus on your model entities and activities.
-     * Expandable support includes DIS EntityStatePdu, FirePdu and CommentPdu all available for 
-     * modification and sending in a simulation loop.
-     * Continuous improvement efforts seek to make this program as easy and straightforward
-     * as possible for DIS simulationists to use and adapt.
-     * All of the other methods are setup, teardown and configuration that you may find
-     * interesting, even helpful, but don't really have to worry about.
+     * Set up the game grids for each player, marking empty water and ship
+     * positions.
      */
-    @SuppressWarnings("SleepWhileInLoop") // yes we might do that
-    public void runSimulationLoops ()
-    {
-      try
-      {              
-        final int     SIMULATION_MAX_LOOP_COUNT = 10; // be deliberate out there!  also avoid infinite loops.
-              int     simulationLoopCount = 0;        // variable, initialized at 0
-              boolean simulationComplete = false;     // sentinel variable as termination condition, are we done yet?
-        
-        // TODO reset Clock Time for today's date and timestamp to zero, providing consistent outputs for each simulation run
-        String timeMessage = "Simulation time " + simulationTimeSeconds + " at LocalDateTime " + LocalDateTime.now();
-        disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_TIME, timeMessage);
-        // TODO replace enumeration with disChannel.COMMENTPDU_TIME
-        // TODO fix VariableRecordType.TIME_AMP_DATE_VALID
-        
-        // ===================================================================================================
-        // loop the simulation while allowed, programmer can set additional conditions to break out and finish
-        while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT)  // are we done yet?
-        {
-            simulationLoopCount++; // good practice: increment loop counter as first action in that loop
-            
-            // =============================================================================================
-            // * your own simulation code starts here! *****************************************************
-            // =============================================================================================
-            
-            //  are there any other variables to modify at the beginning of your loop?
-            
-            // are your reading any DIS PDUs from the network?  check for them here
-            
-            // compute a track, update an ESPDU, whatever it is that your model is doing...
-            
-            // Where is my entity?  Insert changes in position; this sample only changes X position.
-            entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + 1.0); // 1m per timestep
-            
-            // decide whether to fire, and then update the firePdu.  Hmmm, you might want a target to shoot at!
-            
-            // etc. etc. your code goes here for your simulation of interest
-                
-            // something happens between my simulation entities, la de da de da...
-            System.out.println ("... My simulation just did something, no really...");
-            System.out.flush(); // make sure this arrives to user even if other threads somehow become deadlocked
-            
-            
-            // make your reports: narrative code for CommentPdu here (set all to empty strings to avoid sending)
-            narrativeMessage1 = "MV3500 ExampleSimulationProgram";
-            narrativeMessage2 = "runSimulation() loop " + simulationLoopCount;
-            narrativeMessage3 = ""; // intentionally blank for testing
-
-            // your loop termination condition goes here
-            if (simulationLoopCount > MAX_LOOP_COUNT) // for example
-            {
-                simulationComplete = true;
-            }      
-            // =============================================================================================
-            // * your own simulation code is finished here! ************************************************
-            // =============================================================================================
-            
-            // staying synchronized with timestep: wait duration for elapsed time in this loop
-            // Thread.sleep needs a (long) parameter for milliseconds, which are clumsy to use sometimes
-            Thread.sleep((long)(getSimulationTimeStepDuration() * 1000)); // units of seconds * (1000 msec/sec) = milliseconds
-            System.out.println ("... [Pausing for " + getSimulationTimeStepDuration() + " seconds]");
-            
-            // OK now send the status PDUs for this loop, and then continue
-            System.out.println ("... sending PDUs of interest for simulation step " + simulationLoopCount + ", monitor loopback to confirm sent");
-            System.out.flush();
-            
-            // TODO set timesteps in PDUs
-            
-            sendAllPdusForLoopTimestep(simulationTimeSeconds,
-                                       entityStatePdu_1, 
-                                            firePdu_1a, 
-                                         DisChannel.COMMENTPDU_APPLICATION_STATUS, 
-                                           narrativeMessage1, narrativeMessage2, narrativeMessage3);
-            disChannel.sendSinglePdu(simulationTimeSeconds, entityStatePdu_2); // me too i.e. 2!
-            
-            System.out.println ("... [PDUs of interest successfully sent for this loop]");
-            System.out.flush();
-            
-            // ===============================
-            // current loop now finished, check whether to terminate if simulation complete, otherwise continue
-            if (simulationComplete || (simulationLoopCount > 10000)) // for example; including fail-safe condition is good
-            {
-                System.out.println ("... [loop termination condition met, simulationComplete=" + simulationComplete + "]"); // ", final loopCount=" + loopCount + 
-                System.out.flush();
-                break;
+    private void setupGrids() {
+        // Initialize grids with empty water '~'
+        for (int i = 0; i < GRID_SIZE; i++) {
+            for (int j = 0; j < GRID_SIZE; j++) {
+                player1Grid[i][j] = '~';
+                player2Grid[i][j] = '~';
             }
-            simulationTimeSeconds += getSimulationTimeStepDuration(); // good practice: increment simulationTime as lastst action in that loop
-                    
-        }   // end of simulation loop, continue until done
-        // ===================================================================================================// ===================================================================================================// ===================================================================================================// ===================================================================================================
-
-        narrativeMessage2 = "runSimulation() completed successfully"; // all done, so tell everyone else on the channel
-        // TODO better javadoc needs to be autogenerated for VariableRecordType enumerations
-        disChannel.sendCommentPdu(DisChannel.COMMENTPDU_NARRATIVE, narrativeMessage1, narrativeMessage2, narrativeMessage3);
-        System.out.println ("... [final=completion CommentPdu successfully sent for simulation]");
-        
-//        disChannel.getPduRecorder(). TODO record XML as well
-        disChannel.leave(); // embedded SimulationManager is expected to send appropriate PDUs for entity, application shutdown
-      } 
-      catch (InterruptedException iex) // handle any exception that your code might choose to provoke!
-      {
-        Logger.getLogger(ExampleSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
-      }
+        }
+
+        // Place ships on the grids ('P' denotes a ship)
+        for (int[] ship : player1Ships) {
+            player1Grid[ship[0]][ship[1]] = 'P';
+        }
+        for (int[] ship : player2Ships) {
+            player2Grid[ship[0]][ship[1]] = 'P';
+        }
     }
 
     /**
-     * Send EntityState, Fire, Comment PDUs that got updated for this loop, reflecting state of current simulation timestep.
-     * @param simTimeSeconds simulation time in second, applied to PDU as timestamp
-     * @param entityStatePdu the ESPDU to send, if any
-     * @param firePdu        the FirePDU to send, if any
-     * @param commentType    enumeration value describing purpose of the narrative comment PDU
-     * @param comments       String array of narrative comments
-     * @see DisChannel
-//   * @see DisTime // TODO find renamed version
-     * @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html" target="_blank">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
+     * This runSimulationLoops() method is for you, a customizable
+     * programmer-modifiable code block for defining and running a new
+     * simulation of interest.
      */
-    public void sendAllPdusForLoopTimestep(double simTimeSeconds,
-                                   EntityStatePdu entityStatePdu,
-                                          FirePdu firePdu,
-                               VariableRecordType commentType,
-                                     // vararg... variable-length set of String comments can optionally follow
-                                        String... comments)
-    {
-        if (entityStatePdu != null)
-            disChannel.sendSinglePdu(simTimeSeconds, entityStatePdu);
-            
-        if (firePdu != null)
-            disChannel.sendSinglePdu(simTimeSeconds, firePdu); // bang
-        
-        disChannel.sendCommentPdu(simTimeSeconds, commentType, comments); // empty comments are filtered
+    public void runSimulationLoops() {
+        int turnCount = 0;
+        while (turnCount < MAX_TURNS) {
+            if (isPlayer1Turn) {
+                // Player 1 systematically searches Player 2's grid
+                int[] target = selectNextTargetForPlayer1();
+                handleFire(firePduPlayer1, player2Grid, target, "Player 1");
+            } else {
+                // Player 2 fires at Player 1 randomly
+                int[] target = selectRandomTarget();
+                handleFire(firePduPlayer2, player1Grid, target, "Player 2");
+            }
+
+            // Switch turns and increment turn counter
+            isPlayer1Turn = !isPlayer1Turn;
+            turnCount++;
+
+            // Check for win conditions
+            if (checkWinCondition(player1Grid)) {
+                System.out.println("Player 2 wins!");
+                break;
+            } else if (checkWinCondition(player2Grid)) {
+                System.out.println("Player 1 wins!");
+                break;
+            }
+
+            // Wait for the next simulation step
+            try {
+                Thread.sleep((long) (simulationTimeStepDuration * 1000)); // units of seconds * (1000 msec/sec) = milliseconds
+            } catch (InterruptedException iex) {
+                Logger.getLogger(ExampleSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
+            }
+
+            // Increment simulation time
+            simulationTimeSeconds += simulationTimeStepDuration;
+        }
     }
-    
+
     /**
-     * Initial execution via main() method: handle args array of command-line initialization (CLI) arguments here
-     * @param args command-line parameters: network address and port
+     * Systematically select the next target for Player 1 in a row-by-row
+     * manner.
+     *
+     * @return the coordinates of the next target cell.
      */
-    protected void handleArguments (String[] args)
-    {
-        // initial execution: handle args array of initialization arguments here
-        if (args.length == 2) 
-        {
-            if ((args[0] != null) && !args[0].isEmpty())
-                thisProgram.disChannel.setNetworkAddress(args[0]);
-            if ((args[1] != null) && !args[1].isEmpty())
-                thisProgram.disChannel.setNetworkPort(Integer.parseInt(args[1]));
+    private int[] selectNextTargetForPlayer1() {
+        // Systematically select the next target in a row-by-row manner
+        int[] target = {player1SearchRow, player1SearchCol};
+
+        // Move to the next column
+        player1SearchCol++;
+        // If end of row is reached, move to the next row and reset column
+        if (player1SearchCol >= GRID_SIZE) {
+            player1SearchCol = 0;
+            player1SearchRow++;
         }
-        else if (args.length != 0) 
-        {
-            System.err.println("Usage: " + thisProgram.getClass().getSimpleName() + " [address port]");
-            System.exit(-1);
+
+        // Ensure search stays within grid bounds
+        if (player1SearchRow >= GRID_SIZE) {
+            player1SearchRow = 0; // Reset search if bounds are exceeded
         }
+
+        return target;
     }
 
     /**
-     * Get simple descriptor (such as parent class name) for this network interface, used in trace statements
-     * @return simple descriptor name
+     * Randomly select a target on the grid for Player 2's turn.
+     *
+     * @return the coordinates of the randomly selected target cell.
      */
-    public String getDescriptor() {
-        return descriptor;
+    private int[] selectRandomTarget() {
+        int x = (int) (Math.random() * GRID_SIZE);
+        int y = (int) (Math.random() * GRID_SIZE);
+        return new int[]{x, y};
     }
 
     /**
-     * Set new simple descriptor (such as parent class name) for this network interface, used in trace statements
-     * @param newDescriptor simple descriptor name for this interface
+     * Handles the firing action, setting relevant data in the FirePdu, checking
+     * if the target is a hit or miss, updating the grid, and sending the
+     * appropriate PDU.
+     *
+     * @param firePdu the FirePdu object to use for the shot.
+     * @param grid the grid of the player being fired at.
+     * @param target the coordinates of the target cell.
+     * @param player the name of the player firing the shot.
      */
-    public void setDescriptor(String newDescriptor) {
-        if (newDescriptor == null)
-            newDescriptor = "";
-        this.descriptor = newDescriptor;
+    private void handleFire(FirePdu firePdu, char[][] grid, int[] target, String player) {
+        int x = target[0];
+        int y = target[1];
+
+        // Set relevant details in the FirePdu
+        firePdu.setFiringEntityID(new EntityID().setEntityID(player.equals("Player 1") ? 1 : 2));
+        firePdu.setTargetEntityID(new EntityID().setEntityID(player.equals("Player 1") ? 1 : 2));
+        Vector3Double fireLoc = new Vector3Double(); //annoying that there isn't a Vector3Double(x, y, z) constructor...
+        fireLoc.setX(x);
+        fireLoc.setY(y);
+        fireLoc.setZ(0.0);
+        firePdu.setLocationInWorldCoordinates(fireLoc);
+        firePdu.setDescriptor(munitionDescriptor1); // Not needed I guess
+        firePdu.setRange(100.0f);// Not needed I gueess
+
+        // Print the firing action
+        System.out.println(player + " fires at (" + x + ", " + y + ").");
+
+        // Determine hit or miss and update the game grid
+        if (grid[x][y] == 'P') {
+            grid[x][y] = 'H'; // Mark as Hit
+            firePdu.setFireMissionIndex(1); // Indicate that this was a successful hit with an index of 1
+            System.out.println(player + " hits a ship at (" + x + ", " + y + ")!");
+        } else if (grid[x][y] == '~') {
+            grid[x][y] = 'M'; // Mark as Miss
+            firePdu.setFireMissionIndex(0); // Indicate that this was a miss with an index of 0
+            System.out.println(player + " misses at (" + x + ", " + y + ").");
+        } else {
+            System.out.println(player + " fires at (" + x + ", " + y + ") but it's already hit/missed.");
+        }
+
+        // Send the FirePdu to represent the shot
+        disChannel.sendSinglePdu(simulationTimeSeconds, firePdu);
+
+        // Send the updated grid status of both players
+        sendGridStatus();
+    }
+
+    /**
+     * Checks the win condition by verifying if all ships on the grid have been
+     * hit.
+     *
+     * @param grid the grid to check.
+     * @return true if all ships are hit; false otherwise.
+     */
+    private boolean checkWinCondition(char[][] grid) {
+        // Check if all ships have been hit
+        for (int i = 0; i < GRID_SIZE; i++) {
+            for (int j = 0; j < GRID_SIZE; j++) {
+                if (grid[i][j] == 'P') {
+                    return false; // There are still ships left
+                }
+            }
+        }
+        return true; // All ships have been hit
     }
 
     /**
-     * parameter accessor method
-     * @return the simulationTimeStepDuration in seconds
+     * Sends the current grid status of both players as a CommentPdu.
      */
-    public double getSimulationTimeStepDuration() {
-        return simulationTimeStepDuration;
+    private void sendGridStatus() {
+        // Construct a string representation of both grids
+        StringBuilder gridStatus = new StringBuilder();
+        gridStatus.append("Player 1 Grid:\n");
+        appendGridToString(gridStatus, player1Grid);
+        gridStatus.append("Player 2 Grid:\n");
+        appendGridToString(gridStatus, player2Grid);
+
+        // Set the grid status in the CommentPdu
+        gridStatusPdu.getVariableDatums().clear(); // Clear previous comments
+        gridStatusPdu.getVariableDatums().add(new VariableDatum()
+                .setVariableDatumID(VariableRecordType.OTHER)
+                .setVariableDatumValue(gridStatus.toString().getBytes())
+                .setVariableDatumLengthInBytes(gridStatus.toString().getBytes().length));
+
+        // Send the CommentPdu containing the grid status
+        disChannel.sendSinglePdu(simulationTimeSeconds, gridStatusPdu);
     }
 
     /**
-     * parameter accessor method
-     * @param timeStepDurationSeconds the simulationTimeStepDuration in seconds to set
+     * Appends the current grid status to a StringBuilder.
+     *
+     * @param sb the StringBuilder to append to.
+     * @param grid the grid to represent.
      */
-    public void setSimulationTimeStepDuration(double timeStepDurationSeconds) {
-        this.simulationTimeStepDuration = timeStepDurationSeconds;
+    private void appendGridToString(StringBuilder sb, char[][] grid) {
+        for (char[] row : grid) {
+            for (char cell : row) {
+                sb.append(cell).append(' ');
+            }
+            sb.append('\n');
+        }
     }
-    
-    /** Locally instantiable copy of program, can be subclassed. */
-    protected static ExampleSimulationProgram thisProgram;
-  
+
     /**
      * Main method is first executed when a program instance is loaded.
-     * @see <a href="https://docs.oracle.com/javase/tutorial/getStarted/application/index.html" target="_blank">Java Tutorials: A Closer Look at the "Hello World!" Application</a>
+     *
      * @param args command-line parameters: network address and port.
-     *    Command-line arguments are an array of optional String parameters that are passed from execution environment during invocation
+     * Command-line arguments are an array of optional String parameters that
+     * are passed from execution environment during invocation
      */
-    public static void main(String[] args)
-    {
-        thisProgram = new ExampleSimulationProgram("test constructor"); // create instance of self within static main() method
-        
-        thisProgram.disChannel.printlnTRACE("main() started...");
-        
-        thisProgram.handleArguments(args); // process any command-line invocation arguments
-
-        thisProgram.runSimulationLoops(); // ... your simulation execution code goes in there ...
-        
-        thisProgram.disChannel.tearDownNetworkInterface(); // make sure no processes are left lingering
-        
-        thisProgram.disChannel.printlnTRACE("complete."); // report successful completion
-        
-        System.exit(0); // ensure all threads and sockets released
+    public static void main(String[] args) {
+        ExampleSimulationProgram game = new ExampleSimulationProgram();
+        game.runSimulationLoops();
+        System.out.println("Game Over");
     }
 }
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/ExampleSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/ExampleSimulationProgram.java
index a428dd2d01f173cac07c2bceefee9d12cd275df0..66628a8cc36a6e5c40ebfa947c28fbb835f65d27 100644
--- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/ExampleSimulationProgram.java
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/ExampleSimulationProgram.java
@@ -8,7 +8,6 @@
  */
 package MV3500Cohort2024JulySeptember.homework3.Williams;
 
-
 import edu.nps.moves.dis7.entities.swe.platform.surface._001Poseidon;
 import edu.nps.moves.dis7.entities.swe.platform.surface._002Triton;
 import edu.nps.moves.dis7.enumerations.*;
@@ -25,9 +24,9 @@ import java.util.logging.Logger;
  * tasks of interest, and then reporting activity via PDUs to the network.
  * Default program initialization includes PDU recording turned on by default.
  * 
- * Homework 3 Networking choices:
+ * Homework 3 networking choices:
  * This simulation uses UDP multicast for efficient distribution of PDUs to 
- * multiple participants, which is suitable for large-scale simulations where 
+ * multiple participants, which is great for large-scale simulations where 
  * state updates need to reach all networked participants. UDP is chosen over 
  * TCP due to its lower latency, which is essential for real-time simulations.
  *
@@ -39,65 +38,38 @@ import java.util.logging.Logger;
  */
 public class ExampleSimulationProgram
 {
-    /* **************************** infrastructure code, modification is seldom needed ************************* */
-                 
     private   String     descriptor = this.getClass().getSimpleName();
-    /** DIS channel defined by network address/port combination includes multiple utility capabilities */
     protected DisChannel disChannel;
-    /** Factory object used to create new PDU instances */
     protected PduFactory pduFactory;
     
-    /** seconds per loop for real-time or simulation execution */
-    private double  simulationTimeStepDuration  =  1.0; // seconds TODO encapsulate
-    /** initial simulation time in seconds */
+    private double  simulationTimeStepDuration  =  1.0; 
     double  simulationTimeInitial = 0.0;
-    /** current simulation time in seconds */
     double  simulationTimeSeconds = simulationTimeInitial;
-    /** Maximum number of simulation loops */
     int MAX_LOOP_COUNT = 4;
     
     String narrativeMessage1 = new String();
     String narrativeMessage2 = new String();
     String narrativeMessage3 = new String();
     
-    /** EntityID settings for entity 1 */
     protected EntityID           entityID_1          = new EntityID();
-    /** EntityID settings for entity 2 */
     protected EntityID           entityID_2          = new EntityID();
-    /** ESPDU for entity 1 */
     protected EntityStatePdu     entityStatePdu_1;
-    /** ESPDU for entity 2 */
     protected EntityStatePdu     entityStatePdu_2;
-    /** FirePdu for entity 1 first  weapon (if any) */
     protected FirePdu            firePdu_1a;
-    /** FirePdu for entity 1 second weapon (if any) */
     protected FirePdu            firePdu_1b;
-    /** MunitionDescriptor for these weapons */
     protected MunitionDescriptor munitionDescriptor1;
     
-    /**
-     * Constructor to create an instance of this class.
-     * Design goal: additional built-in initialization conveniences can go here
-     * to keep your efforts focused on the runSimulation() method.
-     */
     public ExampleSimulationProgram()
     {
         initialize();
     }
-    /**
-     * Constructor to create an instance of this class.
-     * @param newDescriptor describes this program, useful for logging and debugging
-     */
+
     public ExampleSimulationProgram(String newDescriptor)
     {
         descriptor = newDescriptor;
         initialize();
     }
-    /**
-     * Utility Constructor that allows your example simulation program to override default network address and port
-     * @param address network address to use
-     * @param port corresponding network port to use
-     */
+
     public ExampleSimulationProgram(String address, int port)
     {
         disChannel.setNetworkAddress(address);
@@ -108,9 +80,6 @@ public class ExampleSimulationProgram
         initialize();
     }
     
-    /** Initialize channel setup for OpenDis7 and report a test PDU
-     * @see initializeDisChannel
-     * @see initializeSimulationEntities */
     private void initialize()
     {
         initializeDisChannel();
@@ -122,7 +91,6 @@ public class ExampleSimulationProgram
         disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_SIMULATION_TIMESTEP, timeStepMessage);
     }
     
-    /** Initialize channel setup for OpenDis7 and report a test PDU */
     private void initializeDisChannel()
     {
         if (disChannel == null)
@@ -143,8 +111,6 @@ public class ExampleSimulationProgram
         disChannel.getPduRecorder().setVerbose(true);
     }
     
-    /** Initialize simulation entities.
-     */
     public void initializeSimulationEntities()
     {        
         if (pduFactory == null)
@@ -155,30 +121,31 @@ public class ExampleSimulationProgram
         firePdu_1b          = pduFactory.makeFirePdu();
         munitionDescriptor1 = new MunitionDescriptor();
         
-        // Define participants
-        entityID_1.setSiteID(1).setApplicationID(2).setEntityID(3);
+        entityID_1.setSiteID((int)(Math.random() * 100))
+                  .setApplicationID((int)(Math.random() * 100))
+                  .setEntityID((int)(Math.random() * 100));
         disChannel.addEntity(entityID_1);
         
-        entityID_2.setSiteID(1).setApplicationID(2).setEntityID(4);
+        entityID_2.setSiteID((int)(Math.random() * 100))
+                  .setApplicationID((int)(Math.random() * 100))
+                  .setEntityID((int)(Math.random() * 100));
         disChannel.addEntity(entityID_2);
 
         entityStatePdu_1.setEntityID(entityID_1);
         entityStatePdu_1.setForceId(ForceID.FRIENDLY);
         entityStatePdu_1.setEntityType(new _001Poseidon());
-        entityStatePdu_1.setMarking("Entity #53");
+        entityStatePdu_1.setMarking("Ethan's Poseidon #1");
 
         entityStatePdu_2.setEntityID(entityID_2);
         entityStatePdu_2.setForceId(ForceID.OPPOSING);
         entityStatePdu_2.setEntityType(new _002Triton());
-        entityStatePdu_2.setMarking("Entity #2");
+        entityStatePdu_2.setMarking("Ethan's Triton #2");
 
         munitionDescriptor1.setQuantity(1);
         firePdu_1a.setDescriptor(munitionDescriptor1).setRange(1000.0f);
+
     }
                  
-    /**
-     * This runSimulationLoops() method is customizable for running new simulations.
-     */
     @SuppressWarnings("SleepWhileInLoop")
     public void runSimulationLoops ()
     {
@@ -195,13 +162,14 @@ public class ExampleSimulationProgram
         {
             simulationLoopCount++;
             
-            entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + 1.0);
-            
+            entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + (Math.random() * 2));
+
             System.out.println ("... My simulation just did something...");
             System.out.flush();
             
-            narrativeMessage1 = "MV3500 ExampleSimulationProgram";
-            narrativeMessage2 = "runSimulation() loop " + simulationLoopCount;
+            narrativeMessage1 = "Ethan's Custom Simulation Program";
+            narrativeMessage2 = "Loop " + simulationLoopCount + " - MV3500 Custom Version";
+            narrativeMessage3 = "Simulation developed by Ethan Williams";
 
             if (simulationLoopCount > MAX_LOOP_COUNT) 
             {
@@ -242,14 +210,6 @@ public class ExampleSimulationProgram
       }
     }
 
-    /**
-     * Send EntityState, Fire, Comment PDUs for this loop.
-     * @param simTimeSeconds simulation time in seconds
-     * @param entityStatePdu the ESPDU to send
-     * @param firePdu the FirePDU to send
-     * @param commentType enumeration value describing purpose of the narrative comment PDU
-     * @param comments String array of narrative comments
-     */
     public void sendAllPdusForLoopTimestep(double simTimeSeconds,
                                    EntityStatePdu entityStatePdu,
                                           FirePdu firePdu,
@@ -265,10 +225,6 @@ public class ExampleSimulationProgram
         disChannel.sendCommentPdu(simTimeSeconds, commentType, comments);
     }
     
-    /**
-     * Initial execution via main() method: handle args array of command-line initialization (CLI) arguments here
-     * @param args command-line parameters: network address and port
-     */
     protected void handleArguments (String[] args)
     {
         if (args.length == 2) 
@@ -285,47 +241,26 @@ public class ExampleSimulationProgram
         }
     }
 
-    /**
-     * Get simple descriptor for this network interface, used in trace statements
-     * @return simple descriptor name
-     */
     public String getDescriptor() {
         return descriptor;
     }
 
-    /**
-     * Set new simple descriptor for this network interface, used in trace statements
-     * @param newDescriptor simple descriptor name for this interface
-     */
     public void setDescriptor(String newDescriptor) {
         if (newDescriptor == null)
             newDescriptor = "";
         this.descriptor = newDescriptor;
     }
 
-    /**
-     * parameter accessor method
-     * @return the simulationTimeStepDuration in seconds
-     */
     public double getSimulationTimeStepDuration() {
         return simulationTimeStepDuration;
     }
 
-    /**
-     * parameter accessor method
-     * @param timeStepDurationSeconds the simulationTimeStepDuration in seconds to set
-     */
     public void setSimulationTimeStepDuration(double timeStepDurationSeconds) {
         this.simulationTimeStepDuration = timeStepDurationSeconds;
     }
     
-    /** Locally instantiable copy of program, can be subclassed. */
     protected static ExampleSimulationProgram thisProgram;
   
-    /**
-     * Main method is first executed when a program instance is loaded.
-     * @param args command-line parameters: network address and port.
-     */
     public static void main(String[] args)
     {
         thisProgram = new ExampleSimulationProgram("test constructor");
@@ -342,4 +277,4 @@ public class ExampleSimulationProgram
         
         System.exit(0);
     }
-}
\ No newline at end of file
+}
diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/README.md
index a1c26dac941cf60805b78c8b235494c74e253bfc..94d69620e29da953dcf8ce18811801c9635e01e8 100644
--- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/README.md
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/README.md
@@ -1,9 +1,3 @@
-For Homework 3, I modified the OpenDIS ExampleSimulationProgram to enhance its functionality
-by experimenting with entity enumeration values and adjusting the network communication setup.
-On the networking side, I configured the program to use UDP multicast for distribution of the PDUs across
-multiple participants in the simulation. I did this to attempt to create the
-low-latency communication needed in large-scale simulations, where UDP's minimal overhead is
-advantageous, and multicast ensures that updates reach all clients at the same time. I also
-enabled verbose logging to facilitate debugging. Additionally, I adjusted
-the simulation loop to increment Entity 1’s position in each iteration, simulating movement, and set
-the loop to run for a maximum of 10 iterations.
\ No newline at end of file
+For Homework 3, I altered the ExampleSimulationProgram by randomizing the entity IDs
+and I also introduced randomized movement patterns for the entities during the simulation loop.
+These changes make the simulation more realistic and ensuring variability in each run.
\ No newline at end of file
diff --git a/build.properties b/build.properties
index 2d38b9f13c7e911590a334e2f995526a70a5c100..401b692d7ddf7a3e39105df0dbb812841263aeee 100644
--- a/build.properties
+++ b/build.properties
@@ -17,19 +17,20 @@ common.run.args=-Xmx256m \
 
 win.run.args=${common.run.args}
 
-run.arg1=-Dawt.useSystemAAFontSettings=gasp
-unix.run.args=${common.run.args} ${run.arg1}
+unix.run.args=${common.run.args} \
+    -Dawt.useSystemAAFontSettings=gasp
 
-run.arg2=-Dapple.awt.graphics.UseQuartz=true \
+mac.run.args=${common.run.args} \
+    -Dapple.awt.graphics.UseQuartz=true \
     -Dapple.laf.useScreenMenuBar=true \
     -Dapple.awt.brushMetalLook=true \
     -Xdock:name=${product.shortname} \
     --add-exports java.desktop/com.apple.eawt=ALL-UNNAMED
-mac.run.args=${common.run.args} ${run.arg2}
 
 # property used to identify Viskit config files
 dot.viskit.dir=${user.home}/.${product.shortname}
 c_app.xml=${viskit.dir}/configuration/c_app.xml
 c_gui.xml=${viskit.dir}/configuration/c_gui.xml
+proj.xml=${viskit.dir}/configuration/viskitProject.xml
 
 splash.image=${viskit.dir}/configuration/ViskitSplash2.png
diff --git a/build.xml b/build.xml
index 3e8559d124c43ae4053da712ce3882372836c8bd..52600ba1db0af2eb4f507158ca66538eae12ac22 100644
--- a/build.xml
+++ b/build.xml
@@ -319,7 +319,7 @@ POSSIBILITY OF SUCH DAMAGE.
         <copy                todir ="${dot.viskit.dir}"           file="${c_gui.xml}"/>
     </target>
 
-    <target name="reset.viskit" description="clear an out of synch configuration and metadata directory - only when necessary">
+    <target name="reset.viskit" description="Replace an out-of-synch configuration with known good defaults - only when necessary">
         <echo message="Reset user's Viskit configuration files in ${dot.viskit.dir}"/>
         <delete includeemptydirs="yes" dir="${dot.viskit.dir}"/>
         <mkdir dir="${dot.viskit.dir}"/>
@@ -327,6 +327,7 @@ POSSIBILITY OF SUCH DAMAGE.
         <!-- ${c_app.xml} and ${c_gui.xml} are properties in the build.properties definitions -->
         <copy todir="${dot.viskit.dir}" file="${c_app.xml}" verbose="true"/>
         <copy todir="${dot.viskit.dir}" file="${c_gui.xml}" verbose="true"/>
+        <copy todir="examples/src/ViskitOpenDis7Examples" file="${proj.xml}" overwrite="true"/>
     </target>
 
 </project>
\ No newline at end of file
diff --git a/examples/nbproject/project.properties b/examples/nbproject/project.properties
index a659c6016220db9cc02cbfe18f4b1c0ce29a9244..bb12d3f683a507710517c28cff44c8c0ff5a9892 100644
--- a/examples/nbproject/project.properties
+++ b/examples/nbproject/project.properties
@@ -1,121 +1,121 @@
-annotation.processing.enabled=true
-annotation.processing.enabled.in.editor=false
-annotation.processing.processors.list=
-annotation.processing.run.all.processors=true
-annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
-application.desc=Example programs provided as part of NPS course Networked Graphics MV3500. This course is an introduction to network communications in simulation applications. Topics include an introduction to the TCP/IP protocol stack; TCP/IP socket communications, including TCP, UDP, and multicast; and protocol design issues, with emphasis on Distributed Interactive Simulation (DIS) Protocol and High Level Architecture (HLA). Course emphasis is on creation and testing of network programming network code and web-browser applications.
-application.homepage=https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/examples
-application.splash=..\\..\\NetworkedGraphicsMV3500\\documentation\\images\\OpenDisSurferDude.png
-application.title=NPS Networked Graphics MV3500 examples
-application.vendor=Don Brutzman
-build.classes.dir=${build.dir}/classes
-build.classes.excludes=**/*.java,**/*.form
-# This directory is removed when the project is cleaned:
-build.dir=build
-build.generated.dir=${build.dir}/generated
-build.generated.sources.dir=${build.dir}/generated-sources
-# Only compile against the classpath explicitly listed here:
-build.sysclasspath=ignore
-build.test.classes.dir=${build.dir}/test/classes
-build.test.results.dir=${build.dir}/test/results
-# Uncomment to specify the preferred debugger connection transport:
-#debug.transport=dt_socket
-debug.classpath=\
-    ${run.classpath}
-debug.modulepath=\
-    ${run.modulepath}
-debug.test.classpath=\
-    ${run.test.classpath}
-debug.test.modulepath=\
-    ${run.test.modulepath}
-# Files in build.classes.dir which should be excluded from distribution jar
-dist.archive.excludes=
-# This directory is removed when the project is cleaned:
-dist.dir=dist
-dist.name=Networked_Graphics_MV3500_examples
-dist.jar=${dist.dir}/${dist.name}.jar
-dist.javadoc.dir=${dist.dir}/javadoc
-endorsed.classpath=
-project.licensePath=../license.txt
-viskit.proj.dir=ViskitOpenDis7Examples
-viskit.proj.lib.dir=src/${viskit.proj.dir}/lib
-opendis.helper=SimkitOpenDis7Examples.run.OpenDisHelper
-excludes=ViskitOpenDis7Examples/
-file.reference.dis-enums-1.3.jar=../lib/dis-enums-1.3.jar
-file.reference.opendis7-full.jar=../lib/opendis7-full.jar
-file.reference.open-dis_4.16.jar=../lib/open-dis_4.16.jar
-file.reference.simkit-doc.zip=../lib/simkit-doc.zip
-file.reference.simkit-src.zip=../lib/simkit-src.zip
-file.reference.simkit.jar=../lib/simkit.jar
-#file.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-classes.jar
-#file.reference.opendis7-pdus-classes.jar=../lib/opendis7-pdus-classes.jar
-includes=**/*.java
-jar.compress=false
-javac.classpath=\
-    ${file.reference.opendis7-full.jar}:\
-    ${file.reference.open-dis_4.16.jar}:\
-    ${file.reference.dis-enums-1.3.jar}:\
-    ${file.reference.simkit.jar}:\
-    ${file.reference.simkit-doc.zip}:\
-    ${file.reference.simkit-src.zip}
-#   ${file.reference.opendis7-enumerations-classes.jar}:\
-#   ${file.reference.opendis7-pdus-classes.jar}:\
-
-# Space-separated list of extra javac options
-javac.compilerargs=-Xlint:deprecation -Xlint:unchecked
-javac.deprecation=false
-javac.external.vm=true
-javac.modulepath=
-javac.processormodulepath=
-javac.processorpath=\
-    ${javac.classpath}
-javac.source=21
-javac.target=21
-javac.test.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}
-javac.test.modulepath=\
-    ${javac.modulepath}
-javac.test.processorpath=\
-    ${javac.test.classpath}
-javadoc.additionalparam=-header "NPS Networked Graphics MV3500 Examples"
-javadoc.author=true
-javadoc.encoding=${source.encoding}
-javadoc.html5=false
-javadoc.noindex=false
-javadoc.nonavbar=false
-javadoc.notree=false
-javadoc.private=false
-#javadoc.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-javadoc.jar
-javadoc.splitindex=true
-javadoc.use=true
-javadoc.version=false
-javadoc.windowtitle=MV3500 Examples
-jlink.launcher=false
-jlink.launcher.name=Networked_Graphics_MV3500_examples
-main.class=TcpExamples.TcpExample1Telnet
-manifest.file=manifest.mf
-meta.inf.dir=${src.dir}/META-INF
-mkdist.disabled=false
-platform.active=JDK_22
-run.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}
-# Space-separated list of JVM arguments used when running the project.
-# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
-# To set system properties for unit tests define test-sys-prop.name=value:
-run.jvmargs=
-run.modulepath=\
-    ${javac.modulepath}
-run.test.classpath=\
-    ${javac.test.classpath}:\
-    ${build.test.classes.dir}
-run.test.modulepath=\
-    ${javac.test.modulepath}
-source.encoding=UTF-8
-#source.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-source.jar
-src.dir=src
-src.src.dir=otherProjects\\DisDemo\\src
-src.src2.dir=otherProjects\\DisShooting\\src
-src.src3.dir=otherProjects\\WebSocketGateway\\src
-#src.src4.dir=otherProjects\\BasicServletDemo\\src
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+application.desc=Example programs provided as part of NPS course Networked Graphics MV3500. This course is an introduction to network communications in simulation applications. Topics include an introduction to the TCP/IP protocol stack; TCP/IP socket communications, including TCP, UDP, and multicast; and protocol design issues, with emphasis on Distributed Interactive Simulation (DIS) Protocol and High Level Architecture (HLA). Course emphasis is on creation and testing of network programming network code and web-browser applications.
+application.homepage=https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/examples
+application.splash=..\\..\\NetworkedGraphicsMV3500\\documentation\\images\\OpenDisSurferDude.png
+application.title=NPS Networked Graphics MV3500 examples
+application.vendor=Don Brutzman
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+    ${run.classpath}
+debug.modulepath=\
+    ${run.modulepath}
+debug.test.classpath=\
+    ${run.test.classpath}
+debug.test.modulepath=\
+    ${run.test.modulepath}
+# Files in build.classes.dir which should be excluded from distribution jar
+dist.archive.excludes=
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.name=Networked_Graphics_MV3500_examples
+dist.jar=${dist.dir}/${dist.name}.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+endorsed.classpath=
+project.licensePath=../license.txt
+viskit.proj.dir=ViskitOpenDis7Examples
+viskit.proj.lib.dir=src/${viskit.proj.dir}/lib
+opendis.helper=SimkitOpenDis7Examples.run.OpenDisHelper
+excludes=ViskitOpenDis7Examples/
+file.reference.dis-enums-1.3.jar=../lib/dis-enums-1.3.jar
+file.reference.opendis7-full.jar=../lib/opendis7-full.jar
+file.reference.open-dis_4.16.jar=../lib/open-dis_4.16.jar
+file.reference.simkit-doc.zip=../lib/simkit-doc.zip
+file.reference.simkit-src.zip=../lib/simkit-src.zip
+file.reference.simkit.jar=../lib/simkit.jar
+#file.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-classes.jar
+#file.reference.opendis7-pdus-classes.jar=../lib/opendis7-pdus-classes.jar
+includes=**/*.java
+jar.compress=false
+javac.classpath=\
+    ${file.reference.opendis7-full.jar}:\
+    ${file.reference.open-dis_4.16.jar}:\
+    ${file.reference.dis-enums-1.3.jar}:\
+    ${file.reference.simkit.jar}:\
+    ${file.reference.simkit-doc.zip}:\
+    ${file.reference.simkit-src.zip}
+#   ${file.reference.opendis7-enumerations-classes.jar}:\
+#   ${file.reference.opendis7-pdus-classes.jar}:\
+
+# Space-separated list of extra javac options
+javac.compilerargs=-Xlint:deprecation -Xlint:unchecked
+javac.deprecation=false
+javac.external.vm=true
+javac.modulepath=
+javac.processormodulepath=
+javac.processorpath=\
+    ${javac.classpath}
+javac.source=21
+javac.target=21
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+javac.test.modulepath=\
+    ${javac.modulepath}
+javac.test.processorpath=\
+    ${javac.test.classpath}
+javadoc.additionalparam=-header "NPS Networked Graphics MV3500 Examples"
+javadoc.author=true
+javadoc.encoding=${source.encoding}
+javadoc.html5=false
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+#javadoc.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-javadoc.jar
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=MV3500 Examples
+jlink.launcher=false
+jlink.launcher.name=Networked_Graphics_MV3500_examples
+main.class=TcpExamples.TcpExample1Telnet
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+run.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.modulepath=\
+    ${javac.modulepath}
+run.test.classpath=\
+    ${javac.test.classpath}:\
+    ${build.test.classes.dir}
+run.test.modulepath=\
+    ${javac.test.modulepath}
+source.encoding=UTF-8
+#source.reference.opendis7-enumerations-classes.jar=../lib/opendis7-enumerations-source.jar
+src.dir=src
+src.src.dir=otherProjects\\DisDemo\\src
+src.src2.dir=otherProjects\\DisShooting\\src
+src.src3.dir=otherProjects\\WebSocketGateway\\src
+#src.src4.dir=otherProjects\\BasicServletDemo\\src
diff --git a/examples/src/UdpExamples/UnicastUdpSender.java b/examples/src/UdpExamples/UnicastUdpSender.java
index e7d4daf32708dfa6815fae497003410e3bb1a468..68cde3d0adc819257118fd6344ef554d2e93e312 100644
--- a/examples/src/UdpExamples/UnicastUdpSender.java
+++ b/examples/src/UdpExamples/UnicastUdpSender.java
@@ -27,13 +27,13 @@ public class UnicastUdpSender
     private static final String            MY_NAME = System.getProperty("user.name"); // guru incantation   8)
 //  public  static final int          SENDING_PORT = 1414; // not needed, can let system choose an open local port
     /** socket value of shared interest */
-    public  static final int              UDP_PORT = UnicastUdpReceiver.UDP_PORT; // 1415; ensure consistent
+    public  static final int              UDP_PORT = 1415;// ensure consistent
     private static final int TOTAL_PACKETS_TO_SEND = 100;
     
     /** socket value of shared interest */
-    public static  final String   DESTINATION_HOST = "localhost"; 
+    //public static  final String   DESTINATION_HOST = "localhost"; 
     // here is what we need for lab comms
-//  public static final String   DESTINATION_HOST = "10.1.105.16"; // localhost 127.0.0.1 or argon 10.1.105.1 or 10.1.105.1 or whatever
+    public static final String   DESTINATION_HOST = "127.0.0.1"; // localhost 127.0.0.1 or argon 10.1.105.1 or 10.1.105.1 or whatever
     
     /**
      * Program invocation, execution starts here
@@ -46,7 +46,7 @@ public class UnicastUdpSender
         DataOutputStream  dos = null;
         int   packetID = 0;     // counter variable to send in packet
         float    countdown = -1.0f; // unreachable value is good sentinel to ensure expected changes occur
-        String message = MY_NAME + " says Hello MV3500"; // no really
+        String message = MY_NAME + " says Hello Professor!"; // no really
         String padding = new String();
         
         try
diff --git a/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/ArrivalProcessOpenDis7Assembly.xml b/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/ArrivalProcessOpenDis7Assembly.xml
index 87787fc2afa70f4122f89029fae5350ab3793b37..597e3466d1cbf16277106c2a88056fdaf381ce4b 100644
--- a/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/ArrivalProcessOpenDis7Assembly.xml
+++ b/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/ArrivalProcessOpenDis7Assembly.xml
@@ -24,5 +24,6 @@
     <PropertyChangeListenerConnection property="N" listener="numArrivalsStat" source="aPOpenDis7" description=""/>
     <PropertyChangeListenerConnection property="C" listener="numEntityCreationsStat" source="aPOpenDis7" description=""/>
     <PropertyChangeListenerConnection property="R" listener="numEntityRemovalsStat" source="aPOpenDis7" description=""/>
+    <Output entity="aPOpenDis7"/>
     <Schedule stopTime="100.0" verbose="false" saveReplicationData="false"/>
 </SimkitAssembly>
diff --git a/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/SimpleServerDis7Assembly.xml b/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/SimpleServerDis7Assembly.xml
old mode 100755
new mode 100644
index 11d6ab585dab9323bd35b9aad841dd336e49d286..5aac321ee51ee75c2eb1c78ec7618b2f475737d6
--- a/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/SimpleServerDis7Assembly.xml
+++ b/examples/src/ViskitOpenDis7Examples/Assemblies/dis7/SimpleServerDis7Assembly.xml
@@ -36,5 +36,7 @@
     <PropertyChangeListenerConnection property="numberAvailableServers" listener="numAvailServersStat" source="simpleServer" description=""/>
     <PropertyChangeListenerConnection property="numberArrivals" listener="numArrivalsStat" source="arrivalProcessOpenDis7" description=""/>
     <PropertyChangeListenerConnection property="numberServed" listener="numServedStat" source="simpleServer" description=""/>
+    <Output entity="arrivalProcessOpenDis7"/>
+    <Output entity="simpleServer"/>
     <Schedule stopTime="100000.0" verbose="false" saveReplicationData="false"/>
 </SimkitAssembly>
diff --git a/examples/src/ViskitOpenDis7Examples/lib/Networked_Graphics_MV3500_examples.jar b/examples/src/ViskitOpenDis7Examples/lib/Networked_Graphics_MV3500_examples.jar
index 35ebf4ea7009c85ef6c28842ac4d75c08979a120..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
Binary files a/examples/src/ViskitOpenDis7Examples/lib/Networked_Graphics_MV3500_examples.jar and b/examples/src/ViskitOpenDis7Examples/lib/Networked_Graphics_MV3500_examples.jar differ
diff --git a/examples/src/ViskitOpenDis7Examples/viskitProject.xml b/examples/src/ViskitOpenDis7Examples/viskitProject.xml
index 1d20dbac80274c45b7e83d70c0852ed95ea99f27..f6152d4509d127907441b7f919d5faf2fdaf9e91 100644
--- a/examples/src/ViskitOpenDis7Examples/viskitProject.xml
+++ b/examples/src/ViskitOpenDis7Examples/viskitProject.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<ViskitProject name="ViskitOpenDis7Examples">
+<ViskitProject>
   <AnalystReports name="AnalystReports" />
   <AssembliesDirectory name="Assemblies" />
   <EventGraphsDirectory name="EventGraphs" />
@@ -9,8 +9,8 @@
   </BuildDirectory>
   <DistDirectory name="dist" />
   <LibDirectory name="lib" />
-  <Cached></Cached>
+  <Cached />
   <extraClassPaths>
+    <path value="C:/Users/RJRRLocal/MOVES/Q5/MV3500/src/NetworkedGraphicsMV3500/examples/src/ViskitOpenDis7Examples/lib/Networked_Graphics_MV3500_examples.jar" />
   </extraClassPaths>
-</ViskitProject>
-
+</ViskitProject>
\ No newline at end of file
diff --git a/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/ArrivalProcess.xml b/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/ArrivalProcess.xml
old mode 100755
new mode 100644
diff --git a/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/SimpleMachineFailure.xml b/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/SimpleMachineFailure.xml
index ad872c9652eb9cd6581ba5a65b3d4d4db021ad2b..ab5bd43c6ad40ce491eb30c65e13c8af836d4316 100644
--- a/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/SimpleMachineFailure.xml
+++ b/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/SimpleMachineFailure.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<SimEntity name="SimpleMachineFailure" version="0.1" package="examples" xsi:noNamespaceSchemaLocation="http://diana.nps.edu/Simkit/simkit.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<SimEntity name="SimpleMachineFailure" version="0.1" package="examples" extend="SimEntityBase" xsi:noNamespaceSchemaLocation="http://diana.nps.edu/Simkit/simkit.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <Parameter type="int" name="totalNumberMachines"/>
     <Parameter type="int" name="totalNumberRepairPeople"/>
     <Parameter type="simkit.random.RandomVariate" name="timeToFailure"/>
diff --git a/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/TransferLineComponent.xml b/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/TransferLineComponent.xml
index 63bce207d2bcb60e15209ffd48e2487df9d6cafc..c9e8ddec9b611c19ffb4524e41bda0e529db23c9 100644
--- a/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/TransferLineComponent.xml
+++ b/viskit/MyViskitProjects/DefaultProject/EventGraphs/examples/TransferLineComponent.xml
@@ -1,91 +1,68 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<SimEntity extend="SimEntityBase" name="TransferLineComponent" package="examples" version="0.0.2" xsi:noNamespaceSchemaLocation="http://diana.nps.edu/Simkit/simkit.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<SimEntity name="TransferLineComponent" package="examples" version="0.0.2" extend="SimEntityBase" xsi:noNamespaceSchemaLocation="http://diana.nps.edu/Simkit/simkit.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <Comment>TODO: Fix me, I'm currently broken!! tdn 8/29/24</Comment>
     <Parameter name="totalNumberServers" type="int[]"/>
     <Parameter name="serviceTime" type="simkit.random.RandomVariate[]"/>
     <StateVariable name="numberAvailableServers" type="int[totalNumberServers.length]"/>
     <StateVariable name="numberInQueue" type="int[totalNumberServers.length]"/>
     <Event name="Run">
         <LocalVariable name="j" type="int" value="0">
-            <Comment/>
+            <Comment></Comment>
         </LocalVariable>
-        <LocalVariable name="_idxvar_0" type="int" value="0">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <LocalVariable name="_idxvar_1" type="int" value="0">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <StateTransition index="_idxvar_0" state="numberAvailableServers">
-            <Assignment value="totalNumberServers[_idxvar_0]"/>
+        <StateTransition state="numberAvailableServers" index="j>
+            <Assignment value="totalNumberServers[j]"/>
         </StateTransition>
-        <StateTransition index="_idxvar_1" state="numberInQueue">
+        <StateTransition state="numberInQueue" index="_idxvar_1">
             <Assignment value="0"/>
         </StateTransition>
-        <Schedule delay="0.0" event="InitializeWorkcenter">
+        <Schedule delay="0.0" event="InitializeWorkcenter" priority="DEFAULT">
             <EdgeParameter value="0"/>
         </Schedule>
-        <Coordinate x="0" y="0"/>
+        <Coordinate x="0.0" y="0.0"/>
     </Event>
     <Event name="InitializeWorkcenter">
         <Argument name="i" type="int"/>
-        <LocalVariable name="_idxvar_26" type="int" value="i">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <LocalVariable name="_idxvar_27" type="int" value="i">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <StateTransition index="_idxvar_26" state="numberInQueue">
+        <StateTransition state="numberInQueue" index="_idxvar_26">
             <Assignment value="0"/>
         </StateTransition>
-        <StateTransition index="_idxvar_27" state="numberAvailableServers">
+        <StateTransition state="numberAvailableServers" index="_idxvar_27">
             <Assignment value="totalNumberServers[i]"/>
         </StateTransition>
-        <Schedule condition="i &lt; totalNumberServers.length - 1" event="InitializeWorkcenter">
+        <Schedule event="InitializeWorkcenter" condition="i &lt; totalNumberServers.length - 1" priority="DEFAULT">
             <EdgeParameter value="i+1"/>
         </Schedule>
-        <Coordinate x="120" y="0"/>
+        <Coordinate x="120.0" y="0.0"/>
     </Event>
     <Event name="Arrival">
         <Argument name="i" type="int"/>
-        <LocalVariable name="_idxvar_47" type="int" value="i">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <StateTransition index="_idxvar_47" state="numberInQueue">
+        <StateTransition state="numberInQueue" index="_idxvar_47">
             <Assignment value="numberInQueue[i] + 1"/>
         </StateTransition>
-        <Schedule condition="getNumberAvailableServers(i) &gt; 0" event="StartService">
+        <Schedule event="StartService" condition="getNumberAvailableServers(i) &gt; 0" priority="DEFAULT">
             <EdgeParameter value="i"/>
         </Schedule>
-        <Coordinate x="0" y="180"/>
+        <Coordinate x="0.0" y="180.0"/>
     </Event>
     <Event name="StartService">
         <Argument name="i" type="int"/>
-        <LocalVariable name="_idxvar_48" type="int" value="i">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <LocalVariable name="_idxvar_49" type="int" value="i">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <StateTransition index="_idxvar_48" state="numberInQueue">
+        <StateTransition state="numberInQueue" index="_idxvar_48">
             <Assignment value="numberInQueue[i] + 1"/>
         </StateTransition>
-        <StateTransition index="_idxvar_49" state="numberAvailableServers">
+        <StateTransition state="numberAvailableServers" index="_idxvar_49">
             <Assignment value="numberAvailableServers[i] - 1"/>
         </StateTransition>
-        <Schedule delay="serviceTime[i].generate()" event="EndService">
+        <Schedule delay="serviceTime[i].generate()" event="EndService" priority="DEFAULT">
             <EdgeParameter value="i"/>
         </Schedule>
-        <Coordinate x="160" y="100"/>
+        <Coordinate x="160.0" y="100.0"/>
     </Event>
     <Event name="EndService">
         <Argument name="i" type="int"/>
-        <LocalVariable name="_idxvar_50" type="int" value="i">
-            <Comment>used internally</Comment>
-        </LocalVariable>
-        <StateTransition index="_idxvar_50" state="numberAvailableServers">
+        <StateTransition state="numberAvailableServers" index="_idxvar_50">
             <Assignment value="numberAvailableServers[i]+1"/>
         </StateTransition>
-        <Schedule condition="getNumberInQueue(i) &gt; 0" event="StartService"/>
-        <Schedule condition="i &lt; totalNumberServers.length - 1" event="Arrival"/>
-        <Coordinate x="330" y="200"/>
+        <Schedule event="StartService" condition="getNumberInQueue(i) &gt; 0" priority="DEFAULT"/>
+        <Schedule event="Arrival" condition="i &lt; totalNumberServers.length - 1" priority="DEFAULT"/>
+        <Coordinate x="330.0" y="200.0"/>
     </Event>
-</SimEntity>
\ No newline at end of file
+</SimEntity>
diff --git a/viskit/MyViskitProjects/DefaultProject/viskitProject.xml b/viskit/MyViskitProjects/DefaultProject/viskitProject.xml
index 1a7a1fb34bf2bcba5b570b67f0793a7e0b6c9c27..2c559b5ae10acad72b382aa05802a5cb304d07ed 100644
--- a/viskit/MyViskitProjects/DefaultProject/viskitProject.xml
+++ b/viskit/MyViskitProjects/DefaultProject/viskitProject.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<ViskitProject name="DefaultProject">
+<ViskitProject>
   <AnalystReports name="AnalystReports" />
   <AssembliesDirectory name="Assemblies" />
   <EventGraphsDirectory name="EventGraphs" />
@@ -11,5 +11,7 @@
   <LibDirectory name="lib" />
   <Cached>
   </Cached>
+  <extraClassPaths>
+  </extraClassPaths>
 </ViskitProject>
 
diff --git a/viskit/configuration/viskitProject.xml b/viskit/configuration/viskitProject.xml
index 91c9a9e3e6ee9ec708e59c9cf3bedc2f97236e45..16ae0dd6c2bf553fd03c5c990e84d683c11d94af 100644
--- a/viskit/configuration/viskitProject.xml
+++ b/viskit/configuration/viskitProject.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<ViskitProject name="DefaultProject">
+<ViskitProject>
   <AnalystReports name="AnalystReports" />
   <AssembliesDirectory name="Assemblies" />
   <EventGraphsDirectory name="EventGraphs" />
diff --git a/viskit/lib/viskit.jar b/viskit/lib/viskit.jar
index 9a7c4a7574779f8e7e76765f7ace939dab637828..3482568ad3c2beeabe3015e9c4c479154b6317d3 100644
Binary files a/viskit/lib/viskit.jar and b/viskit/lib/viskit.jar differ