diff --git a/MV3500DistributedSimulationSyllabus2024JulySeptember.docx b/MV3500DistributedSimulationSyllabus2024JulySeptember.docx index 371f296a678decc875ed2b11f624c42d33bc4654..43164767fdbf08483f6f8b715d1c5ec6ded9b867 100644 Binary files a/MV3500DistributedSimulationSyllabus2024JulySeptember.docx and b/MV3500DistributedSimulationSyllabus2024JulySeptember.docx differ diff --git a/MV3500DistributedSimulationSyllabus2024JulySeptember.pdf b/MV3500DistributedSimulationSyllabus2024JulySeptember.pdf index 22f2b3bdf32037be46a53374023cb8921795c9e8..96622654d9e5ad6b13328ccca758f1e35c8b3e0d 100644 Binary files a/MV3500DistributedSimulationSyllabus2024JulySeptember.pdf and b/MV3500DistributedSimulationSyllabus2024JulySeptember.pdf differ diff --git a/assignments/README.md b/assignments/README.md index dda6f4963dc2297fe819068511b492ad995f8d5d..a113f3b7925ff46a3e5525fd8c608baf621fec84 100644 --- a/assignments/README.md +++ b/assignments/README.md @@ -1,17 +1,17 @@ -# Networked Graphics MV3500 Course Assignments using Netbeans +# Networked Graphics MV3500 Course Assignments using NetBeans ## Initialization and Refresh -To submit homework via Netbeans to the gitlab server you will first need to -clone a copy of the course repository at +To submit homework via NetBeans to the gitlab server you will first need to +use Git to clone a copy of the course repository at * https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500 -Use Netbeans to upload/update your homework assignments as follows: +Use NetBeans to upload/update your homework assignments as follows: 1. *context menu:* **Git > Remote > Pull from Upstream** to first always ensure you update your repository 1. *Making sure:* Did you perform step one and pull git to refresh your local version?! -1. Select file of interest in Netbeans tab for Files +1. Select file of interest in NetBeans tab for Files 1. *context menu:* **Refactor/Rename** and take spaces out of file name (gets wacky on various operating systems, email etc.) 1. Ensure Java classes and source files start with your last name 1. *context menu:* **Run file**(s) to test @@ -21,7 +21,7 @@ Use Netbeans to upload/update your homework assignments as follows: ## Adding and Editing Your Files -All MV3500 cohorts have source code collected under a common Netbeans project. +All MV3500 cohorts have source code collected under a common NetBeans project. 1. Find your current cohort src subdirectories, for example * [assignments / src / MV3500Cohort2024JulySeptember](src/MV3500Cohort2024JulySeptember) (we are here!) @@ -54,7 +54,7 @@ After committing and pushing, you can now verify that your files are been shared ## References -* [Netbeans](http://www.netbeans.org) and [Using Git Support](https://netbeans.apache.org/kb/docs/ide/git.html) with [tutorial video, version 8.2](https://www.youtube.com/watch?v=rs3QSq5hNf4) +* [NetBeans](http://www.netbeans.org) and [Using Git Support](https://netbeans.apache.org/kb/docs/ide/git.html) with [tutorial video, version 8.2](https://www.youtube.com/watch?v=rs3QSq5hNf4) * [GitLab Flavored Markdown (GFM)](https://docs.gitlab.com/ee/user/markdown.html) and [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Here-Cheatsheet) * UML [Sequence diagram](https://en.wikipedia.org/wiki/Sequence_diagram) on Wikipedia * [Wireshark](https://www.wireshark.org) network protocol analyzer diff --git a/assignments/build.xml b/assignments/build.xml index 0d34721a796d0f04a276f75c8b606601bd7ff1e1..a7d93fc88d00806f1ea2f28c79c6ce3102808f09 100644 --- a/assignments/build.xml +++ b/assignments/build.xml @@ -144,7 +144,7 @@ POSSIBILITY OF SUCH DAMAGE. <property name="javadoc.nonavbar" value="false"/> <property name="javadoc.notree" value="false"/> <property name="javadoc.private" value="false"/> - <property name="javadoc.source" value="${java.source}"/> +<!--<property name="javadoc.source" value="${java.source}"/>--> <property name="javadoc.splitindex" value="true"/> <property name="javadoc.breakiterator" value="true"/> <property name="javadoc.use" value="true"/><!-- Create class and package usage pages --> @@ -171,13 +171,13 @@ POSSIBILITY OF SUCH DAMAGE. notree="${javadoc.notree}" Overview="src/overview.html" Private="${javadoc.private}" - source="${java.source}" Splitindex="${javadoc.splitindex}" Use="${javadoc.use}" useexternalfile="yes" verbose="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> + <!-- source="${java.source}" --> <classpath> <pathelement location="../lib/opendis7-full.jar"/> <pathelement location="../lib/open-dis_4.16.jar"/> diff --git a/assignments/nbproject/project.properties b/assignments/nbproject/project.properties index 9003d11a34aa62d496dd78e30b32d7bea504d908..8423aa450053a37e372c3f6f2c9c2f5dd69ed33d 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=22 -javac.target=22 -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 +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 diff --git a/assignments/nbproject/project.xml b/assignments/nbproject/project.xml index d7234beae9aa3ea90d012607e6919204e1a4942a..ec9c9401e07d97eb2d28c832cc9985585aeb9f06 100644 --- a/assignments/nbproject/project.xml +++ b/assignments/nbproject/project.xml @@ -1,44 +1,43 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://www.netbeans.org/ns/project/1"> - <type>org.netbeans.modules.java.j2seproject</type> - <configuration> - <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> - <name>Networked Graphics MV3500 assignments</name> - <explicit-platform explicit-source-supported="true"/> - <source-roots> - <root id="src.dir"/> - </source-roots> - <test-roots> - <root id="test.src.dir"/> - </test-roots> - </data> - <spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1"> - <word>accessor</word> - <word>autogeneration</word> - <word>classpath</word> - <word>Cygwin</word> - <word>deliverables</word> - <word>docx</word> - <word>https</word> - <word>interarrival</word> - <word>javadoc</word> - <word>localhost</word> - <word>multicast</word> - <word>Netbeans</word> - <word>netcat</word> - <word>NPS</word> - <word>pdu</word> - <word>README</word> - <word>simkit</word> - <word>simulationists</word> - <word>SISO</word> - <word>subpackage</word> - <word>teardown</word> - <word>txt</word> - <word>UML</word> - <word>unicast</word> - <word>wikipedia</word> - <word>Wireshark</word> - </spellchecker-wordlist> - </configuration> -</project> +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>Networked Graphics MV3500 assignments</name> + <source-roots> + <root id="src.dir"/> + </source-roots> + <test-roots> + <root id="test.src.dir"/> + </test-roots> + </data> + <spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1"> + <word>accessor</word> + <word>autogeneration</word> + <word>classpath</word> + <word>Cygwin</word> + <word>deliverables</word> + <word>docx</word> + <word>https</word> + <word>interarrival</word> + <word>javadoc</word> + <word>localhost</word> + <word>multicast</word> + <word>Netbeans</word> + <word>netcat</word> + <word>NPS</word> + <word>pdu</word> + <word>README</word> + <word>simkit</word> + <word>simulationists</word> + <word>SISO</word> + <word>subpackage</word> + <word>teardown</word> + <word>txt</word> + <word>UML</word> + <word>unicast</word> + <word>wikipedia</word> + <word>Wireshark</word> + </spellchecker-wordlist> + </configuration> +</project> diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework1/Schnitzler/SchnitzlerUnicastNetworking.java b/assignments/src/MV3500Cohort2024JulySeptember/homework1/Schnitzler/SchnitzlerUnicastNetworking.java index 7bdf6b26638e408a8ddb55443d56a53d789cfbbc..52405cbcb2c7cf405be4c8e53f4fde13de6cf6db 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework1/Schnitzler/SchnitzlerUnicastNetworking.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework1/Schnitzler/SchnitzlerUnicastNetworking.java @@ -21,6 +21,7 @@ public class SchnitzlerUnicastNetworking { } /** + * Program invocation, execution starts here * @param args the command line arguments */ public static void main(String[] args) { diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Client.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Client.java index 26dbd0604ae39d1cd4760b5652b1a3e81ad5dca2..f712e71dd50031f6c3acfc08f61b38b40acbb9a6 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Client.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Client.java @@ -4,13 +4,12 @@ import java.io.*; import java.net.*; /** - * This client program establishes a socket connection to the {@link TcpExamples.TcpExample4DispatchServer}, + * This client program establishes a socket connection to the , * then checks how long it takes to read the single line it expects as a server response. * The modification I have added is it checks for a password from the server. And it matches it says success and disconnects - * No fancy footwork here, it is pretty simple and similar to {@link TcpExamples.TcpExample3Client}. + * No fancy footwork here, it is pretty simple and similar to TcpExamples.TcpExample3Client}. + * borrowed code from class * - * @see TcpExample4DispatchServer - * @see TcpExample4HandlerThread * * @see <a href="../../../src/TcpExamples/TcpExample4TerminalLog.txt" target="blank">TcpExample4TerminalLog.txt</a> * @see <a href="../../../src/TcpExamples/TcpExample4SequenceDiagram.png" target="blank">TcpExample4SequenceDiagram.png</a> @@ -19,7 +18,7 @@ import java.net.*; * @author Don McGregor * @author Don Brutzman * @author MV3500 class - * @MarkMM + * @author MarkMM */ public class Matiski2Client { diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2HandlerThread.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2HandlerThread.java index dd70c8524af605297e581e18fd8ba936518c8129..beb348bd1d096450c0779136f34b0243eb18de2f 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2HandlerThread.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2HandlerThread.java @@ -5,18 +5,16 @@ import java.net.*; /** * <p> - * This utility class supports the {@link TcpExamples.TcpExample4DispatchServer} program, + * This utility class supports the TcpExamples.TcpExample4DispatchServer 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 * if the server can't respond to a connection for several seconds. * </p> * <p> - * Warning: do not run this class! It is created and used automatically by {@link TcpExamples.TcpExample4DispatchServer} at run time. + * Warning: do not run this class! It is created and used automatically by TcpExamples.TcpExample4DispatchServer} at run time. * </p> - * - * @see TcpExample4Client - * @see TcpExample4DispatchServer + * see examples * * @see <a href="../../../src/TcpExamples/TcpExample4TerminalLog.txt" target="blank">TcpExample4TerminalLog.txt</a> * @see <a href="../../../src/TcpExamples/TcpExample4SequenceDiagram.png" target="blank">TcpExample4SequenceDiagram.png</a> @@ -25,6 +23,7 @@ import java.net.*; * @author Don McGregor * @author Don Brutzman * @author MV3500 class + * borrowed heavily from above authors */ public class Matiski2HandlerThread extends Thread { diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Server.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Server.java index 7676d44b9b53f3e8f41ddef3fa824006d9b435e2..2d4360b3120d398c581fc7089be79bf800c4a477 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Server.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Matiski/Matiski2Server.java @@ -9,8 +9,6 @@ import java.net.*; * This advanced technique is often used in high=performance high=capacity server programs. * * - * @see TcpExample4Client - * @see Matiski2HandlerThread * * @see <a href="../../../src/TcpExamples/TcpExample4TerminalLog.txt" target="blank">TcpExample4TerminalLog.txt</a> * @see <a href="../../../src/TcpExamples/TcpExample4SequenceDiagram.png" target="blank">TcpExample4SequenceDiagram.png</a> @@ -19,6 +17,7 @@ import java.net.*; * @author Don McGregor * @author Don Brutzman * @author MV3500 class + * borrowed heavily from above authors */ public class Matiski2Server { diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java index 382ceeb106179abdf2c4f2499db2cf75eb36712c..5a98f34dc5bb592ce709d0c6f2bd9e3f6e8c75a1 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Romero/RomeroClientHW2.java @@ -7,9 +7,8 @@ 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. - * No fancy footwork here, it is pretty simple and similar to {@link TcpExample3Client}. * * @author Don McGregor * @author Don Brutzman 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/homework2/Schnitzler/SchnitzlerClient.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Schnitzler/SchnitzlerClient.java index d1d3b1c85d67098d7be44e3cf1b99a95bcdd751e..7e97435c1d600118d3afa6259fb34ee10b9290b1 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Schnitzler/SchnitzlerClient.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Schnitzler/SchnitzlerClient.java @@ -13,11 +13,22 @@ import java.util.Scanner; * @author simonschnitzler */ public class SchnitzlerClient { + + /** Default constructor */ + public SchnitzlerClient(){ + // default constructor + } + + /** IPv6 String constant for localhost address, similarly IPv4 127.0.0.1 + * @see <a href="https://en.wikipedia.org/wiki/localhost" target="_blank">https://en.wikipedia.org/wiki/localhost</a> + * @see <a href="https://en.wikipedia.org/wiki/IPv6_address" target="_blank">https://en.wikipedia.org/wiki/IPv6_address</a> + */ public final static String LOCALHOST = "0:0:0:0:0:0:0:1"; //Local host /** + * Program invocation, execution starts here * @param args the command line arguments - * @throws java.lang.Exception + * @throws java.lang.Exception if connection failed */ public static void main(String[] args) throws Exception { Socket socket = new Socket(LOCALHOST, 2317); diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Schnitzler/SchnitzlerServer.java b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Schnitzler/SchnitzlerServer.java index 47cc363f2d1b7e8e2cea4178dc612913d39ddedb..9b1e5afc7b1de845e0c71b8b9accec3eea4faed4 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework2/Schnitzler/SchnitzlerServer.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework2/Schnitzler/SchnitzlerServer.java @@ -16,10 +16,18 @@ import java.util.Set; * @author simonschnitzler */ public class SchnitzlerServer { + + /** Default constructor */ + public SchnitzlerServer(){ + // default constructor + } + // the set clientWriters contains form all sockets the active PrintStream private static Set<PrintWriter> clientWriters = new HashSet<>(); /** + * Program invocation, execution starts here + * * @param args the command line arguments */ public static void main(String[] args) { diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/ExampleSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/ExampleSimulationProgram.java new file mode 100644 index 0000000000000000000000000000000000000000..6372a714e6a04a55eb71c38868c54acfa5ec9a21 --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/ExampleSimulationProgram.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 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 */ + 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 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); + 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(ExampleSimulationProgram.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 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 + */ + 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 + } +} diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a1f900c417af2114b2bd482ba58370ab58a1c751 --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/README.md @@ -0,0 +1,18 @@ +# Rene Romero Homework 3 + +*** + +## Description + +Modification to ... + +<!-- + +Phrases taken from: <b>https://www.divein.com/everyday/monday-motivation-quotes/</b> + +<a href="images/MOTD.png"><img src="images/MOTD.png" width="700" align="center"/></a> + +Message of the day reference: <b>https://en.wikipedia.org/wiki/Message_of_the_day </b> + +--> + diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/package-info.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..b73149c24729e236437c4963fa8533ceecc37b09 --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Romero/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.Romero; diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgram.java new file mode 100644 index 0000000000000000000000000000000000000000..a5e42691d8d460162361a3b370617b601b204425 --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgram.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 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.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 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 */ + 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 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); + 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(ExampleSimulationProgram.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 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 + */ + 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 + } +} diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9fa0fbe84db4a7a4ae58a198b00d200518cfef2c --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/README.md @@ -0,0 +1 @@ +For Homework 3, I have done nothing yet \ No newline at end of file diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/package-info.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..f910736254e88eba3a501b33003eddbd86835479 --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/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.Smith; diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/ExampleSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/ExampleSimulationProgram.java new file mode 100644 index 0000000000000000000000000000000000000000..66628a8cc36a6e5c40ebfa947c28fbb835f65d27 --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/ExampleSimulationProgram.java @@ -0,0 +1,280 @@ +/** + * Copyright (c) 2008-2024, 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 + * + * This main class is my submission for HW 3. + * + * @author ethanjwilliams + */ +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.*; +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. + * + * Homework 3 networking choices: + * This simulation uses UDP multicast for efficient distribution of PDUs to + * 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. + * + * @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 ExampleSimulationProgram +{ + private String descriptor = this.getClass().getSimpleName(); + protected DisChannel disChannel; + protected PduFactory pduFactory; + + private double simulationTimeStepDuration = 1.0; + double simulationTimeInitial = 0.0; + double simulationTimeSeconds = simulationTimeInitial; + int MAX_LOOP_COUNT = 4; + + String narrativeMessage1 = new String(); + String narrativeMessage2 = new String(); + String narrativeMessage3 = new String(); + + protected EntityID entityID_1 = new EntityID(); + protected EntityID entityID_2 = new EntityID(); + protected EntityStatePdu entityStatePdu_1; + protected EntityStatePdu entityStatePdu_2; + protected FirePdu firePdu_1a; + protected FirePdu firePdu_1b; + protected MunitionDescriptor munitionDescriptor1; + + public ExampleSimulationProgram() + { + initialize(); + } + + public ExampleSimulationProgram(String newDescriptor) + { + descriptor = newDescriptor; + initialize(); + } + + public ExampleSimulationProgram(String address, int port) + { + disChannel.setNetworkAddress(address); + disChannel.setNetworkPort(port); + disChannel.setVerboseComments(true); + disChannel.setVerboseDisNetworkInterface(true); + disChannel.setVerbosePduRecorder(true); + initialize(); + } + + private void initialize() + { + initializeDisChannel(); + initializeSimulationEntities(); + + disChannel.join(); + + String timeStepMessage = "Simulation timestep duration " + getSimulationTimeStepDuration() + " seconds"; + disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_SIMULATION_TIMESTEP, timeStepMessage); + } + + 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()); + disChannel.setUpNetworkInterface(); + disChannel.printlnTRACE ("just checking: disChannel.getNetworkAddress()=" + disChannel.getNetworkAddress() + + ", getNetworkPort()=" + disChannel.getNetworkPort()); + disChannel.getDisNetworkInterface().setVerbose(true); + disChannel.printlnTRACE ("just checking: hasVerboseSending()=" + disChannel.getDisNetworkInterface().hasVerboseSending() + + ", hasVerboseReceipt()=" + disChannel.getDisNetworkInterface().hasVerboseReceipt()); + disChannel.getPduRecorder().setVerbose(true); + } + + 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(); + + entityID_1.setSiteID((int)(Math.random() * 100)) + .setApplicationID((int)(Math.random() * 100)) + .setEntityID((int)(Math.random() * 100)); + disChannel.addEntity(entityID_1); + + 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("Ethan's Poseidon #1"); + + entityStatePdu_2.setEntityID(entityID_2); + entityStatePdu_2.setForceId(ForceID.OPPOSING); + entityStatePdu_2.setEntityType(new _002Triton()); + entityStatePdu_2.setMarking("Ethan's Triton #2"); + + munitionDescriptor1.setQuantity(1); + firePdu_1a.setDescriptor(munitionDescriptor1).setRange(1000.0f); + + } + + @SuppressWarnings("SleepWhileInLoop") + public void runSimulationLoops () + { + try + { + final int SIMULATION_MAX_LOOP_COUNT = 10; + int simulationLoopCount = 0; + boolean simulationComplete = false; + + String timeMessage = "Simulation time " + simulationTimeSeconds + " at LocalDateTime " + LocalDateTime.now(); + disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_TIME, timeMessage); + + while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT) + { + simulationLoopCount++; + + entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + (Math.random() * 2)); + + System.out.println ("... My simulation just did something..."); + System.out.flush(); + + narrativeMessage1 = "Ethan's Custom Simulation Program"; + narrativeMessage2 = "Loop " + simulationLoopCount + " - MV3500 Custom Version"; + narrativeMessage3 = "Simulation developed by Ethan Williams"; + + if (simulationLoopCount > MAX_LOOP_COUNT) + { + simulationComplete = true; + } + + Thread.sleep((long)(getSimulationTimeStepDuration() * 1000)); + System.out.println ("... [Pausing for " + getSimulationTimeStepDuration() + " seconds]"); + + sendAllPdusForLoopTimestep(simulationTimeSeconds, + entityStatePdu_1, + firePdu_1a, + DisChannel.COMMENTPDU_APPLICATION_STATUS, + narrativeMessage1, narrativeMessage2); + disChannel.sendSinglePdu(simulationTimeSeconds, entityStatePdu_2); + + System.out.println ("... [PDUs of interest successfully sent for this loop]"); + System.out.flush(); + + if (simulationComplete || (simulationLoopCount > 10000)) + { + System.out.println ("... [loop termination condition met, simulationComplete=" + simulationComplete + "]"); + System.out.flush(); + break; + } + simulationTimeSeconds += getSimulationTimeStepDuration(); + } + + narrativeMessage2 = "runSimulation() completed successfully"; + disChannel.sendCommentPdu(DisChannel.COMMENTPDU_NARRATIVE, narrativeMessage1, narrativeMessage2, narrativeMessage3); + System.out.println ("... [final=completion CommentPdu successfully sent for simulation]"); + + disChannel.leave(); + } + catch (InterruptedException iex) + { + Logger.getLogger(ExampleSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex); + } + } + + public void sendAllPdusForLoopTimestep(double simTimeSeconds, + EntityStatePdu entityStatePdu, + FirePdu firePdu, + VariableRecordType commentType, + String... comments) + { + if (entityStatePdu != null) + disChannel.sendSinglePdu(simTimeSeconds, entityStatePdu); + + if (firePdu != null) + disChannel.sendSinglePdu(simTimeSeconds, firePdu); + + disChannel.sendCommentPdu(simTimeSeconds, commentType, comments); + } + + protected void handleArguments (String[] args) + { + 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); + } + } + + public String getDescriptor() { + return descriptor; + } + + public void setDescriptor(String newDescriptor) { + if (newDescriptor == null) + newDescriptor = ""; + this.descriptor = newDescriptor; + } + + public double getSimulationTimeStepDuration() { + return simulationTimeStepDuration; + } + + public void setSimulationTimeStepDuration(double timeStepDurationSeconds) { + this.simulationTimeStepDuration = timeStepDurationSeconds; + } + + protected static ExampleSimulationProgram thisProgram; + + public static void main(String[] args) + { + thisProgram = new ExampleSimulationProgram("test constructor"); + + thisProgram.disChannel.printlnTRACE("main() started..."); + + thisProgram.handleArguments(args); + + thisProgram.runSimulationLoops(); + + thisProgram.disChannel.tearDownNetworkInterface(); + + thisProgram.disChannel.printlnTRACE("complete."); + + System.exit(0); + } +} diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e5281d6ca4f5d7927c9f833c08c89247986ddc19 --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/README.md @@ -0,0 +1,3 @@ +For Homework 3, I customized the Example Simulation Program 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/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/package-info.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..77f86efe6241f09656c2c45caf35f924e8bf318b --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Williams/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.Williams; diff --git a/assignments/src/overview.html b/assignments/src/overview.html index f69d25fd87fabfebc9a7d4394296c564d6dd31ff..76a76b3ecc73a81aad4087b33e0c2c98aea832f9 100644 --- a/assignments/src/overview.html +++ b/assignments/src/overview.html @@ -5,7 +5,7 @@ <h1> Course Resources </h1> <p> <!-- Note that javadoc throws an incorrect error regarding title attribute, but resulting HTML works as expected --> - <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/assignments/README.md" target="_blank" title="Open-Dis Surfer Dude, Thanks Don McGregor!"><img src="OpenDisSurferDude.png" alt="Open-Dis Surfer Dude, Thanks Don McGregor!" style="float:right"/></a> + <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/assignments/README.md" target="_blank"><img src="OpenDisSurferDude.png" alt="Open-Dis Surfer Dude, Thanks Don McGregor!" style="float:right"/></a> <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/assignments" target="_blank">Assignments</a>, <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/examples" target="_blank">examples</a>, and <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/presentations" target="_blank">presentations</a> diff --git a/build.xml b/build.xml index 1703724144ea4a527829ab4c55549b49752cb1af..3e8559d124c43ae4053da712ce3882372836c8bd 100644 --- a/build.xml +++ b/build.xml @@ -1,309 +1,332 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - Copyright (c) 1995-2023 held by the author(s). All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the names of the Naval Postgraduate School (NPS) - Modeling Virtual Environments and Simulation (MOVES) Institute - (https://www.nps.edu and https://www.MovesInstitute.org) - nor the names of its contributors may be used to endorse or - promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ---> - -<!-- - Document : build.xml - Created on : 1 November 2017 - Author : Don Brutzman and Don McGregor - Description: Ant build.xml file for Networked Graphics MV3500 ---> -<project name="MV3500 Networked Graphics" default="all" basedir="."> - <description>Build targets for NPS Networked Graphics MV3500</description> - - <!-- TODO add targets for project maintenance, testing and deployment - - <property name="specificationsDirectory" location="specifications"/> - <import file="specifications/build.xml"/> --> - <property file="build.properties"/> - - <target name="versions" description="show tool versions and environment values"> - <echo>ant -version</echo> - <exec executable="ant" dir="." vmlauncher="false"> - <arg value="-version"/> - </exec> - <echo>java -version</echo> - <exec executable="java" dir="." vmlauncher="false"> - <arg value="-version"/> - </exec> - <echo></echo> - <!-- Ant environment variables https://ant.apache.org/manual/Tasks/property.html --> - <echo> ANT_HOME=${env.ANT_HOME}</echo> - <echo> JAVA_HOME=${env.JAVA_HOME}</echo> - <echo>CLASSPATH=${env.CLASSPATH}</echo> - <!--<echo>USER =${env.USER}</echo> --> - <!-- https://stackoverflow.com/questions/949678/ant-is-using-wrong-java-version --> - <!--echo>javac source/target $java.source=${java.source}</ --> - <echo>Java/JVM version $ant.java.version=${ant.java.version}</echo> - <echo>Java/JVM detail version $java.version=${java.version}</echo> - <echo>Ant version $ant.version=${ant.version}</echo> - <echo>Configuration settings: https://savage.nps.edu/Savage/developers.html</echo> - <!-- TODO Netbeans version --> - <!-- TODO Netbeans project version --> - <!-- DEBUG: to show all environment and local properties, add - <echoproperties/> --> - <echo message="==========================================="/> - </target> - - <target name="all" depends="versions"> - <ant dir="examples" target="clean"/> - <ant dir="examples" target="jar"/> - <ant dir="assignments" target="clean"/> - <ant dir="assignments" target="jar"/> - <antcall target="javadoc.all"/> - </target> - - <target name="clean.all.pduLogs" description="clean autogenerated PDU capture logs"> - <ant dir="assignments" target="clean.all.pduLogs"/> - <ant dir="examples" target="clean.all.pduLogs"/> - </target> - - <target name="javadoc.all"> - <ant dir="examples" target="view.opendis7.javadoc"/> - <ant dir="assignments" target="javadoc.custom"/> - <ant dir="examples" target="javadoc.custom"/> - </target> - - <target name="view.gitlab.nps.edu.MV3500" description="view MV3500 gitlab site in web browser (via Netbeans only)"> - <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500"/> - <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500"/> - <!-- TODO implementation-independent approach if possible. other Ant approaches have to be customized for each OS --> - </target> - - <target name="view.gitlab.nps.edu.MV3500.assignments" description="view MV3500 gitlab examples in web browser (via Netbeans only)"> - <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/assignments"/> - <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/assignments"/> - </target> - - <target name="view.gitlab.nps.edu.MV3500.examples" description="view MV3500 gitlab examples in web browser (via Netbeans only)"> - <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/examples"/> - <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/examples"/> - <!-- TODO implementation-independent approach if possible. other Ant approaches have to be customized for each OS --> - </target> - - <target name="view.gitlab.nps.edu.MV3500.issues" description="view online issues in web browser (Netbeans only)"> - <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/issues" /> - <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/issues" /> - <!-- TODO implementation-independent approach if possible, but note that other Ant approaches usually have to be customized for each OS. --> - <echo message="... for issue visibility, be sure to login" /> - </target> - - <target name="view.gitlab.nps.edu.MV3500.specifications.README" description="view MV3500 gitlab examples in web browser (via Netbeans only)"> - <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/specifications/README.md"/> - <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/specifications/README.md"/> - </target> - - <target name="view.open-dis.github.com" description="view github open-dis site in web browser (via Netbeans only)"> - <echo message="https://github.com/open-dis"/> - <nbbrowse url="https://github.com/open-dis"/> - </target> - - <target name="view.open-dis.github.com.opendis7-java" description="view github open-dis open-dis-java current build in web browser (via Netbeans only)"> - <echo message="https://github.com/open-dis/opendis7-java"/> - <nbbrowse url="https://github.com/open-dis/opendis7-java"/> - </target> - - <target name="view.open-dis.github.com.opendis7-source-generator" description="view github open-dis opendis7-source-generator project in web browser (via Netbeans only)"> - <echo message="https://github.com/open-dis"/> - <nbbrowse url="https://github.com/open-dis"/> - </target> - - <target name="update.opendis7.jar.from.local" description="update opendis7-java jar files from locally built project into lib directory"> - - <property name="opendis7-java.relative" value="../../x3d-github/opendis7-java/dist"/> - <echo message="Copy ${opendis7-java.relative}/opendis7-full.jar to project lib/ subdirectory..."/> - <!-- https://ant.apache.org/manual/Tasks/fail.html --> - <fail message="opendis7-full.jar not found"> - <condition> - <not> - <resourcecount count="1"> - <fileset id="fs" dir="${opendis7-java.relative}" includes="opendis7-full.jar"/><!-- comma separated --> - </resourcecount> - </not> - </condition> - </fail> - <!-- clean out prior versions --> - <delete file="lib/opendis7-pdus-classes.jar" verbose="false" failonerror="false"/> - <delete file="lib/opendis7-pdus-javadoc.jar" verbose="false" failonerror="false"/> - <delete file="lib/opendis7-pdus-source.jar" verbose="false" failonerror="false"/> - <delete file="lib/opendis7-enumerations-classes.jar" verbose="false" failonerror="false"/> - <delete file="lib/opendis7-enumerations-javadoc.jar" verbose="false" failonerror="false"/> - <delete file="lib/opendis7-enumerations-source.jar" verbose="false" failonerror="false"/> - - <!-- replace latest version --> - <delete file="lib/opendis7-full.jar" verbose="true" failonerror="false"/> - <copy file="${opendis7-java.relative}/opendis7-full.jar" todir="lib" force="true" verbose="true" failonerror="true"/> - - <!-- - <delete file="assignments/dist/lib/opendis7-full.jar" verbose="true" failonerror="false"/> - <delete file="examples/dist/lib/opendis7-full.jar" verbose="true" failonerror="false"/> - <copy file="${opendis7-java.relative}/opendis7-full.jar" todir="assignments/dist/lib" force="true" verbose="true" failonerror="true"/> - <copy file="${opendis7-java.relative}/opendis7-full.jar" todir="examples/dist/lib" force="true" verbose="true" failonerror="true"/> - - <copy file="${opendis7-java.relative}/opendis7-enumerations-classes.jar" todir="lib" force="true" verbose="true" failonerror="true"/> - <copy file="${opendis7-java.relative}/opendis7-enumerations-source.jar" todir="lib" force="true" verbose="true" failonerror="true"/> - <copy file="${opendis7-java.relative}/opendis7-enumerations-javadoc.jar" todir="lib" force="true" verbose="true" failonerror="true"/> - - <fail message="opendis7-pdus-classes.jar not found"> - <condition> - <not> - <resourcecount count="1"> - <fileset id="fs" dir="${opendis7-java.relative}" includes="opendis7-pdus-classes.jar"/> - </resourcecount> - </not> - </condition> - </fail> - - - <copy file="${opendis7-java.relative}/opendis7-pdus-classes.jar" todir="lib" force="true" verbose="true" failonerror="true"/> - <copy file="${opendis7-java.relative}/opendis7-pdus-javadoc.jar" todir="lib" force="true" verbose="true" failonerror="true"/> - <copy file="${opendis7-java.relative}/opendis7-pdus-source.jar" todir="lib" force="true" verbose="true" failonerror="true"/> - --> - <!-- <delete file="lib/opendis7-classes.jar" verbose="true" failonerror="false"/> prior name --> - <!-- <delete file="lib/opendis7-javadoc.jar" verbose="true" failonerror="false"/> prior name --> - <!-- <delete file="lib/opendis7-source.jar" verbose="true" failonerror="false"/> prior name --> - - </target> - - <property name="gitlab.nps.edu.MV3500.lib" value="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/lib"/> - - <target name="update.opendis7.jar.from.gitlab" description="Update local opendis7 .jar files in project lib directory"> - <echo message="Update local opendis7 .jar files in project lib directory using"/> - <echo message=" ${gitlab.nps.edu.MV3500.lib}"/> - <nbbrowse url= "${gitlab.nps.edu.MV3500.lib}"/> - <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-full.jar" - dest="lib" verbose="true" usetimestamp="true"/> - <!-- - <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-pdus-classes.jar" - dest="lib" verbose="true" usetimestamp="true"/> - <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-enumerations-classes.jar" - dest="lib" verbose="true" usetimestamp="true"/> - <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-pdus-source.jar" - dest="lib" verbose="true" usetimestamp="true"/> - <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-enumerations-source.jar" - dest="lib" verbose="true" usetimestamp="true"/> - <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-pdus-javadoc.jar" - dest="lib" verbose="true" usetimestamp="true"/> - <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-enumerations-javadoc.jar" - dest="lib" verbose="true" usetimestamp="true"/> - --> - </target> - - <target name="update.opendis7.jar.from.maven" description="update opendis7.jar in project lib directory"> - <echo message="TODO retrieve from Maven published repository once available"/> - </target> - - <property name="gitlab.nps.edu.MV3302.lib" value="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/tree/master/lib/Simkit"/> - - <target name="update.simkit.jar.from.gitlab" description="Update local opendis7 .jar files in project lib directory"> - <echo message="Update local simkit .jar files in project lib directory using"/> - <echo message="TODO not yet updating correctly..."/> - <echo message=" ${gitlab.nps.edu.MV3302.lib}"/> - <nbbrowse url= "${gitlab.nps.edu.MV3302.lib}"/> - <get src="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/raw/master/lib/Simkit/simkit.jar" - dest="lib" verbose="true" usetimestamp="true"/> - <get src="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/raw/master/lib/Simkit/simkit-src.zip" - dest="lib" verbose="true" usetimestamp="true"/> - <get src="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/raw/master/lib/Simkit/simkit-doc.zip" - dest="lib" verbose="true" usetimestamp="true"/> - </target> - - <!-- Viskit properties --> - <target name="platformInitialize" depends="platformType"/> - <target name="platformType"> - <condition property="isWin" > - <os family="windows"/> - </condition> - <condition property="isMac" > - <os family="mac"/> - </condition> - <!-- Based on Apache Ant user-manual example --> - <condition property="isUnix"> - <and> - <os family="unix"/> - - <not> - <equals arg1="${os.name}" arg2="Mac OS X"/> - </not> - - </and> - </condition> - </target> - <target name="initWin" if="isWin"> - <property name="run.args" value="${win.run.args}"/> - </target> - <target name="initUnix" if="isUnix"> - <property name="run.args" value="${unix.run.args}"/> - </target> - <target name="initMac" if="isMac"> - <property name="run.args" value="${mac.run.args}"/> - </target> - <target name="initializeAll" depends="platformInitialize,initWin,initUnix,initMac"/> - - <target name="set.classpath" depends="initializeAll"> - <path id="runtime.classpath"> - <fileset dir="${viskit.lib.dir}"> - <include name="**/*.jar"/> - </fileset> - <pathelement path="${extra.classpath}"/> - </path> - <!--<echo message="runtime.classpath=${toString:runtime.classpath}"/>--> - </target> - - <target name="run.viskit" depends="set.classpath" description="Start the Visual Simikit (viskit) DES Authoring Tool on any O/S"> - <splash imageurl="file:${basedir}/${splash.image}" - useproxy="true" - showduration="5000"/> - <java classname="${main.class}" - classpathref="runtime.classpath" - dir="${viskit.dir}" - fork="true"> - <jvmarg line="${run.args}"/> - <arg value="${assy.file}"/> - </java> - </target> - - <target name="clean.all.viskit.logs" description="clean autogenerated PDU capture and Viskit generated logs"> - <delete dir="${viskit.dir}/logs"/> - <delete dir="${viskit.dir}/pduLog"/> - </target> - - <target name="nuke.dot.viskit" description="Abolish an out of synch configuration and metadata directory - only when necessary"> - <delete includeemptydirs="yes" dir="${dot.viskit.dir}"/> - <mkdir dir="${dot.viskit.dir}"/> - <copy todir="${dot.viskit.dir}" file="${c_app.xml}"/> - <copy todir="${dot.viskit.dir}" file="${c_gui.xml}"/> - </target> - +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 1995-2023 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + (https://www.nps.edu and https://www.MovesInstitute.org) + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +--> + +<!-- + Document : build.xml + Created on : 1 November 2017 + Author : Don Brutzman and Don McGregor + Description: Ant build.xml file for Networked Graphics MV3500 +--> +<project name="MV3500 Networked Graphics" default="all" basedir="."> + <description>Build targets for NPS Networked Graphics MV3500</description> + + <!-- TODO add targets for project maintenance, testing and deployment + + <property name="specificationsDirectory" location="specifications"/> + <import file="specifications/build.xml"/> --> + <property file="build.properties"/> + + <target name="versions" description="show tool versions and environment values"> + <echo>ant -version</echo> + <exec executable="ant" dir="." vmlauncher="false"> + <arg value="-version"/> + </exec> + <echo>java -version</echo> + <exec executable="java" dir="." vmlauncher="false"> + <arg value="-version"/> + </exec> + <echo></echo> + <!-- Ant environment variables https://ant.apache.org/manual/Tasks/property.html --> + <echo> ANT_HOME=${env.ANT_HOME}</echo> + <echo> JAVA_HOME=${env.JAVA_HOME}</echo> + <echo>CLASSPATH=${env.CLASSPATH}</echo> + <!--<echo>USER =${env.USER}</echo> --> + <!-- https://stackoverflow.com/questions/949678/ant-is-using-wrong-java-version --> + <!--echo>javac source/target $java.source=${java.source}</ --> + <echo>Java/JVM version $ant.java.version=${ant.java.version}</echo> + <echo>Java/JVM detail version $java.version=${java.version}</echo> + <echo>Ant version $ant.version=${ant.version}</echo> + <echo>Configuration settings: https://savage.nps.edu/Savage/developers.html</echo> + <!-- TODO Netbeans version --> + <!-- TODO Netbeans project version --> + <!-- DEBUG: to show all environment and local properties, add + <echoproperties/> --> + <echo message="==========================================="/> + </target> + + <target name="all" depends="versions"> + <ant dir="examples" target="clean"/> + <ant dir="examples" target="jar"/> + <ant dir="assignments" target="clean"/> + <ant dir="assignments" target="jar"/> + <antcall target="javadoc.all"/> + </target> + + <target name="clean.all.pduLogs" description="clean autogenerated PDU capture logs"> + <ant dir="assignments" target="clean.all.pduLogs"/> + <ant dir="examples" target="clean.all.pduLogs"/> + </target> + + <target name="javadoc.custom.all"> + <ant dir="assignments" target="javadoc.custom" useNativeBaseDir="true"/> + <ant dir="examples" target="javadoc.custom" useNativeBaseDir="true"/> + </target> + + <target name="view.gitlab.nps.edu.MV3500" description="view MV3500 gitlab site in web browser (via Netbeans only)"> + <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500"/> + <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500"/> + <!-- TODO implementation-independent approach if possible. other Ant approaches have to be customized for each OS --> + </target> + + <target name="view.gitlab.nps.edu.MV3500.assignments" description="view MV3500 gitlab examples in web browser (via Netbeans only)"> + <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/assignments"/> + <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/assignments"/> + </target> + + <target name="view.gitlab.nps.edu.MV3500.examples" description="view MV3500 gitlab examples in web browser (via Netbeans only)"> + <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/examples"/> + <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/examples"/> + <!-- TODO implementation-independent approach if possible. other Ant approaches have to be customized for each OS --> + </target> + + <target name="view.gitlab.nps.edu.MV3500.issues" description="view online issues in web browser (Netbeans only)"> + <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/issues" /> + <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/issues" /> + <!-- TODO implementation-independent approach if possible, but note that other Ant approaches usually have to be customized for each OS. --> + <echo message="... for issue visibility, be sure to login" /> + </target> + + <target name="view.gitlab.nps.edu.MV3500.specifications.README" description="view MV3500 gitlab examples in web browser (via Netbeans only)"> + <echo message="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/specifications/README.md"/> + <nbbrowse url="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/specifications/README.md"/> + </target> + + <target name="view.open-dis.github.com" description="view github open-dis site in web browser (via Netbeans only)"> + <echo message="https://github.com/open-dis"/> + <nbbrowse url="https://github.com/open-dis"/> + </target> + + <target name="view.open-dis.github.com.opendis7-java" description="view github open-dis open-dis-java current build in web browser (via Netbeans only)"> + <echo message="https://github.com/open-dis/opendis7-java"/> + <nbbrowse url="https://github.com/open-dis/opendis7-java"/> + </target> + + <target name="view.open-dis.github.com.opendis7-source-generator" description="view github open-dis opendis7-source-generator project in web browser (via Netbeans only)"> + <echo message="https://github.com/open-dis"/> + <nbbrowse url="https://github.com/open-dis"/> + </target> + + <target name="update.opendis7.jar.from.local" description="update opendis7-java jar files from locally built project into lib directory"> + + <property name="opendis7-java.relative" value="../../x3d-github/opendis7-java/dist"/> + <echo message="Copy ${opendis7-java.relative}/opendis7-full.jar to project lib/ subdirectory..."/> + <!-- https://ant.apache.org/manual/Tasks/fail.html --> + <fail message="opendis7-full.jar not found"> + <condition> + <not> + <resourcecount count="1"> + <fileset id="fs" dir="${opendis7-java.relative}" includes="opendis7-full.jar"/><!-- comma separated --> + </resourcecount> + </not> + </condition> + </fail> + <!-- clean out prior versions --> + <delete file="lib/opendis7-pdus-classes.jar" verbose="false" failonerror="false"/> + <delete file="lib/opendis7-pdus-javadoc.jar" verbose="false" failonerror="false"/> + <delete file="lib/opendis7-pdus-source.jar" verbose="false" failonerror="false"/> + <delete file="lib/opendis7-enumerations-classes.jar" verbose="false" failonerror="false"/> + <delete file="lib/opendis7-enumerations-javadoc.jar" verbose="false" failonerror="false"/> + <delete file="lib/opendis7-enumerations-source.jar" verbose="false" failonerror="false"/> + + <!-- replace latest version --> + <delete file="lib/opendis7-full.jar" verbose="true" failonerror="false"/> + <copy file="${opendis7-java.relative}/opendis7-full.jar" todir="lib" force="true" verbose="true" failonerror="true"/> + + <!-- + <delete file="assignments/dist/lib/opendis7-full.jar" verbose="true" failonerror="false"/> + <delete file="examples/dist/lib/opendis7-full.jar" verbose="true" failonerror="false"/> + <copy file="${opendis7-java.relative}/opendis7-full.jar" todir="assignments/dist/lib" force="true" verbose="true" failonerror="true"/> + <copy file="${opendis7-java.relative}/opendis7-full.jar" todir="examples/dist/lib" force="true" verbose="true" failonerror="true"/> + + <copy file="${opendis7-java.relative}/opendis7-enumerations-classes.jar" todir="lib" force="true" verbose="true" failonerror="true"/> + <copy file="${opendis7-java.relative}/opendis7-enumerations-source.jar" todir="lib" force="true" verbose="true" failonerror="true"/> + <copy file="${opendis7-java.relative}/opendis7-enumerations-javadoc.jar" todir="lib" force="true" verbose="true" failonerror="true"/> + + <fail message="opendis7-pdus-classes.jar not found"> + <condition> + <not> + <resourcecount count="1"> + <fileset id="fs" dir="${opendis7-java.relative}" includes="opendis7-pdus-classes.jar"/> + </resourcecount> + </not> + </condition> + </fail> + + + <copy file="${opendis7-java.relative}/opendis7-pdus-classes.jar" todir="lib" force="true" verbose="true" failonerror="true"/> + <copy file="${opendis7-java.relative}/opendis7-pdus-javadoc.jar" todir="lib" force="true" verbose="true" failonerror="true"/> + <copy file="${opendis7-java.relative}/opendis7-pdus-source.jar" todir="lib" force="true" verbose="true" failonerror="true"/> + --> + <!-- <delete file="lib/opendis7-classes.jar" verbose="true" failonerror="false"/> prior name --> + <!-- <delete file="lib/opendis7-javadoc.jar" verbose="true" failonerror="false"/> prior name --> + <!-- <delete file="lib/opendis7-source.jar" verbose="true" failonerror="false"/> prior name --> + + </target> + + <property name="gitlab.nps.edu.MV3500.lib" value="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/lib"/> + + <target name="update.opendis7.jar.from.gitlab" description="Update local opendis7 .jar files in project lib directory"> + <echo message="Update local opendis7 .jar files in project lib directory using"/> + <echo message=" ${gitlab.nps.edu.MV3500.lib}"/> + <nbbrowse url= "${gitlab.nps.edu.MV3500.lib}"/> + <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-full.jar" + dest="lib" verbose="true" usetimestamp="true"/> + <!-- + <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-pdus-classes.jar" + dest="lib" verbose="true" usetimestamp="true"/> + <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-enumerations-classes.jar" + dest="lib" verbose="true" usetimestamp="true"/> + <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-pdus-source.jar" + dest="lib" verbose="true" usetimestamp="true"/> + <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-enumerations-source.jar" + dest="lib" verbose="true" usetimestamp="true"/> + <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-pdus-javadoc.jar" + dest="lib" verbose="true" usetimestamp="true"/> + <get src="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/raw/master/lib/opendis7-enumerations-javadoc.jar" + dest="lib" verbose="true" usetimestamp="true"/> + --> + </target> + + <target name="update.opendis7.jar.from.maven" description="update opendis7.jar in project lib directory"> + <echo message="TODO retrieve from Maven published repository once available"/> + </target> + + <property name="gitlab.nps.edu.MV3302.lib" value="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/tree/master/lib/Simkit"/> + + <target name="update.simkit.jar.from.gitlab" description="Update local opendis7 .jar files in project lib directory"> + <echo message="Update local simkit .jar files in project lib directory using"/> + <echo message="TODO not yet updating correctly..."/> + <echo message=" ${gitlab.nps.edu.MV3302.lib}"/> + <nbbrowse url= "${gitlab.nps.edu.MV3302.lib}"/> + <get src="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/raw/master/lib/Simkit/simkit.jar" + dest="lib" verbose="true" usetimestamp="true"/> + <get src="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/raw/master/lib/Simkit/simkit-src.zip" + dest="lib" verbose="true" usetimestamp="true"/> + <get src="https://gitlab.nps.edu/abuss/MV3302ClassCode/-/raw/master/lib/Simkit/simkit-doc.zip" + dest="lib" verbose="true" usetimestamp="true"/> + </target> + + <!-- Viskit properties --> + <target name="platformInitialize" depends="platformType"/> + <target name="platformType"> + <condition property="isWin" > + <os family="windows"/> + </condition> + <condition property="isMac" > + <os family="mac"/> + </condition> + <!-- Based on Apache Ant user-manual example --> + <condition property="isUnix"> + <and> + <os family="unix"/> + + <not> + <equals arg1="${os.name}" arg2="Mac OS X"/> + </not> + + </and> + </condition> + </target> + <target name="initWin" if="isWin"> + <property name="run.args" value="${win.run.args}"/> + </target> + <target name="initUnix" if="isUnix"> + <property name="run.args" value="${unix.run.args}"/> + </target> + <target name="initMac" if="isMac"> + <property name="run.args" value="${mac.run.args}"/> + </target> + <target name="initializeAll" depends="platformInitialize,initWin,initUnix,initMac"/> + + <target name="set.classpath" depends="initializeAll"> + <path id="runtime.classpath"> + <fileset dir="${viskit.lib.dir}"> + <include name="**/*.jar"/> + </fileset> + <pathelement path="${extra.classpath}"/> + </path> + <!--<echo message="runtime.classpath=${toString:runtime.classpath}"/>--> + </target> + + <target name="run.viskit" depends="set.classpath" description="Start the Visual Simikit (viskit) DES Authoring Tool on any O/S"> + <splash imageurl="file:${basedir}/${splash.image}" + useproxy="true" + showduration="5000"/> + <java classname="${main.class}" + classpathref="runtime.classpath" + dir="${viskit.dir}" + fork="true"> + <jvmarg line="${run.args}"/> + <arg value="${assy.file}"/> + </java> + </target> + + <target name="clean.all.viskit.logs" description="clean autogenerated PDU capture and Viskit generated logs"> + <delete dir="${viskit.dir}/logs"/> + <delete dir="${viskit.dir}/pduLog"/> + </target> + + <target name="reset.viskit.MV3500" description="initialize user preferences for Viskit MV3500"> + <echo message="Warning: under development"/> + <echo message="Reset MV3500 user's Viskit configuration files in ${dot.viskit.dir}"/> + <delete includeemptydirs="yes" dir="${dot.viskit.dir}"/> + <!-- repopulute with defaults --> + <mkdir dir="${dot.viskit.dir}"/> + <copy verbose="true" tofile="${dot.viskit.dir}/c_app.xml" file="c_app.ViskitDefaultMV3500.xml"/> + <copy todir ="${dot.viskit.dir}" file="${c_gui.xml}"/> + </target> + + <target name="reset.viskit.DefaultViskitProject" description="initialize user preferences for the bundled DefaultViskitProject"> + <!-- TODO watch for that project to get renamed --> + <echo message="Warning: under development"/> + <echo message="Reset MV3500 user's Viskit configuration files in ${dot.viskit.dir}"/> + <delete includeemptydirs="yes" dir="${dot.viskit.dir}"/> + <!-- repopulute with defaults --> + <mkdir dir="${dot.viskit.dir}"/> + <copy verbose="true" tofile="${dot.viskit.dir}/c_app.xml" file="c_app.ViskitDefaultProject.xml"/> + <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"> + <echo message="Reset user's Viskit configuration files in ${dot.viskit.dir}"/> + <delete includeemptydirs="yes" dir="${dot.viskit.dir}"/> + <mkdir dir="${dot.viskit.dir}"/> + <!-- repopulute with defaults --> + <!-- ${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"/> + </target> + </project> \ No newline at end of file diff --git a/c_app.ViskitDefaultMV3500.xml b/c_app.ViskitDefaultMV3500.xml new file mode 100644 index 0000000000000000000000000000000000000000..787151ea9f26ecfa0731f2bb82e40a82aac71ac2 --- /dev/null +++ b/c_app.ViskitDefaultMV3500.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Viskit application configuration file c_app.xml --> +<!-- Programming note: values in this file are retrieved by keys such as 'app.beanshell.warning' --> +<!-- Programming note: the root element name is ignored when assembling keys --> +<ViskitConfig> + <app> + <beanshell> + <warning>true</warning> + </beanshell> + <mainframe> + <size h="680" w="930" /> + </mainframe> + <projecthome> + <!-- These two attributes MUST always be at least zero-length Strings --> + <!-- DefaultProject is included in this template for convenience --> + <path dir="../examples/src"/> + <name value="ViskitOpenDis7Examples"/> + </projecthome> + <tabs> + <EventGraphEditor visible="true" /> + <AssemblyEditor visible="true" /> + <AssemblyRun visible="true" /> + <DesignOfExperiments visible="false" /> + <ClusterRun visible="false" /> + <AnalystReport visible="false" /> + </tabs> + <debug>false</debug> + </app> + <history> + <ProjectEditor> + <Recent> + <!-- MV3500 includes the following two projects --> + <Project value="../viskit/MyViskitProjects/DefaultProject" /> + <Project value="../examples/src/ViskitOpenDis7Examples"/> + </Recent> + </ProjectEditor> + <Cluster> + <Account last="true" password="" port="4444" server="wipeout.hpr.nps.edu" username="" /> + </Cluster> + <AssemblyEditor> + <Recent> + <AssemblyFile value="../examples/src/ViskitOpenDis7Examples/Assemblies/dis7/ArrivalProcessOpenDis7Assembly.xml"/> + <AssemblyFile value="../examples/src/ViskitOpenDis7Examples/Assemblies/dis7/SimpleServerDis7Assembly.xml"/> + </Recent> + </AssemblyEditor> + <EventGraphEditor> + <Recent> + <EventGraphFile value="../examples/src/ViskitOpenDis7Examples/EventGraphs/dis7/ArrivalProcessOpenDis7.xml"/> + </Recent> + </EventGraphEditor> + </history> +</ViskitConfig> + diff --git a/c_app.ViskitDefaultProject.xml b/c_app.ViskitDefaultProject.xml new file mode 100644 index 0000000000000000000000000000000000000000..1e8bb99daa8877be272678459d9703cd2976ab89 --- /dev/null +++ b/c_app.ViskitDefaultProject.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Viskit application configuration file c_app.xml --> +<!-- Programming note: values in this file are retrieved by keys such as 'app.beanshell.warning' --> +<!-- Programming note: the root element name is ignored when assembling keys --> +<ViskitConfig> + <app> + <beanshell> + <warning>true</warning> + </beanshell> + <mainframe> + <size h="680" w="930" /> + </mainframe> + <projecthome> + <!-- These two attributes MUST always be at least zero-length Strings --> + <!-- DefaultProject is included in this template for convenience --> + <!-- TODO keep an eye out for possible rename, e.g. DefaultViskitProject --> + <path dir="./MyViskitProjects" /> + <name value="DefaultProject" /> + </projecthome> + <tabs> + <EventGraphEditor visible="true" /> + <AssemblyEditor visible="true" /> + <AssemblyRun visible="true" /> + <DesignOfExperiments visible="false" /> + <ClusterRun visible="false" /> + <AnalystReport visible="false" /> + </tabs> + <debug>false</debug> + </app> + <history> + <ProjectEditor> + <Recent> + <!-- MV3500 includes the following two projects --> + <Project value="./MyViskitProjects/DefaultProject" /> + <Project value="../examples/src/ViskitOpenDis7Examples"/> + </Recent> + </ProjectEditor> + <Cluster> + <Account last="true" password="" port="4444" server="wipeout.hpr.nps.edu" username="" /> + </Cluster> + <AssemblyEditor> + <Recent> + <AssemblyFile value="./MyViskitProjects/DefaultProject/Assemblies/examples/ArrayTesterAssembly.xml" /> + <AssemblyFile value="./MyViskitProjects/DefaultProject/Assemblies/examples/InventoryModelAssembly.xml" /> + <AssemblyFile value="./MyViskitProjects/DefaultProject/Assemblies/examples/ServerAssembly3.xml" /> + <AssemblyFile value="./MyViskitProjects/DefaultProject/Assemblies/examples/ServerWithRenegesAssembly.xml" /> + <AssemblyFile value="./MyViskitProjects/DefaultProject/Assemblies/examples/TestServerGenericAssembly.xml" /> + </Recent> + </AssemblyEditor> + <EventGraphEditor> + <Recent> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/ArrayTester.xml" /> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/ArrivalProcess.xml" /> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/InventoryModel.xml" /> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/SimpleServer.xml" /> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/Creator.xml" /> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/ServerWithReneges.xml" /> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/EntityCreator.xml" /> + <EventGraphFile value="./MyViskitProjects/DefaultProject/EventGraphs/examples/ServerGeneric.xml" /> + </Recent> + </EventGraphEditor> + </history> +</ViskitConfig> + diff --git a/examples/build.xml b/examples/build.xml index 31bdfd58879a38df1f4fb6905c378b780595ce27..c3edb7fd9fb2f56c7f074da12735b35b06b94bf2 100644 --- a/examples/build.xml +++ b/examples/build.xml @@ -148,7 +148,7 @@ POSSIBILITY OF SUCH DAMAGE. <property name="javadoc.nonavbar" value="false"/> <property name="javadoc.notree" value="false"/> <property name="javadoc.private" value="false"/> - <property name="javadoc.source" value="${java.source}"/> +<!--<property name="javadoc.source" value="${java.source}"/>--> <property name="javadoc.splitindex" value="true"/> <property name="javadoc.breakiterator" value="true"/> <property name="javadoc.use" value="true"/><!-- Create class and package usage pages --> @@ -176,13 +176,13 @@ POSSIBILITY OF SUCH DAMAGE. notree="${javadoc.notree}" Overview="src/overview.html" Private="${javadoc.private}" - source="${java.source}" Splitindex="${javadoc.splitindex}" Use="${javadoc.use}" useexternalfile="yes" verbose="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> + <!-- source="${java.source}" --> <classpath> <pathelement location="../lib/opendis7-full.jar"/> <pathelement location="../lib/open-dis_4.16.jar"/> diff --git a/examples/nbproject/project.properties b/examples/nbproject/project.properties index 546aa0b56deba63200d7b17bfc738d729255093e..a659c6016220db9cc02cbfe18f4b1c0ce29a9244 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=22 -javac.target=22 -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 +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 diff --git a/examples/nbproject/project.xml b/examples/nbproject/project.xml index cdded973dc5a08e306d32fa0fceb376c3486a6a7..d7c8e3fd3bc7ee7e746750956a36a82fa1034338 100644 --- a/examples/nbproject/project.xml +++ b/examples/nbproject/project.xml @@ -1,92 +1,91 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://www.netbeans.org/ns/project/1"> - <type>org.netbeans.modules.java.j2seproject</type> - <configuration> - <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> - <name>Networked Graphics MV3500 examples</name> - <explicit-platform explicit-source-supported="true"/> - <source-roots> - <root id="src.dir"/> - <root id="src.src.dir"/> - <root id="src.src2.dir"/> - </source-roots> - <test-roots/> - </data> - <spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1"> - <word>accessor</word> - <word>autogeneration</word> - <word>classpath</word> - <word>CommentPdu</word> - <word>CourseExamples</word> - <word>createDatagramSocket</word> - <word>createThreads</word> - <word>customizable</word> - <word>Cygwin</word> - <word>Datagram</word> - <word>datagramSocket</word> - <word>deserialization</word> - <word>DisChannel</word> - <word>DisPduType</word> - <word>DisThreadedNetworkInterface</word> - <word>docx</word> - <word>ExampleSimulationProgram</word> - <word>ExampleTrackInterpolation</word> - <word>getEspduCount</word> - <word>getNetworkAddress</word> - <word>getNetworkPort</word> - <word>gitlab</word> - <word>html</word> - <word>initialLocation</word> - <word>instantiable</word> - <word>interarrival</word> - <word>interpolators</word> - <word>ipconfig</word> - <word>isAlive</word> - <word>isClosed</word> - <word>isConnected</word> - <word>isInterrupted</word> - <word>javadoc</word> - <word>joinGroup</word> - <word>killThread</word> - <word>latestLocation</word> - <word>leaveGroup</word> - <word>localhost</word> - <word>loopback</word> - <word>marshalling</word> - <word>multicast</word> - <word>NetBeans</word> - <word>netcat</word> - <word>NPS</word> - <word>pdu</word> - <word>PduCaptureLog</word> - <word>pduLog</word> - <word>PduRecorder</word> - <word>PDUs</word> - <word>pduSentList</word> - <word>pduTrack</word> - <word>png</word> - <word>prepended</word> - <word>receiveThread</word> - <word>runSimulation</word> - <word>sendingThread</word> - <word>setKillSentinelAndInterrupts</word> - <word>simkit</word> - <word>simulationComplete</word> - <word>simulationists</word> - <word>src</word> - <word>subclassed</word> - <word>subpackage</word> - <word>TcpExamples</word> - <word>teardown</word> - <word>thisHostName</word> - <word>timestep</word> - <word>TrackSimulationProgram</word> - <word>txt</word> - <word>UdpMulticastHttpExamples</word> - <word>unicast</word> - <word>waypoint</word> - <word>waypoints</word> - <word>Wireshark</word> - </spellchecker-wordlist> - </configuration> -</project> +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>Networked Graphics MV3500 examples</name> + <source-roots> + <root id="src.dir"/> + <root id="src.src.dir"/> + <root id="src.src2.dir"/> + </source-roots> + <test-roots/> + </data> + <spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1"> + <word>accessor</word> + <word>autogeneration</word> + <word>classpath</word> + <word>CommentPdu</word> + <word>CourseExamples</word> + <word>createDatagramSocket</word> + <word>createThreads</word> + <word>customizable</word> + <word>Cygwin</word> + <word>Datagram</word> + <word>datagramSocket</word> + <word>deserialization</word> + <word>DisChannel</word> + <word>DisPduType</word> + <word>DisThreadedNetworkInterface</word> + <word>docx</word> + <word>ExampleSimulationProgram</word> + <word>ExampleTrackInterpolation</word> + <word>getEspduCount</word> + <word>getNetworkAddress</word> + <word>getNetworkPort</word> + <word>gitlab</word> + <word>html</word> + <word>initialLocation</word> + <word>instantiable</word> + <word>interarrival</word> + <word>interpolators</word> + <word>ipconfig</word> + <word>isAlive</word> + <word>isClosed</word> + <word>isConnected</word> + <word>isInterrupted</word> + <word>javadoc</word> + <word>joinGroup</word> + <word>killThread</word> + <word>latestLocation</word> + <word>leaveGroup</word> + <word>localhost</word> + <word>loopback</word> + <word>marshalling</word> + <word>multicast</word> + <word>NetBeans</word> + <word>netcat</word> + <word>NPS</word> + <word>pdu</word> + <word>PduCaptureLog</word> + <word>pduLog</word> + <word>PduRecorder</word> + <word>PDUs</word> + <word>pduSentList</word> + <word>pduTrack</word> + <word>png</word> + <word>prepended</word> + <word>receiveThread</word> + <word>runSimulation</word> + <word>sendingThread</word> + <word>setKillSentinelAndInterrupts</word> + <word>simkit</word> + <word>simulationComplete</word> + <word>simulationists</word> + <word>src</word> + <word>subclassed</word> + <word>subpackage</word> + <word>TcpExamples</word> + <word>teardown</word> + <word>thisHostName</word> + <word>timestep</word> + <word>TrackSimulationProgram</word> + <word>txt</word> + <word>UdpMulticastHttpExamples</word> + <word>unicast</word> + <word>waypoint</word> + <word>waypoints</word> + <word>Wireshark</word> + </spellchecker-wordlist> + </configuration> +</project> diff --git a/examples/src/SimkitOpenDis7Examples/README.md b/examples/src/SimkitOpenDis7Examples/README.md index 5bb6cc0e3b210f02238669008be1839d26146702..fffbb566f2a9e79df29768f6f246430bb63054b9 100644 --- a/examples/src/SimkitOpenDis7Examples/README.md +++ b/examples/src/SimkitOpenDis7Examples/README.md @@ -1,13 +1,25 @@ -# Simkit DIS Examples +# MV3500 Simkit Viskit DIS Examples -[This directory](https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/examples/src/SimkitOpenDis7Examples) includes simple Simkit programs which are getting modified to -utilize opendis7-java libraries for PDU output. +<!-- TODO rename directory SimkitViskitOpenDis7Examples --> +<!-- https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/examples/src/SimkitOpenDis7Examples/README.md --> + +*Simkit* is a powerful tool for modeling and simulation that can be networked +with other applications by integrating use of the +Distributed Interactive Simulation (DIS) protocol. +This directory includes simple Simkit programs which are getting modified to +utilize [opendis7-java](https://savage.nps.edu/opendis7-java) libraries for PDU output. + +*Viskit* is a visual editor for authoring Simkit event graphs and simulation assemblies. +Models are authored visually and saved as XML, which in turn generates Simkit Java code. +This tool is newly restored and we are now building examples that integrate +DIS capabilities with Simkit. ## Design Goals * Integrate code to share state changes from Simkit entities as DIS PDU messages. * Establish reference examples with corresponding output logs for test confirmation. -* Build interoperability examples for distributed simulation using Simkit, DIS and X3D. +* Build interoperability examples for distributed simulation using Simkit, Viskit, DIS and X3D. +* Continue evolution of [Viskit tool](https://gitlab.nps.edu/Savage/viskit) and integrated builds. ## Example Programs @@ -39,10 +51,12 @@ c. Two Crane Berths * Buss, Arnold, [Component Based Simulation Modeling with Simkit](documentation/BussComponentBasedSimulationModelingSimkitWintersim2002.pdf), Proceedings of the 2002 Winter Simulation Conference. * [Discrete Event Simulation Modeling](documentation/Discrete Event Simulation Modeling.pdf) manual for Simkit -* https://github.com/ahbuss/Simkit +* [Github: Simkit](https://github.com/ahbuss/Simkit) * https://gitlab.nps.edu/abuss/MV3302ClassCode * [MV3302: Introduction to Discrete Event Simulation Modeling (SP22_1_AB)](https://cle.nps.edu/portal/site/7c6b3539-58e4-4640-9551-ab03f8629e3c) in NPS Sakai * [MV3302 > Resources > Handouts](https://cle.nps.edu/portal/site/7c6b3539-58e4-4640-9551-ab03f8629e3c/tool/7f0dea2b-fa42-4bed-8c38-c67ce9f56582?panel=Main) +* [Simkit Quick Reference](documentation/SimkitQuickReference.docx) +* [Viskit demo video](https://savage.nps.edu/videos/Viskit-demo-2023MAR4.mp4) and [info](https://savage.nps.edu/videos/Viskit-demo-info-2023MAR4.mp4) ## TODO diff --git a/examples/src/SimkitOpenDis7Examples/documentation/Discrete Event Simulation Modeling.pdf b/examples/src/SimkitOpenDis7Examples/documentation/Discrete Event Simulation Modeling.pdf index 529b1ed191932d95269a4471d6fb0ed5c7ca3995..13eca24db967ef92fa894582513f25d094790ac2 100644 Binary files a/examples/src/SimkitOpenDis7Examples/documentation/Discrete Event Simulation Modeling.pdf and b/examples/src/SimkitOpenDis7Examples/documentation/Discrete Event Simulation Modeling.pdf differ diff --git a/examples/src/UdpExamples/MulticastUdpChatKeyboardLog.txt b/examples/src/UdpExamples/MulticastUdpChatKeyboardLog.txt new file mode 100644 index 0000000000000000000000000000000000000000..c4a07fb833c7cfea7ca64f4495533205b5c88ba6 --- /dev/null +++ b/examples/src/UdpExamples/MulticastUdpChatKeyboardLog.txt @@ -0,0 +1,64 @@ +MulticastUdpChatKeyboardLog.txt + +=============================== +oldlaptop MulticastUdpChatKeyboardSender + +ant -f D:\\x-nps-gitlab\\NetworkedGraphicsMV3500\\examples -Dnb.internal.action.name=run.single -Djavac.includes=UdpExamples/MulticastUdpChatKeyboardSender.java -Drun.class=UdpExamples.MulticastUdpChatKeyboardSender run-single +init: +Deleting: D:\x-nps-gitlab\NetworkedGraphicsMV3500\examples\build\built-jar.properties +deps-jar: +Updating property file: D:\x-nps-gitlab\NetworkedGraphicsMV3500\examples\build\built-jar.properties +Compiling 1 source file to D:\x-nps-gitlab\NetworkedGraphicsMV3500\examples\build\classes +compile-single: +run-single: +UdpExamples.MulticastUdpChatKeyboardSender started... +Multicast address/port: 239.1.2.15/1718 +[DisThreadedNetworkInterface] using network interface Intel(R) Dual Band Wireless-AC 8260 +type new message here: oldlaptop 1 +Sent packet 1 of 100: "oldlaptop 1" +type new message here: oldlaptop 2 +Sent packet 2 of 100: "oldlaptop 2" +type new message here: quit +Sent packet 3 of 100: "quit" + +=============================== +newlaptop MulticastUdpChatKeyboardSender + +ant -f C:\\x3d-nps-gitlab\\NetworkedGraphicsMV3500\\examples -Dnb.internal.action.name=run.single -Djavac.includes=UdpExamples/MulticastUdpChatKeyboardSender.java -Drun.class=UdpExamples.MulticastUdpChatKeyboardSender run-single +init: +Deleting: C:\x3d-nps-gitlab\NetworkedGraphicsMV3500\examples\build\built-jar.properties +deps-jar: +Updating property file: C:\x3d-nps-gitlab\NetworkedGraphicsMV3500\examples\build\built-jar.properties +Compiling 1 source file to C:\x3d-nps-gitlab\NetworkedGraphicsMV3500\examples\build\classes +compile-single: +run-single: +UdpExamples.MulticastUdpChatKeyboardSender started... +Multicast address/port: 239.1.2.15/1718 +[DisThreadedNetworkInterface] using network interface Intel(R) Wi-Fi 6E AX210 160MHz +type new message here: newlaptop 1 +Sent packet 1 of 100: "newlaptop 1" +type new message here: newlaptop 2 +Sent packet 2 of 100: "newlaptop 2" + +=============================== +oldlaptop MulticastUdpReceiver + +ant -f D:\\x-nps-gitlab\\NetworkedGraphicsMV3500\\examples -Dnb.internal.action.name=run.single -Djavac.includes=UdpExamples/MulticastUdpReceiver.java -Drun.class=UdpExamples.MulticastUdpReceiver run-single +init: +Deleting: D:\x-nps-gitlab\NetworkedGraphicsMV3500\examples\build\built-jar.properties +deps-jar: +Updating property file: D:\x-nps-gitlab\NetworkedGraphicsMV3500\examples\build\built-jar.properties +Compiling 1 source file to D:\x-nps-gitlab\NetworkedGraphicsMV3500\examples\build\classes +compile-single: +run-single: +UdpExamples.MulticastUdpReceiver started... +[DisThreadedNetworkInterface] using network interface Intel(R) Dual Band Wireless-AC 8260 +Multicast address/port: 239.1.2.15/1718 isBound=true +Multicast packets received log: + 1. "[brutzman 1] oldlaptop 1" + 2. "[brutzman 1] newlaptop 1" + 3. "[brutzman 2] newlaptop 2" + 4. "[brutzman 2] oldlaptop 2" + 5. "[brutzman 3] quit" + +=============================== \ No newline at end of file diff --git a/examples/src/UdpExamples/MulticastUdpChatKeyboardSender.java b/examples/src/UdpExamples/MulticastUdpChatKeyboardSender.java new file mode 100644 index 0000000000000000000000000000000000000000..79ad6716309c91b67c5e3dd64c79d48309b51cd9 --- /dev/null +++ b/examples/src/UdpExamples/MulticastUdpChatKeyboardSender.java @@ -0,0 +1,155 @@ +package UdpExamples; + +import static UdpExamples.MulticastUdpReceiver.BUFFER_LENGTH; +import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface; +import java.io.*; +import java.net.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Get keyboard input to send string packets on a UDP multicast group. + * The source looks a lot like MulticastUdpSender. + * TODO: Start this after launching MulticastUdpReceiver. + * Multicast must be enabled for the (wired or wireless) LAN that the system is connected too. + * Note that these paired programs can communicate within a remote LAN (such as a wireless + * home network) even if one or both machines are connected via a + * <a href="https://en.wikipedia.org/wiki/Virtual_private_network" target="_blank">Virtual Private Network (VPN)</a>. + * + * Privacy note: this sender advertises your user name as part of the multicast packet message + * + * @author mcgredo + * @author brutzman@nps.edu + */ +public class MulticastUdpChatKeyboardSender +{ + /** Default constructor */ + public MulticastUdpChatKeyboardSender() + { + // default constructor + } + // reserved range for all IPv4 multicast: 224.0.0.0 through 239.255.255.255 + // https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml + + /** Default multicast group address for send and receive connections. + * @see <a href="https://en.wikipedia.org/wiki/Multicast_address" target="_blank">https://en.wikipedia.org/wiki/Multicast_address</a> */ + public static final String MULTICAST_ADDRESS = "239.1.2.15"; // within reserved multicast address range + /** Default socket port used, matches Wireshark DIS capture default + * @see <a href="https://en.wikipedia.org/wiki/Port_(computer_networking)" target="_blank">https://en.wikipedia.org/wiki/Port_(computer_networking)</a> */ + public static final int DESTINATION_PORT = 1718; + + /** Time to live: how many router-decrement levels can be crossed */ + public static final int TTL = 10; + + /** How many packets to send prior to termination */ + public static final int MAXLOOPSIZE = 100; // or maybe 20000 + + /** How many packets to send prior to termination */ + public static final String LINE_TERMINATOR = "###;"; // do not begin with ; + + /** Receiving this message causes termination + * @see <a href="https://en.wikipedia.org/wiki/Sentinel_value" target="_blank">https://en.wikipedia.org/wiki/Sentinel_value</a> */ + public static final String QUIT_SENTINEL = "QUIT QUIT QUIT!"; + private static NetworkInterface ni; + + /** + * Program invocation, execution starts here. + * TODO: allow setting address/port group and provide help message. + * @param args command-line arguments + * @throws java.io.IOException execution error + */ + @SuppressWarnings("SleepWhileInLoop") + public static void main(String[] args) throws IOException + { + MulticastSocket multicastSocket = null; + InetSocketAddress group = null; + + // Put together a message with binary content. "ByteArrayOutputStream" + // is a java.io utility that lets us put together an array of binary + // data, which we put into the UDP packet. + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + try + { + System.out.println("UdpExamples.MulticastUdpChatKeyboardSender started..."); + // https://stackoverflow.com/questions/18747134/getting-cant-assign-requested-address-java-net-socketexception-using-ehcache + System.setProperty("java.net.preferIPv4Stack", "true"); + + // multicast group we are sending to--not a single host + multicastSocket = new MulticastSocket(/*DESTINATION_PORT*/); + multicastSocket.setTimeToLive(TTL); // time to live reduces scope of transmission + InetAddress multicastAddress = InetAddress.getByName(MULTICAST_ADDRESS); + System.out.println("Multicast address/port: " + multicastAddress.getHostAddress() + "/" + DESTINATION_PORT); + + group = new InetSocketAddress(multicastAddress, DESTINATION_PORT); + // Join group useful on receiving side + multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); + // You can join multiple groups here + + byte[] buffer = baos.toByteArray(); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group/*, DESTINATION_PORT*/); + + String userName = System.getProperty("user.name"); + String newMessage = new String(); // from user via keyboard + + for (int messageIndex = 1; messageIndex < MAXLOOPSIZE; messageIndex++) + { + String spacer = new String(); // align console outputs + if (messageIndex < 10) + spacer = " "; + + // Put together an updated packet to send + if (messageIndex < MAXLOOPSIZE) + { + System.out.print ("type new message here: "); + newMessage = System.console().readLine(); // this line blocks, awaiting keyboard input from user +// System.out.println ("[trace] console return: " + newMessage); + + // avoid overrunning receive buffer + int maxStringLength = BUFFER_LENGTH - LINE_TERMINATOR.length() - userName.length() - 5; + if (newMessage.length() > maxStringLength) + newMessage = newMessage.substring(0, maxStringLength); + + // Put together an updated packet to send + dos.writeChars("[" + userName + " " + spacer + messageIndex + "] "); + dos.writeChars(newMessage + LINE_TERMINATOR); // string chars for readability, include ; semicolon as termination sentinel + } + else dos.writeChars(QUIT_SENTINEL + LINE_TERMINATOR); // note string must include ; semicolon as termination sentinel + + buffer = baos.toByteArray(); + packet.setData(buffer); + multicastSocket.send(packet); + System.out.print ("Sent packet " + spacer + (messageIndex) + " of " + MAXLOOPSIZE + ": "); + System.out.println("\"" + newMessage + "\""); + baos.reset(); + + // How fast does this go? Does UDP try to slow it down, or does + // this cause network problems? (hint: yes for an unlimited send + // rate, unlike TCP). How do you know on the receiving side + // that you haven't received a duplicate UDP packet, out of + // order packet, or dropped packet? Necessary considerations. + Thread.sleep(1000); // only send one per second + } + System.out.println("MulticastSender complete."); + } + catch(IOException | InterruptedException e) + { + System.err.println("Problem with MulticastSender, see exception trace:"); + System.err.println(e); + } finally { + + if (multicastSocket != null && !multicastSocket.isClosed()) { + try { + multicastSocket.leaveGroup(group, ni); + } catch (IOException ex) { + Logger.getLogger(MulticastUdpChatKeyboardSender.class.getName()).log(Level.SEVERE, null, ex); + } + multicastSocket.close(); + } + + dos.close(); + } + } + +} diff --git a/examples/src/UdpExamples/MulticastUdpReceiver.java b/examples/src/UdpExamples/MulticastUdpReceiver.java index e7d5220158b9ae03570998d5729f7ecaa6853348..83b5c415e9c0f5ac468984ab26d3fc1fbbf0b81a 100644 --- a/examples/src/UdpExamples/MulticastUdpReceiver.java +++ b/examples/src/UdpExamples/MulticastUdpReceiver.java @@ -1,5 +1,6 @@ package UdpExamples; +import static UdpExamples.MulticastUdpChatKeyboardSender.LINE_TERMINATOR; import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface; import java.io.*; import java.net.*; @@ -8,7 +9,12 @@ import java.util.logging.Level; import java.util.logging.Logger; /** - * Looks a lot like UdpReceiver. Start this before launching MulticastSender. + * Send preformatted test packets on a UDP multicast group. + * The source looks a lot like UnicastUdpReceiver. Start this before launching MulticastUdpSender. + * Multicast must be enabled for the (wired or wireless) LAN that the system is connected too. + * Note that these paired programs can communicate within a remote LAN (such as a wireless + * home network) even if one or both machines are connected via a + * <a href="https://en.wikipedia.org/wiki/Virtual_private_network" target="_blank">Virtual Private Network (VPN)</a>. * * @author mcgredo * @author brutzman@nps.edu @@ -33,6 +39,8 @@ public class MulticastUdpReceiver private static final boolean INFINITE_READ_LOOP = true; private static NetworkInterface ni; + + public static final int BUFFER_LENGTH = 1500; /** * Program invocation, execution starts here @@ -42,7 +50,7 @@ public class MulticastUdpReceiver { MulticastSocket multicastSocket = null; InetSocketAddress group = null; - ByteBuffer buffer = ByteBuffer.allocate(1500); + ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH); DatagramPacket packet = new DatagramPacket(buffer.array(), buffer.capacity()); try { @@ -62,49 +70,75 @@ public class MulticastUdpReceiver group = new InetSocketAddress(multicastAddress, DESTINATION_PORT); // Join group useful on receiving side - multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); + multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); // utility function // You can join multiple groups here - System.out.println("Multicast address/port: " + multicastAddress.getHostAddress() + "/" + DESTINATION_PORT); + System.out.println("Multicast address/port: " + multicastAddress.getHostAddress() + "/" + DESTINATION_PORT + + " isBound=" + multicastSocket.isBound()); + // unnecessary, no server involved: + "isConnected=" + multicastSocket.isConnected() System.out.println("Multicast packets received log:"); - int index, count = 0; // initialize - float firstFloat, secondFloat; + int messageCount = 0; // initialize StringBuilder firstCharacters = new StringBuilder(); char nextChar; - while (true) { // true is always true, so this is an infinite loop that continues until interrupted - multicastSocket.receive(packet); - count++; + while (true) // true is always true, so this is an infinite loop that continues until interrupted + { + // initializations for this loop + int messageIndex = 0; + float firstFloat = 0.0f; + float secondFloat = 0.0f; + + multicastSocket.receive(packet); // this method call will block until a packet is received + messageCount++; - nextChar = ' '; + nextChar = ' '; // reinitialize while (nextChar != ';') // read and build string until terminator ; found { nextChar = buffer.getChar(); firstCharacters.append(nextChar); } - if (firstCharacters.toString().contains(MulticastUdpSender.QUIT_SENTINEL)) { + if (firstCharacters.toString().contains(MulticastUdpSender.QUIT_SENTINEL)) + { System.out.println("Received sentinel \"" + MulticastUdpSender.QUIT_SENTINEL + "\""); if (!INFINITE_READ_LOOP) { break; // exit out of reading loop } } - index = buffer.getInt(); - firstFloat = buffer.getFloat(); - secondFloat = buffer.getFloat(); + boolean foundNumbers = false; + String line = firstCharacters.toString(); + if (line.contains(LINE_TERMINATOR)) + { + foundNumbers = false; + firstCharacters.setLength(line.length() - LINE_TERMINATOR.length()); // clip EOL sentinel + } + else if (buffer.hasRemaining()) // likely always true since size is 1500 + { + messageIndex = buffer.getInt(); + firstFloat = buffer.getFloat(); + secondFloat = buffer.getFloat(); + // simplistic tests for numbers read from buffer + if ((messageIndex == 0) && (firstFloat == 0.0f) && (secondFloat == 0.0f)) + foundNumbers = false; + else if ((messageIndex >= 0) && (messageIndex <= 10000)) + foundNumbers = true; + } + else System.out.print("[trace] no numbers encountered in buffer"); buffer.clear(); - if (count < 10) { - System.out.print(" "); // prettier output formatting + if (messageCount < 10) { + System.out.print(" "); // prettier output formatting for first nine lines } - System.out.print(count + ". \"" + firstCharacters + "\" "); // wrap string in quote marks - System.out.println("index=" + index + ", firstFloat=" + firstFloat + " secondFloat=" + secondFloat); - - System.out.println("MulticastReceiver loop complete."); - firstCharacters.setLength(0); + System.out.println(messageCount + ". \"" + firstCharacters + "\" "); // wrap string in quote marks + if (foundNumbers) + { + System.out.println(" messageIndex=" + messageIndex + ", firstFloat=" + firstFloat + " secondFloat=" + secondFloat); + System.out.println(" MulticastUdpReceiver message receipt complete."); + } + firstCharacters.setLength(0); // reset } } catch (IOException e) { - System.err.println("Problem with MulticastReceiver, see exception trace:"); + System.err.println("Problem with MulticastUdpReceiver, see exception trace:"); System.err.println(e); } finally // clean up after exit condition { @@ -117,7 +151,7 @@ public class MulticastUdpReceiver multicastSocket.close(); } // socket/database/completion cleanup code can go here, if needed. - System.out.println("MulticastReceiver finally block, complete."); + System.out.println("MulticastUdpReceiver finally block, complete."); } } } diff --git a/examples/src/UdpExamples/MulticastUdpSender.java b/examples/src/UdpExamples/MulticastUdpSender.java index 68788b7f83da4a6edbf7c8d358669ebd7de0963f..9d6e95c77b4540e2eca94864d707669155416297 100644 --- a/examples/src/UdpExamples/MulticastUdpSender.java +++ b/examples/src/UdpExamples/MulticastUdpSender.java @@ -7,7 +7,12 @@ import java.util.logging.Level; import java.util.logging.Logger; /** - * Looks a lot like UdpSender. Start this after launching MulticastReceiver. + * Send preformatted test packets on a UDP multicast group. + * The source looks a lot like UnicastUdpSender. Start this after launching MulticastUdpReceiver. + * Multicast must be enabled for the (wired or wireless) LAN that the system is connected too. + * Note that these paired programs can communicate within a remote LAN (such as a wireless + * home network) even if one or both machines are connected via a + * <a href="https://en.wikipedia.org/wiki/Virtual_private_network" target="_blank">Virtual Private Network (VPN)</a>. * * Privacy note: this sender advertises your user name as part of the multicast packet message * @@ -77,7 +82,7 @@ public class MulticastUdpSender group = new InetSocketAddress(multicastAddress, DESTINATION_PORT); // Join group useful on receiving side - multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); + multicastSocket.joinGroup(group, ni = DisThreadedNetworkInterface.findIpv4Interface()); // utility function // You can join multiple groups here byte[] buffer = baos.toByteArray(); @@ -91,6 +96,7 @@ public class MulticastUdpSender // Put together an updated packet to send dos.writeChars("From " + System.getProperty("user.name") + ": "); dos.writeChars("MulticastSender packet " + Integer.toString(index) + ";"); // string chars for readability + // semicolon as message terminator prior to numbers dos.writeInt (index); // arbitrary data, needs Java or byte-alignment to read dos.writeFloat(17.0f); // arbitrary data, needs Java or byte-alignment to read dos.writeFloat(23.0f); // arbitrary data, needs Java or byte-alignment to read diff --git a/examples/src/overview.html b/examples/src/overview.html index 6934f6486fdc55ff3e6da9d143d70624290f00d9..3e6b58ffaf0088e568d179b0164a8c037772d289 100644 --- a/examples/src/overview.html +++ b/examples/src/overview.html @@ -5,7 +5,7 @@ <h1> Course Resources </h1> <p> <!-- Note that javadoc throws an incorrect error regarding title attribute, but resulting HTML works as expected --> - <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/README.md" target="_blank" title="Open-Dis Surfer Dude, Thanks Don McGregor!"><img src="OpenDisSurferDude.png" alt="Open-Dis Surfer Dude, Thanks Don McGregor!" style="float:right"/></a> + <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/README.md" target="_blank"><img src="OpenDisSurferDude.png" alt="Open-Dis Surfer Dude, Thanks Don McGregor!" style="float:right"/></a> <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/assignments" target="_blank">Assignments</a>, <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/examples" target="_blank">examples</a>, and <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/tree/master/presentations" target="_blank">presentations</a> diff --git a/presentations/08_DIS_DistributedInteractiveSimulationProtocol.pptx b/presentations/08a_DIS_DistributedInteractiveSimulationProtocol.pptx similarity index 100% rename from presentations/08_DIS_DistributedInteractiveSimulationProtocol.pptx rename to presentations/08a_DIS_DistributedInteractiveSimulationProtocol.pptx diff --git a/presentations/08b_DIS_Tutorial_redirect.html b/presentations/08b_DIS_Tutorial_redirect.html new file mode 100644 index 0000000000000000000000000000000000000000..6cbe0cd314c842c2c631f1901069d0cb9830e18d --- /dev/null +++ b/presentations/08b_DIS_Tutorial_redirect.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> + <!-- If you are seeing this source HTML, please go to the link below! --> + <head> + <meta http-equiv="Content-Style-Type" content="text/html"> + <title>08b_DIS_DistributedInteractiveSimulationTutorial redirect</title> + <meta http-equiv="refresh" content="0; url=https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/conferences/IITSEC2021/README.md"> + </head> + <body> + <p> + Go to the + <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/conferences/IITSEC2021/README.md">Distributed Interactive Simulation (DIS) 101 Tutorial: The Basics</a> + page... + </p> + </body> +</html> \ No newline at end of file diff --git a/presentations/08b_DIS_Tutorial_redirect.md b/presentations/08b_DIS_Tutorial_redirect.md new file mode 100644 index 0000000000000000000000000000000000000000..7dc0910e1aeebc269b206e05d8982b2f44b13bee --- /dev/null +++ b/presentations/08b_DIS_Tutorial_redirect.md @@ -0,0 +1,6 @@ +<!-- https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/presentations/08b_DIS_Tutorial_redirect.md --> + +## DIS Tutorial Redirect + +Please go to +[Distributed Interactive Simulation (DIS) 101 Tutorial: The Basics](https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/conferences/IITSEC2021/README.md)