diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/README.md deleted file mode 100644 index 7d4497eba49fb1f84703d5d52a046afda8c3019b..0000000000000000000000000000000000000000 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/README.md +++ /dev/null @@ -1,44 +0,0 @@ -## Homework 3: Example Simulation Recording using OpenDIS Network Streams - -<!-- Viewable at https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/assignments/src/MV3500Cohort2024JulySeptember/homework3/README.md --> - -### Description - -Using the [OpenDIS ExampleSimulationProgram](../../../../../examples/src/OpenDis7Examples/ExampleSimulationProgram.java) and implement a simple DES. -In the DES a SimpleMover and a SimplePathMoverManager are used. The SimpleMover is moving along a given path. -The SimpleMover is modified in this way, that every time if the movement is changed an ESPDU is sent via DisChannel, but at least every 5 seconds with the current position. - -### Assignment - -1. Adapt the functionality for [OpenDIS ExampleSimulationProgram](../../../../examples/src/OpenDis7Examples/ExampleSimulationProgram.java), modifying provided code -2. Experiment with the enumeration values that set up each entity and PDU. What works for you? What makes sense for your future work? -3. Adapt or replace the UML diagrams to describe what you have going on. -4. Record, save and replay your result stream using [PduRecorder](https://savage.nps.edu/opendis7-java/javadoc/edu/nps/moves/dis7/utilities/stream/PduRecorder.html) or [Wireshark](https://www.wireshark.org) - * see local [assignments/src/pduLog](../../../pduLog) subdirectory for latest opendis log files - * Coming soon, we will also (again have) [X3D-Edit](https://savage.nps.edu/X3D-Edit) for DIS stream recording/replay -5. Observe good-practice conventions in the [assignments README](../../../README.md) and [current-course README](../README.md) instructions. - -This assignment presents a Problem Prototyping opportunity. -While some minimal functionality is expected, the general outline of -a networking problem and proposed solution holds great interest. -Think of it as warmup preparation for your future work. - -This is also a freeplay opportunity. -You have the option to pick one or more of the provided course example programs -and adapt the source to demonstrate a new client-server handshake protocol of interest. - -Be sure to provide a rationale that justifies why the networking choices you made -(TCP/UDP, unicast/multicast, etc.) are the best for the problem you are addressing. - -You may find that the prior [homework2 README](../homework2/README.md) still provides -helpful details on what specific deliverables are expected in each homework assignment. - -Team efforts are encouraged, though if you choose a team approach be sure to justify why. -This is a good warmup prior to final projects. Have fun with Java networking! - -### Prior Assignment, August 2019 - -In 2019, students worked together on a single project to check wireless multicast connectivity recently deployed on NPS campus. - -See their experimental results in the [NPS Multicast Connectivity Report](../../MV3500Cohort2019JulySeptember/homework3). - diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SchnitzlerSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SchnitzlerSimulationProgram.java deleted file mode 100644 index cfb786ec308e46b7c8a27ed269a6dbf8c45b88fc..0000000000000000000000000000000000000000 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SchnitzlerSimulationProgram.java +++ /dev/null @@ -1,357 +0,0 @@ -/** - * 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 for the original dis part - * @author simonschnitzler for the simulation part - */ -package MV3500Cohort2024JulySeptember.homework3.Schnitzler; - -import edu.nps.moves.dis7.pdus.*; -import edu.nps.moves.dis7.utilities.DisChannel; -import edu.nps.moves.dis7.utilities.PduFactory; -import java.awt.geom.Point2D; -import java.time.LocalDateTime; -import java.util.logging.Level; -import java.util.logging.Logger; -import simkit.Schedule; -import simkit.util.SimplePropertyDumper; - -/** 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 SchnitzlerSimulationProgram -{ - /* **************************** 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 = 20; - - 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 SchnitzlerSimulationProgram() - { - initialize(); - } - /** - * Constructor to create an instance of this class. - * @param newDescriptor describes this program, useful for logging and debugging - */ - public SchnitzlerSimulationProgram(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 SchnitzlerSimulationProgram(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 - } - - /** - * Set up the DES. A single SimpleMoverOpenDis7 starting at (0.0,0.0) - * with a maximum speed of 30.0 and the following - * waypoints:<br>(20.0,100.0),<br>(80.0,10.0),<br>(140.0,150.0) - */ - private void initializeSimulation(){ - Point2D startingPoint = new Point2D.Double(0.0,0.0); - double maxSpeed = 30.0; - SimpleMoverOpenDis7 simpleMover = new SimpleMoverOpenDis7(startingPoint, maxSpeed, disChannel); - simpleMover.setName("Fred"); - - Point2D[] path = new Point2D[]{new Point2D.Double(20.0,100.0), - new Point2D.Double(80.0,10.0),new Point2D.Double(140.0,150.0)}; - - SimplePathMoverManagerOpenDis7 simplePathMoverManager = new SimplePathMoverManagerOpenDis7(path,true); - - simplePathMoverManager.addSimEventListener(simpleMover); - simpleMover.addSimEventListener(simplePathMoverManager); - - SimplePropertyDumper simplePropertyDumper = new SimplePropertyDumper(); - simplePathMoverManager.addPropertyChangeListener(simplePropertyDumper); - simpleMover.addPropertyChangeListener(simplePropertyDumper); - simplePropertyDumper.setDumpSource(true); - - System.out.println(simpleMover); - System.out.println(simplePathMoverManager); - - Schedule.setVerbose(true); - Schedule.reset(); - Schedule.setPauseAfterEachEvent(true); - - } - - /** - * 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 - { - int simulationLoopCount = 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 - - initializeSimulation(); - - while (simulationLoopCount < 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! ***************************************************** - // ============================================================================================= - - double simTime = Schedule.getSimTime(); - while(simTime < simulationLoopCount * getSimulationTimeStepDuration()){ - Schedule.startSimulation(); - simTime = Schedule.getSimTime(); - } - - - // 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]"); - - - // =============================== - // 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(SchnitzlerSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex); - } - - } - - /** - * 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 SchnitzlerSimulationProgram 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 SchnitzlerSimulationProgram("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/Schnitzler/SimpleMoverOpenDis7.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SimpleMoverOpenDis7.java deleted file mode 100644 index 7b5a9f439a5b4f8b83201a230057eada3fe4dd6b..0000000000000000000000000000000000000000 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SimpleMoverOpenDis7.java +++ /dev/null @@ -1,403 +0,0 @@ -package MV3500Cohort2024JulySeptember.homework3.Schnitzler; - -import edu.nps.moves.dis7.entities.deu.platform.land.Leopard2A7PLUS; -import edu.nps.moves.dis7.enumerations.ForceID; -import edu.nps.moves.dis7.pdus.EntityID; -import edu.nps.moves.dis7.pdus.EntityStatePdu; -import edu.nps.moves.dis7.pdus.Vector3Float; -import edu.nps.moves.dis7.utilities.DisChannel; -import edu.nps.moves.dis7.utilities.PduFactory; -import java.awt.geom.Point2D; -import static java.lang.Double.NaN; -import simkit.Schedule; -import simkit.SimEntityBase; - -/** - * Represent a unit that moves with constant velocity. Its responsibilities are - * to maintain its state and respond to events directing it to perform only - * maneuver, specifically to move to a given waypoint at its maximum speed. - * - * @author simonschnitzler - */ -public class SimpleMoverOpenDis7 extends SimEntityBase { - - /** max time between two ESPDUs */ - public static final double HEARTBEATTIME = 5.0; - - /** 2D Vector with NaN as values */ - public static final Point2D NaP = new Point2D.Double(NaN, NaN); - - private Point2D initialLocation; - private double maxSpeed; - - /** Dis extension */ - private DisChannel disChannel; - - /** last stop location of the simpleMover */ - protected Point2D lastStopLocation; - /** current velocity of the mover */ - protected Point2D velocity; - /** current destination of the simpleMover */ - protected Point2D destination; - /** start move time of the simpleMover */ - protected double startMoveTime; - - /** EntityID settings for simpleMover */ - private EntityID entityID = new EntityID(); - - /** ESPDU for simpleMover */ - private EntityStatePdu entityStatePdu; - - /** PduFactory */ - private PduFactory pduFactory; - - - - - /** - * Instantiate lastStopLocation, velocity, and destination as NaP each - */ - public SimpleMoverOpenDis7() { - lastStopLocation = (Point2D) NaP.clone(); - velocity = (Point2D) NaP.clone(); - destination = (Point2D) NaP.clone(); - } - - /** - * Instantiate a new SimpleMover with the given initialLocation and - * maxSpeed. - * - * @param initialLocation Given initial location of this mover - * @param maxSpeed Given maximum speed of mover - */ - public SimpleMoverOpenDis7(Point2D initialLocation, double maxSpeed) { - this(); - setInitialLocation(initialLocation); - setMaxSpeed(maxSpeed); - } - - /** - * Instantiate a new SimpleMover with the given initialLocation and - * maxSpeed. - * - * @param initialLocation Given initial location of this mover - * @param maxSpeed Given maximum speed of mover - * @param disChannel Given DisChannel to use for send ESPDU - */ - public SimpleMoverOpenDis7(Point2D initialLocation, double maxSpeed, DisChannel disChannel) { - this(initialLocation, maxSpeed); - setDisChannel(disChannel); - initializeEntity(); - } - - /** - * Initialize simulation entity for the simpleMover. - */ - private void initializeEntity(){ - if (pduFactory == null) - pduFactory = disChannel.getPduFactory(); - entityStatePdu = pduFactory.makeEntityStatePdu(); - - // 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.setSiteID(1).setApplicationID(2).setEntityID(3);// made-up example ID; - disChannel.addEntity(entityID); - - - entityStatePdu.setEntityID(entityID); - entityStatePdu.setForceId(ForceID.FRIENDLY); - entityStatePdu.setEntityType(new Leopard2A7PLUS()); - entityStatePdu.setMarking("Mover #1"); - entityStatePdu.getMarkingString(); // use Netbeans Debug breakpoint here to check left justified... - } - - private void sendESPDU(){ - Point2D currentLocation = getCurrentLocation(); - entityStatePdu.getEntityLocation().setX(currentLocation.getX()); - entityStatePdu.getEntityLocation().setY(currentLocation.getY()); - entityStatePdu.getEntityLocation().setZ(0.0); - Point2D currentVelocity = getVelocity(); - Vector3Float currentVelocityFloat = new Vector3Float(); - currentVelocityFloat.setX((float)currentVelocity.getX()); - currentVelocityFloat.setY((float)currentVelocity.getY()); - currentVelocityFloat.setZ(0.0f); - entityStatePdu.setEntityLinearVelocity(currentVelocityFloat); - entityStatePdu.setTimestampSeconds(Schedule.getSimTime()); - - disChannel.sendSinglePdu(entityStatePdu); - } - - /** - * Set lastStopLocation to initialLocation<br> - * set velocity to (0,0)<br> - * set destination to NaP<br> - * set startMoveTime to the current SimTime - */ - @Override - public void reset() { - super.reset(); - lastStopLocation.setLocation(getInitialLocation()); - velocity.setLocation(0.0, 0.0); - destination.setLocation(NaP); - startMoveTime = Schedule.getSimTime(); - } - - /** - * Fire property changes for all state variables with the initial values. - */ - public void doRun() { - firePropertyChange("lastStopLocation", getLastStopLocation()); - firePropertyChange("velocity", getVelocity()); - firePropertyChange("destination", getDestination()); - firePropertyChange("startMoveTime", getStartMoveTime()); - - sendESPDU(); - waitDelay("HeartBeat", HEARTBEATTIME, this); - } - - /** - * If no changes happen, a heartbeat is send. - * - * @param mover which is meant to send a heartbeat - */ - public void doHeartBeat(SimpleMoverOpenDis7 mover){ - sendESPDU(); - - waitDelay("HeartBeat", HEARTBEATTIME, mover); - } - - /** - * set destination to the given destination and firePropertyChange<br> - * schedule StartMove(this) if the distance to the destination is greater - * than 0.0 - * - * @param destination the new destination for the mover - */ - public void doMoveTo(Point2D destination) { - Point2D oldDestination = getDestination(); - this.destination.setLocation(destination); - firePropertyChange("destination", oldDestination, getDestination()); - - if (lastStopLocation.distance(destination) > 0.0) { - waitDelay("StartMove", 0.0, this); - } - } - - /** - * Compute the distance to the destination <br> - * compute the moveTime to destination <br> - * compute velocity with maxSpeed and direction to the destination <br> - * set startMoveTime to the current SimTime <br> - * Schedule an EndMove event with the given mover as parameter and the delay - * of the computed moveTime - * - * @param mover instance which starts its move - */ - public void doStartMove(SimpleMoverOpenDis7 mover) { - double distance = lastStopLocation.distance(destination); - double moveTime = distance / getMaxSpeed(); - - Point2D oldVelocity = getVelocity(); - this.velocity.setLocation((destination.getX() - lastStopLocation.getX()) / moveTime, - (destination.getY() - lastStopLocation.getY()) / moveTime); - firePropertyChange("velocity", oldVelocity, getVelocity()); - - double oldStartMoveTime = getStartMoveTime(); - startMoveTime = Schedule.getSimTime(); - firePropertyChange("startMoveTime", oldStartMoveTime, getStartMoveTime()); - - waitDelay("EndMove", moveTime, mover); - - interrupt("HeartBeat", mover); - sendESPDU(); - waitDelay("HeartBeat", HEARTBEATTIME, mover); - - } - - /** - * Set lastStopLocation to the destination<br> - * set velocity to 0.0<br> - * set destination to NaP - * - * @param mover instance which ends its move - */ - public void doEndMove(SimpleMoverOpenDis7 mover) { - Point2D oldLastStopLocation = getLastStopLocation(); - lastStopLocation.setLocation(getDestination()); - firePropertyChange("lastStopLocation", oldLastStopLocation, getLastStopLocation()); - - Point2D oldVelocity = getVelocity(); - velocity.setLocation(0.0, 0.0); - firePropertyChange("velocity", oldVelocity, getVelocity()); - - Point2D oldDestination = getDestination(); - destination.setLocation(NaP); - firePropertyChange("destination", oldDestination, getDestination()); - - interrupt("HeartBeat", mover); - sendESPDU(); - waitDelay("HeartBeat", HEARTBEATTIME, mover); - } - - /** - * Schedule an OrderStop event with this mover instance as parameter and a - * delay of 0.0 - */ - public void doOrderStop() { - waitDelay("Stop", 0.0, this); - } - - /** - * Set lastStopLocation to the currentLocation<br> - * set startMoveTime to the current SimTime<br> - * set velocity to 0.0<br> - * cancel the EndMove event for the given mover instance - * - * @param mover instance which stops its move - */ - public void doStop(SimpleMoverOpenDis7 mover){ - Point2D oldLastStopLocation = getLastStopLocation(); - lastStopLocation.setLocation(getCurrentLocation()); - firePropertyChange("lastStopLocation", oldLastStopLocation, getLastStopLocation()); - - double oldStartMoveTime = getStartMoveTime(); - startMoveTime = Schedule.getSimTime(); - firePropertyChange("startMoveTime", oldStartMoveTime, getStartMoveTime()); - - Point2D oldVelocity = getVelocity(); - velocity.setLocation(0.0, 0.0); - firePropertyChange("velocity", oldVelocity, getVelocity()); - - interrupt("EndMove",mover); - - interrupt("HeartBeat", mover); - sendESPDU(); - waitDelay("HeartBeat", HEARTBEATTIME, mover); - } - - /** - * Return current location. - * - * @return this mover's current location based on linear equation of motion - */ - public Point2D getCurrentLocation() { - double elapsedTime = Schedule.getSimTime() - getStartMoveTime(); - return new Point2D.Double(lastStopLocation.getX() + elapsedTime * velocity.getX(), - lastStopLocation.getY() + elapsedTime * velocity.getY()); - } - - /** - * Return initial location. - * @return initialLocation - */ - public Point2D getInitialLocation() { - return (Point2D) initialLocation.clone(); - } - - /** - * Set initial Location - * - * @param initialLocation initial location of the mover. - */ - public void setInitialLocation(Point2D initialLocation) { - this.initialLocation = (Point2D) initialLocation.clone(); - } - - /** - * Get max speed. - * - * @return maxSpeed of the mover. - */ - public double getMaxSpeed() { - return maxSpeed; - } - - /** - * Set max speed - * - * @param maxSpeed of the mover. - * @throws IllegalArgumentException if the speed is negative. - */ - public void setMaxSpeed(double maxSpeed) { - if (maxSpeed < 0.0) { - throw new IllegalArgumentException("maxSpeed must be >= 0.0: " + maxSpeed); - } - this.maxSpeed = maxSpeed; - } - - /** - * Get last stop location. - * - * @return lastStopLocation of the mover. - */ - public Point2D getLastStopLocation() { - return (Point2D) lastStopLocation.clone(); - } - - /** - * Get velocity. - * - * @return velocity of the mover. - */ - public Point2D getVelocity() { - return (Point2D) velocity.clone(); - } - - /** - * Get destination. - * - * @return destination of the mover. - */ - public Point2D getDestination() { - return (Point2D) destination.clone(); - } - - /** - * Get start move time. - * - * @return startMoveTime time since the last StartMove event. - */ - public double getStartMoveTime() { - return startMoveTime; - } - - /** - * Get dis channel. - * - * @return disChannel of the simulation. - */ - public DisChannel getDisChannel() { - return disChannel; - } - - - /** - * Set DisChannel. - * - * @param disChannel of the simulation. - * @throws IllegalArgumentException if the disChannel is null. - */ - public void setDisChannel(DisChannel disChannel) { - if (disChannel == null) { - throw new IllegalArgumentException("disChannel is: " + disChannel); - } - this.disChannel = disChannel; - } - - /** - * Override normal toString() to return current location and velocity - * - * @return Name (current location, current velocity) - */ - @Override - public String toString() { - Point2D currentLocation = getCurrentLocation(); - return String.format("%s (%,.3f, %,.3f) [%,.3f, %,.3f]", getName(), - currentLocation.getX(), currentLocation.getY(), - velocity.getX(), velocity.getY()); - } - -} diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SimplePathMoverManagerOpenDis7.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SimplePathMoverManagerOpenDis7.java deleted file mode 100644 index 3860affbdfed615d1fdd0ae130276e1edfa77332..0000000000000000000000000000000000000000 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/SimplePathMoverManagerOpenDis7.java +++ /dev/null @@ -1,175 +0,0 @@ -package MV3500Cohort2024JulySeptember.homework3.Schnitzler; - -import java.awt.geom.Point2D; -import simkit.SimEntityBase; - -/** - * Represent a move manager. Each instance of SimplePathMoverManager will - * control a single SimpleMover, directing it along a pre-determined list of - * waypoints (Point2D instances). This component has only one state variable - * next. - * - * @author simonschnitzler - */ -public class SimplePathMoverManagerOpenDis7 extends SimEntityBase { - - private Point2D[] path; - private boolean startOnRun; - - /** next waypoint index */ - protected int nextWaypointIndex; - - /** - * Zero-argument constructor - */ - public SimplePathMoverManagerOpenDis7() { - } - - /** - * Instantiate with given parameters - * - * @param path given path - * @param startOnRun if startOnRun is true, start from Run event - */ - public SimplePathMoverManagerOpenDis7(Point2D[] path, boolean startOnRun) { - this(); - setPath(path); - setStartOnRun(startOnRun); - } - - /** - * Set nextWaypointIndex to the initial value 0; - */ - @Override - public void reset() { - super.reset(); - nextWaypointIndex = 0; - } - - /** - * Fire property change for the state variable nextWaypointIndex<br> - * If startOnRun is true schedule a MoveTo event with the waypoint at index - * nextWaypointIndex as parameter and with a delay of 0.0. - */ - public void doRun() { - firePropertyChange("nextWaypointIndex", getNextWaypointIndex()); - - if (isStartOnRun()) { - waitDelay("MoveTo", 0.0, getPath(getNextWaypointIndex())); - } - } - - /** - * Does nothing - meant to be "heard" by another component - * - * @param waypoint which is the next destination - */ - public void doMoveTo(Point2D waypoint) { - } - - /** - * Add 1 to the nextWaypointIndex and fire a property change<br> - * If the new nextWaypointIndex is less than the length of the path, then - * schedule a MoveTo event with a delay of 0.0 and the waypoint at the index - * of the new nextWaypointIndex as parameter.<br> - * If the new nextWaypointIndex is equal to the length of the path, then - * schedule a Stop event with a delay of 0.0 - * - * @param mover which ends its move - */ - public void doEndMove(SimpleMoverOpenDis7 mover) { - int oldNextWaypointIndex = getNextWaypointIndex(); - nextWaypointIndex += 1; - firePropertyChange("nextWaypointIndex", oldNextWaypointIndex, getNextWaypointIndex()); - - if (getNextWaypointIndex() < path.length) { - waitDelay("MoveTo", 0.0, getPath(getNextWaypointIndex())); - } - if (getNextWaypointIndex() == path.length) { - waitDelay("Stop", 0.0); - } - } - - /** - * Schedule an OrderStop event with a delay of 0.0 - */ - public void doStop(){ - waitDelay("OrderStop",0.0); - } - - /** - * Does nothing - meant to be "heard" by another component - */ - public void doOrderStop(){ - } - - /** - * Get path. - * @return the path - */ - public Point2D[] getPath() { - return path.clone(); - } - - /** - * Get waypoint at given index of the path. - * - * @param index of the waypoint - * @return the waypoint of the path at the given index - */ - public Point2D getPath(int index) { - return (Point2D) path[index].clone(); - } - - /** - * Set the path. - * - * @param path the path to set - * @throws IllegalArgumentException if the path length is not greater than 0 - */ - public void setPath(Point2D[] path) { - if (path.length > 0) { - this.path = path.clone(); - } else { - throw new IllegalArgumentException("path must be at least lengt 1: " + path.length); - } - } - - /** - * Set the waypoint of the path at a given index. - * - * @param index of the waypoint to set - * @param path the waypoint of the path to set at the given index - */ - public void setPath(int index, Point2D path) { - this.path[index] = (Point2D) path.clone(); - } - - /** - * Get startOnRun Boolean. - * - * @return startOnRun - */ - public boolean isStartOnRun() { - return startOnRun; - } - - /** - * Set startOnRunBoolean. - * - * @param startOnRun boolean if should start from the beginning. - */ - public void setStartOnRun(boolean startOnRun) { - this.startOnRun = startOnRun; - } - - /** - * Get next waypoint index. - * - * @return nextWaypointIndex - */ - public int getNextWaypointIndex() { - return nextWaypointIndex; - } - -} diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/package-info.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/package-info.java deleted file mode 100644 index 308438e0b4c67ec9201b01020d7a30f345aed88f..0000000000000000000000000000000000000000 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Schnitzler/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/** - * 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.Schnitzler;