diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC1_MCAST_PduSender.java b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC1_MCAST_PduSender.java new file mode 100755 index 0000000000000000000000000000000000000000..271379d5792767c9dab8525d8e62c8bb02f7ab31 --- /dev/null +++ b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC1_MCAST_PduSender.java @@ -0,0 +1,116 @@ +package MV3500Cohort2019JulySeptember.projects.BrennenstuhlKnobelochMcCann; + +import java.io.*; +import java.net.*; +import java.util.*; + +import edu.nps.moves.dis7.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class BRE_KNO_MCC_PC1_MCAST_PduSender +{ + + public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3"; + public static final int DEFAULT_MULTICAST_PORT = 2342; + + static boolean keepRunning = true; + int senderIntervall = 0; + + public void run(int numbOfPDUS) + { + System.out.println("BRE_KNO_MCC_PC1_MCAST_PduSender started..."); + System.out.println("Generate PDUs and note issues, if any..."); + + + while (keepRunning){ + List<Pdu> generatedPdusList = createPDU(numbOfPDUS, senderIntervall); + + // Send the PDUs we created + System.out.println("Send the " + generatedPdusList.size() + " PDUs we created..."); + + try + { + InetAddress localMulticastAddress = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS); + MulticastSocket socket = new MulticastSocket(DEFAULT_MULTICAST_PORT); + socket.joinGroup(localMulticastAddress); + + for (int idx = 0; idx < generatedPdusList.size(); idx++) + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + byte[] buffer; + + Pdu aPdu = generatedPdusList.get(idx); + try + { + aPdu.marshal(dos); + } + catch (Exception ex) + { + Logger.getLogger(BRE_KNO_MCC_PC1_MCAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + + buffer = baos.toByteArray(); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, localMulticastAddress, DEFAULT_MULTICAST_PORT); + socket.send(packet); + try + { + Thread.sleep(100L); + } + catch (InterruptedException ex) + { + } + } + } + catch (IOException e) + { + System.out.println(e); + } + + senderIntervall++; + try + { + Thread.sleep(2000); + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC1_MCAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + public static void main(String args[]) + { + BRE_KNO_MCC_PC1_MCAST_PduSender sender = new BRE_KNO_MCC_PC1_MCAST_PduSender(); + sender.run(5); + } + + private List<Pdu> createPDU(int numbOfPDUs, int intervall) + { + List<Pdu> list = new ArrayList(); + + for (int i = 0; i < numbOfPDUs; i++) + { + CommentPdu newCommentPdu = new CommentPdu(); + ArrayList<VariableDatum> payloadList = new ArrayList<VariableDatum>(); + + ArrayList<String> commentsList = new ArrayList<>(); + newCommentPdu.setTimestamp((intervall * 5) + i ); + commentsList.add("Chuck Norris is comming to town! " + " Warning " + newCommentPdu.getTimestamp()); + + for (String comment : commentsList) + { + VariableDatum newVariableDatum = new VariableDatum(); + newVariableDatum.setVariableDatumValue(comment.getBytes()); + payloadList.add(newVariableDatum); + } + newCommentPdu.setVariableDatums(payloadList); + + Pdu aPdu = newCommentPdu; + list.add(aPdu); + } + + return list; + } +} diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_Controller.java b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_Controller.java new file mode 100644 index 0000000000000000000000000000000000000000..e1fe5cbfe32afa4a5aad588a49ac44a028daea7c --- /dev/null +++ b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_Controller.java @@ -0,0 +1,77 @@ +package MV3500Cohort2019JulySeptember.projects.BrennenstuhlKnobelochMcCann; + +import edu.nps.moves.dis7.Pdu; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class BRE_KNO_MCC_PC2_Controller +{ + + static boolean keepRunningMainThread = true; + static BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver pc2_pc1_receiver; + static BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender pc2_pc3_sender; + static BRE_KNO_MCC_PC2_PC3_UNICAST_PduReceiver pc2_pc3_receiver; + + static InetAddress mcastIPPC1; + static InetAddress ipPC3; + static int portPC1; + static int portPC3; + + public static void main(String[] args) throws UnknownHostException + { + mcastIPPC1 = InetAddress.getByName("239.1.2.3"); + portPC1 = 2342; + ipPC3 = InetAddress.getByName("172.20.156.94"); + portPC3 = 2343; + + pc2_pc1_receiver = new BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver(); + pc2_pc1_receiver.resetMcastMessagesToSend(); + pc2_pc1_receiver.resetSavedMCASTMessagesList(); + pc2_pc1_receiver.setKeepRunning(true); //use this to terminate thread instead of killing it by hard + pc2_pc1_receiver.setNetworkData(mcastIPPC1, portPC1); + pc2_pc1_receiver.start(); + + pc2_pc3_sender = new BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender(); + pc2_pc3_sender.setNetworkSettinigs(ipPC3, portPC3); + pc2_pc3_sender.setKeepRunning(true); + + pc2_pc3_receiver = new BRE_KNO_MCC_PC2_PC3_UNICAST_PduReceiver(); + pc2_pc3_receiver.setNetworkSettings(2344); + pc2_pc3_receiver.setKeepRunning(true); + + + while (keepRunningMainThread) + { + List<Pdu> tempSet = pc2_pc1_receiver.getMCASTMessagesToSend(); + + if (!tempSet.isEmpty()) + { + if (!pc2_pc3_sender.isAlive()) + { + pc2_pc3_sender.start(); + } + pc2_pc3_sender.setListToSend(tempSet); + + if (!pc2_pc3_receiver.isAlive()) + { + pc2_pc3_receiver.start(); + } + } + + else + { + try + { + Thread.sleep(2000); + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_Controller.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + } +} diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.java b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..d61ca2c015f453bfb59b6b7f257471b6f5ca8f62 --- /dev/null +++ b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.java @@ -0,0 +1,160 @@ +package MV3500Cohort2019JulySeptember.projects.BrennenstuhlKnobelochMcCann; + +import com.sun.corba.se.impl.orbutil.concurrent.Mutex; +import java.net.*; +import java.io.*; + +import edu.nps.moves.dis7.*; +import edu.nps.moves.dis7.enumerations.*; +import edu.nps.moves.dis7.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver extends Thread +{ + + public static final boolean USE_FAST_ESPDU = false; + static List<Integer> savedMCASTMessages = new ArrayList(); + static List<Pdu> mcastMessagesToSend = new ArrayList(); + static Mutex mutex = new Mutex(); + static boolean keepRunning = false; + static boolean isRunning = false; + + PduFactory factory; + MulticastSocket socket; + InetAddress address; + DatagramPacket packet; + + public void run() + { + try + { + isRunning = true; + factory = new PduFactory(); + + while (keepRunning) + { + byte buffer[] = new byte[1500]; + packet = new DatagramPacket(buffer, buffer.length); + + socket.receive(packet); + + Pdu pdu = factory.createPdu(packet.getData()); + if (pdu != null && (pdu.getPduType() == DISPDUType.COMMENT)) + { + + if (!savedMCASTMessages.contains(pdu.getTimestamp())) + { + System.out.println("BRE_KNO_MCC_PC1_MCAST received Massage."); + savedMCASTMessages.add(pdu.getTimestamp()); + + try + { + mutex.acquire(); + System.out.println("PC2 - PC1 received: Internal ID " + pdu.getTimestamp() + " added."); + mcastMessagesToSend.add(pdu); + mutex.release(); + + System.out.println("Added to SendList and saved in archiv."); + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + } + else + { + System.out.println("BRE_KNO_MCC_PC1_MCAST received Massage. Is already in list. Nothing added to SendList."); + } + + } + else + { + System.out.println("received packet but pdu is null or not a PDU from type COMMENT"); + } + } + } + catch (IOException e) + { + System.out.println("Problem with BRE_KNO_MCC_PC1_MCAST_PduReceiver, see exception trace:"); + System.out.println(e); + } + finally + { + System.out.println("BRE_KNO_MCC_PC1_MCAST_PduReceiver complete."); + } + + isRunning = false; + } + + public boolean isRunning() + { + return isRunning; + } + + public void setNetworkData(InetAddress addr, int port) + { + try + { + address = addr; + socket = new MulticastSocket(port); + socket.joinGroup(address); + } + catch (IOException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public void setKeepRunning(boolean k) + { + keepRunning = k; + } + + public void resetSavedMCASTMessagesList() + { + try + { + mutex.acquire(); + savedMCASTMessages.clear(); + mutex.release(); + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public void resetMcastMessagesToSend() + { + try + { + mutex.acquire(); + mcastMessagesToSend.clear(); + mutex.release(); + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public List<Pdu> getMCASTMessagesToSend() + { + List<Pdu> temp = null; + try + { + mutex.acquire(); + temp = new ArrayList(mcastMessagesToSend); + mcastMessagesToSend.clear(); + mutex.release(); + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC1_MCAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + return temp; + } +} diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC3_UNICAST_PduReceiver.java b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC3_UNICAST_PduReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..a0dffe5c75e42284e0b4bcf856d652b118b2d92d --- /dev/null +++ b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC3_UNICAST_PduReceiver.java @@ -0,0 +1,60 @@ +package MV3500Cohort2019JulySeptember.projects.BrennenstuhlKnobelochMcCann; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.SocketException; + +public class BRE_KNO_MCC_PC2_PC3_UNICAST_PduReceiver extends Thread +{ + + static boolean keepRunning = false; + static boolean isRunning = false; + + static int portPC3; + + public void run() + { + isRunning = true; + + try (DatagramSocket socket = new DatagramSocket(portPC3)) + { + + byte[] buffer = new byte[65507]; + + socket.setSoTimeout(30000); + + while (true) + { + DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length); + + socket.receive(datagramPacket); + + String receivedMessage = new String(datagramPacket.getData()); + System.out.println(receivedMessage); + } + } + catch (SocketException e) + { + isRunning = false; + e.printStackTrace(); + } + catch (IOException e) + { + isRunning = false; + System.out.println("Timeout. Client is closing."); + } + } + + public boolean getIsRunning(){ + return isRunning; + } + + public void setNetworkSettings(int port){ + portPC3 = port; + } + + public void setKeepRunning(boolean k){ + keepRunning = k; + } +} diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.java b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.java new file mode 100755 index 0000000000000000000000000000000000000000..53c4a670c5203662d755429bb4a9806f5a5594d9 --- /dev/null +++ b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.java @@ -0,0 +1,128 @@ +package MV3500Cohort2019JulySeptember.projects.BrennenstuhlKnobelochMcCann; + +import com.sun.corba.se.impl.orbutil.concurrent.Mutex; +import java.util.*; + +import edu.nps.moves.dis7.*; +import edu.nps.moves.dis7.enumerations.DISPDUType; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender extends Thread +{ + static Mutex mutex = new Mutex(); + static List<Pdu> messagesToSend = new ArrayList(); + static boolean keepRunning = false; + static boolean isRunning = false; + + static InetAddress pc3IP; + static int portPC3; + + public void run() + { + try + { + isRunning = true; + DatagramSocket socket = new DatagramSocket(portPC3); + + while (keepRunning) + { + try + { + mutex.acquire(); + if (!messagesToSend.isEmpty()) + { + Pdu tempPdu = messagesToSend.get(0); + messagesToSend.remove(messagesToSend.get(0)); + mutex.release(); + + if (tempPdu.getPduType() != DISPDUType.COMMENT) + { + System.out.println("Received Message Is Not A CommentPDU. Skiped."); + } + else + { + //Sending via UNICAST + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + byte[] buffer; + + try + { + tempPdu.marshal(dos); + } + catch (Exception ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + buffer = baos.toByteArray(); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, pc3IP, portPC3); + + try + { + socket.send(packet); + } + catch (IOException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + else + { + mutex.release(); + } + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + catch (SocketException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public void setNetworkSettinigs(InetAddress address, int port) + { + pc3IP = address; + portPC3 = port; + } + + public boolean getIsRunning() + { + return isRunning; + } + + public void setKeepRunning(boolean k) + { + keepRunning = k; + } + + public void setListToSend(List<Pdu> pduSetToSend) + { + try + { + mutex.acquire(); + while (!pduSetToSend.isEmpty()) + { + messagesToSend.add(pduSetToSend.get(0)); + pduSetToSend.remove(0); + } + mutex.release(); + } + catch (InterruptedException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + } +} diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.java b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..de2f52bf8fd7472793f92314d95cc7e05434d448 --- /dev/null +++ b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.java @@ -0,0 +1,168 @@ +package MV3500Cohort2019JulySeptember.projects.BrennenstuhlKnobelochMcCann; + +import java.net.*; +import java.io.*; + +import edu.nps.moves.dis7.*; +import edu.nps.moves.dis7.util.PduFactory; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver +{ + + static boolean keepRunning = true; + static boolean isRunning = false; + + static int portPC3; + static InetAddress ipPC2; + static DatagramSocket socket; + + public static void main(String[] args) + { + + portPC3 = 2343; + try + { + ipPC2 = InetAddress.getByName("172.20.148.181"); + } + catch (UnknownHostException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + + run(); + } + + public static void run() + { + isRunning = true; + byte[] buffer = new byte[65507]; + + try + { + DatagramSocket clientSocket = new DatagramSocket(portPC3); + socket = new DatagramSocket(2344); + + while (keepRunning) + { + DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length); + + try + { + System.out.println("waiting for receiving message..."); + clientSocket.receive(datagramPacket); + System.out.println("Message received."); + + PduFactory factory = new PduFactory(); + + Pdu tempPdu = factory.createPdu(datagramPacket.getData()); + StringBuilder message = new StringBuilder(); + message.append("Pdu type: "); + message.append(tempPdu.getPduType()); + message.append(" Internal ID: "); + message.append(tempPdu.getTimestamp()); + message.append(" "); + + //extract comments + CommentPdu commentPdu = (CommentPdu) tempPdu; // cast to precise type + ArrayList<VariableDatum> payloadList = (ArrayList) commentPdu.getVariableDatums(); + + for (VariableDatum variableDatum : payloadList) + { + String nextComment = new String(variableDatum.getVariableDatumValue()); // convert byte[] to String + message.append(nextComment); + } + + System.out.println(message); + + sendAnswerUNICASTtoPC2(tempPdu.getTimestamp()); + sendMCASTOver3000(tempPdu); + + } + catch (IOException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + catch (SocketException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public boolean isRunning() + { + return isRunning; + } + + public void setKeepRunning(boolean k) + { + keepRunning = k; + } + + static void sendAnswerUNICASTtoPC2(int internID) + { + //Sending via UNICAST + + String message = ("PC3: Packet with InternID " + internID + " received."); + DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), ipPC2, 2344); + try + { + socket.send(packet); + } + catch (IOException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC2_PC3_UNICAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + } + + static void sendMCASTOver3000(Pdu tempPdu) + { + InetAddress localMulticastAddress = null; + try + { + localMulticastAddress = InetAddress.getByName("239.1.2.3"); + } + catch (UnknownHostException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + byte[] buffer; + + try + { + tempPdu.marshal(dos); + } + catch (Exception ex) + { + Logger.getLogger(BRE_KNO_MCC_PC1_MCAST_PduSender.class.getName()).log(Level.SEVERE, null, ex); + } + + buffer = baos.toByteArray(); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, localMulticastAddress, 3000); + MulticastSocket socket; + try + { + socket = new MulticastSocket(3000); + socket.joinGroup(localMulticastAddress); + socket.send(packet); + } + catch (IOException ex) + { + Logger.getLogger(BRE_KNO_MCC_PC3_PC2_UNICAST_PduReceiver.class.getName()).log(Level.SEVERE, null, ex); + } + try + { + Thread.sleep(100L); + } + catch (InterruptedException ex) + { + } + } +} diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Final Presentation.pptx b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Final Presentation.pptx new file mode 100644 index 0000000000000000000000000000000000000000..30a7da0988c7f9bbe0f6a893376d51df93513c62 Binary files /dev/null and b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Final Presentation.pptx differ diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Readme.docx b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Readme.docx new file mode 100644 index 0000000000000000000000000000000000000000..0ee16b9a1355dd0e520e2616e771637c5ad8ada0 Binary files /dev/null and b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Readme.docx differ diff --git a/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Readme.pdf b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Readme.pdf new file mode 100644 index 0000000000000000000000000000000000000000..be3e29d6c1eaafb14b2fa9563bb006b811cacb34 Binary files /dev/null and b/assignments/src/MV3500Cohort2019JulySeptember/projects/BrennenstuhlKnobelochMcCann/Readme.pdf differ