Skip to content
Snippets Groups Projects
Commit 7cb1a1b4 authored by Kens's avatar Kens
Browse files

Final project stuff for SasalaMaroon

parent 70e6b1ac
No related branches found
No related tags found
No related merge requests found
Showing
with 29627 additions and 0 deletions
// package edu.nps.moves.examples; // copy example from OpenDIS distribution, modify to serve as template
import java.io.*;
import java.net.*;
import java.util.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import edu.nps.moves.dis.*;
import edu.nps.moves.disutil.CoordinateConversions;
import edu.nps.moves.disutil.DisTime;
/**This file reads a .csv and send out ESPDUs based on each row of the .csv.
* This file uses Don McGregors original example of OpneDisEspduSender as the
* starting point for the file and was modified to read the .csv and send an
* espdu for each entry.
*
* modified for MV3500 final project by Brian Hanley
*
*
* Creates and sends ESPDUs in IEEE binary format.
*
* @author DMcG
*/
public class CSVreaderOpenDisEspduSenderFP
{
//public static final int NUMBER_TO_SEND = 5000;
public static final int SENDING_PORT = 1414;
public static final int RECEIVING_PORT = 1415;
public static final String DESTINATION_HOST = "localhost";
public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
/** Default multicast group address we send on */
public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
/** Default port we send on */
public static final int DIS_DESTINATION_PORT = 3000;
/** Possible system properties, passed in via -Dattr=val
* networkMode: unicast, broadcast, multicast
* destinationIp: where to send the packet. If in multicast mode, this can be multicast.
* To determine broadcast destination IP, use an online broadcast address
* calculator, for example http://www.remotemonitoringsystems.ca/broadcast.php
* If in multicast mode, a join() will be done on the multicast address.
* port: port used for both source and destination.
* @param args
*/
public static void main(String args[]) throws FileNotFoundException
{
/** an entity state pdu */
EntityStatePdu espdu = new EntityStatePdu();
//MulticastSocket socket = null; // must be initialized, even if null
DisTime disTime = DisTime.getInstance(); // TODO explain
int alternator = -1;
// ICBM coordinates for my office
double lat = 36.595517;
double lon = -121.877000;
// Default settings. These are used if no system properties are set.
// If system properties are passed in, these are over ridden.
int port = DIS_DESTINATION_PORT;
NetworkMode mode = NetworkMode.BROADCAST;
InetAddress destinationIp = null; // must be initialized, even if null
try
{
destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
}
catch(UnknownHostException e)
{
System.out.println(e + " Cannot create multicast address");
System.exit(0);
}
// All system properties, passed in on the command line via -Dattribute=value
Properties systemProperties = System.getProperties();
// IP address we send to
String destinationIpString = systemProperties.getProperty("destinationIp");
// Port we send to, and local port we open the socket on
String portString = systemProperties.getProperty("port");
// Network mode: unicast, multicast, broadcast
String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
// Set up a socket to send information
try
{
// Port we send to
if(portString != null)
port = Integer.parseInt(portString);
//socket = new MulticastSocket(port);
// Where we send packets to, the destination IP address
if(destinationIpString != null)
{
destinationIp = InetAddress.getByName(destinationIpString);
}
// Type of transport: unicast, broadcast, or multicast
// TODO convert to String constants
if(networkModeString != null)
{
if(networkModeString.equalsIgnoreCase("unicast"))
mode = NetworkMode.UNICAST;
else if(networkModeString.equalsIgnoreCase("broadcast"))
mode = NetworkMode.BROADCAST;
else if(networkModeString.equalsIgnoreCase("multicast"))
{
mode = NetworkMode.MULTICAST;
if(!destinationIp.isMulticastAddress())
{
throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
}
// socket.joinGroup(destinationIp);
}
} // end networkModeString
}
catch(IOException | RuntimeException e)
{
System.out.println("Unable to initialize networking. Exiting.");
System.out.println(e);
System.exit(-1);
}
// Initialize values in the Entity State PDU object. The exercise ID is
// a way to differentiate between different virtual worlds on one network.
// Note that some values (such as the PDU type and PDU family) are set
// automatically when you create the ESPDU.
espdu.setExerciseID((short)1);
// Marking espduMarking = new Marking();
// espduMarking.setCharactersString(portString);t
// espdu.setMarking(espduMarking);
// The EID is the unique identifier for objects in the world. This
// EID should match up with the ID for the object specified in the
// VMRL/x3d/virtual world.
EntityID entityID = espdu.getEntityID();
entityID.setSite(1); // 0 is apparently not a valid site number, per the spec
entityID.setApplication(1);
entityID.setEntity(2);
// Set the entity type. SISO has a big list of enumerations, so that by
// specifying various numbers we can say this is an M1A2 American tank,
// the USS Enterprise, and so on. We'll make this a tank. There is a
// separate project elsehwhere in this project that implements DIS
// enumerations in C++ and Java, but to keep things simple we just use
// numbers here.
// EntityType entityType = espdu.getEntityType();
// entityType.setEntityKind((short)1); // Platform (vs lifeform, munition, sensor, etc.)
// entityType.setCountry(224); // UK
// entityType.setDomain((short)1); // Land (vs air, surface, subsurface, space)
// entityType.setCategory((short)1); // Tank
// entityType.setSubcategory((short)1); // M1 Abrams
// entityType.setSpec((short)4); // M1A1 w/ mine roller
Set<InetAddress> broadcastAddresses;
// Loop through sending .csv entities
String fileName = "FinalProjects/2018March/Hanley/Entities.csv";
File inputFile = new File(fileName);
Scanner scanner;
try
{
DatagramSocket udpSocket = new DatagramSocket(SENDING_PORT);
for (int idx =0; idx<400; idx++){
scanner = new Scanner(inputFile); //this scanner reads from the .csv file identified by fileName
//this next line is only necesary if the .csv has a header row. this has the
//scanner read the line and gets ready for the parsing in the while loop.
//if the .csv does not have a header, comment out this line or you will miss the first entity.
scanner.nextLine();
//this section reads through the .csv and parses it to send out as an espdu.
while(scanner.hasNextLine()) {
String line = scanner.nextLine();
//System.out.println(line);
String[] splits;
splits = line.split(",");
if (splits[0].startsWith("#")) continue;
//this section parse each line into the component necessary to build a DIS ESPDU;
int kind = Integer.parseInt(splits[3]);
int country = Integer.parseInt(splits[4]);
int domain = Integer.parseInt(splits[5]);
int category = Integer.parseInt(splits[6]);
int subCategory = Integer.parseInt(splits[7]);
int special = Integer.parseInt(splits[8]);
int bumperNumber = Integer.parseInt(splits[2]);
float entityLat = Float.parseFloat(splits[9]);
//System.out.println(entityLat);
float entityLon = Float.parseFloat(splits[10]);
String marking = splits[11];
//System.out.println(marking);
//This section provides the ESPDU its entity specific information
entityID.setEntity(bumperNumber);
EntityType entityType = espdu.getEntityType();
entityType.setEntityKind((short) kind); // Platform (vs lifeform, munition, sensor, etc.)
entityType.setCountry((short)country); // country identifier from .csv all should be us for this example
entityType.setDomain((short)domain); // Land (vs air, surface, subsurface, space)
entityType.setCategory((short)category); // for this exampl tank, light truck, heavy truck or light armor
entityType.setSubcategory((short)subCategory); // M1 Abrams, M113, M998, or FMTV
entityType.setSpec((short)special); // various for this example
//System.out.println("entity ID: "+ bumperNumber); // a check built to make sure each line of the .csv was being read and parsed
Marking entityMarking = new Marking(); //creates a marking instance which can be added to the espdu
entityMarking.setCharactersString(marking);
espdu.setMarking(entityMarking);
//System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
//for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
// DIS time is a pain in the ass. DIS time units are 2^31-1 units per
// hour, and time is set to DIS time units from the top of the hour.
// This means that if you start sending just before the top of the hour
// the time units can roll over to zero as you are sending. The receivers
// (escpecially homegrown ones) are often not able to detect rollover
// and may start discarding packets as dupes or out of order. We use
// an NPS timestamp here, hundredths of a second since the start of the
// year. The DIS standard for time is often ignored in the wild; I've seen
// people use Unix time (seconds since 1970) and more. Or you can
// just stuff idx into the timestamp field to get something that is monotonically
// increasing.
// Note that timestamp is used to detect duplicate and out of order packets.
// That means if you DON'T change the timestamp, many implementations will simply
// discard subsequent packets that have an identical timestamp. Also, if they
// receive a PDU with an timestamp lower than the last one they received, they
// may discard it as an earlier, out-of-order PDU. So it is a good idea to
// update the timestamp on ALL packets sent.
// An alterative approach: actually follow the standard. It's a crazy concept,
// but it might just work.
int timestamp = disTime.getDisAbsoluteTimestamp();
espdu.setTimestamp(timestamp);
// Set the position of the entity in the world. DIS uses a cartesian
// coordinate system with the origin at the center of the earth, the x
// axis out at the equator and prime meridian, y out at the equator and
// 90 deg east, and z up and out the north pole. To place an object on
// the earth's surface you also need a model for the shape of the earth
// (it's not a sphere.) All the fancy math necessary to do this is in
// the SEDRIS SRM package. There are also some one-off formulas for
// doing conversions from, for example, lat/lon/altitude to DIS coordinates.
// Here we use those one-off formulas.
// Modify the position of the object. This will send the object a little
// due east by adding some to the longitude every iteration. Since we
// are on the Pacific coast, this sends the object east. Assume we are
// at zero altitude. In other worlds you'd use DTED to determine the
// local ground altitude at that lat/lon, or you'd just use ground clamping.
// The x and y values will change, but the z value should not.
//lon = lon + (double)((double)idx / 100000.0);
//System.out.println("lla=" + lat + "," + lon + ", 0.0");
//double direction = Math.pow((-1.0), (idx));
lon = entityLon + (idx * 0.002);
lat = entityLat + (idx * 0.002);
//System.out.println(lat);
//System.out.println(lon);
double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
Vector3Double location = espdu.getEntityLocation();
location.setX(disCoordinates[0]);
location.setY(disCoordinates[1]);
location.setZ(disCoordinates[2]);
//System.out.println("lat, lon:" + lat + ", " + lon);
//System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
// Optionally, we can do some rotation of the entity
/*
Orientation orientation = espdu.getEntityOrientation();
float psi = orientation.getPsi();
psi = psi + idx;
orientation.setPsi(psi);
orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
*/
// You can set other ESPDU values here, such as the velocity, acceleration,
// and so on.
// Marshal out the espdu object to a byte array, then send a datagram
// packet with that data in it.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
espdu.marshal(dos);
//FirePdu fire = new FirePdu();
//byte[] fireArray = fire.marshal();
// The byte array here is the packet in DIS format. We put that into a
// datagram and send it.
byte[] data = baos.toByteArray();
broadcastAddresses = getBroadcastAddresses();
Iterator it = broadcastAddresses.iterator();
InetAddress destinationAddress = InetAddress.getByName(DESTINATION_HOST);
while(it.hasNext())
{
InetAddress broadcast = (InetAddress)it.next();
//System.out.println("Sending broadcast datagram packet to " + broadcast);
DatagramPacket packet = new DatagramPacket(data, data.length, destinationAddress, RECEIVING_PORT );
//socket.send(packet);
udpSocket.send(packet);
// TODO experiment with these! 8)
//packet = new DatagramPacket(fireArray, fireArray.length, broadcast, 3000); // alternate
// socket.send(packet);
}
// Send every 1 sec. Otherwise this will be all over in a fraction of a second.
//Thread.sleep(3000);
location = espdu.getEntityLocation();
if (bumperNumber ==66){
System.out.println("Espdu #" + idx + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
double c[] = {location.getX(), location.getY(), location.getZ()};
double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
System.out.printf(" Location (lat/lon/alt): [ %.4f , %.4f, %.4f] \n",lla[0],lla[1],lla[2]);
}
}
// Send every 1 sec. Otherwise this will be all over in a fraction of a second.
System.out.println("Iteration "+idx);
System.out.println("Sleep Time");
Thread.sleep(3000);
}
}
catch(IOException | InterruptedException e)
{
System.out.println(e);
}
}
/**
* A number of sites get all snippy about using 255.255.255.255 for a broadcast
* address; it trips their security software and they kick you off their
* network. (Comcast, NPS.) This determines the broadcast address for all
* connected interfaces, based on the IP and subnet mask. If you have
* a dual-homed host it will return a broadcast address for both. If you have
* some VMs running on your host this will pick up the addresses for those
* as well--eg running VMWare on your laptop with a local IP this will
* also pick up a 192.168 address assigned to the VM by the host OS.
*
* @return set of all broadcast addresses
*/
public static Set<InetAddress> getBroadcastAddresses()
{
Set<InetAddress> broadcastAddresses = new HashSet<>();
Enumeration interfaces;
try
{
interfaces = NetworkInterface.getNetworkInterfaces();
while(interfaces.hasMoreElements())
{
NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
if(anInterface.isUp())
{
Iterator it = anInterface.getInterfaceAddresses().iterator();
while(it.hasNext())
{
InterfaceAddress anAddress = (InterfaceAddress)it.next();
if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
continue;
//System.out.println("Getting broadcast address for " + anAddress);
InetAddress broadcastAddress = anAddress.getBroadcast();
if(broadcastAddress != null)
broadcastAddresses.add(broadcastAddress);
}
}
}
}
catch(SocketException e)
{
e.printStackTrace();
System.out.println(e);
}
return broadcastAddresses;
}
}
#exerciseID,#siteID,#entityID,#entityKind,#Country,#Domain,#Category,#Subcategory,#special,#lat,#long,Marking
1,1,66,1,225,1,1,1,2,36.5955,-121.875,CoCDR
1,1,65,1,225,1,1,1,2,36.588,-121.882,CoXO
1,1,11,1,225,1,1,1,2,36.596,-121.877,1stPL
1,1,12,1,225,1,1,1,4,36.597,-121.878,1stRoller
1,1,13,1,225,1,1,1,5,36.594,-121.878,1stPlow
1,1,14,1,225,1,1,1,2,36.595,-121.877,1stPSG
1,1,21,1,225,1,1,1,2,36.603,-121.88,2ndPL
1,1,22,1,225,1,1,1,4,36.604,-121.881,2ndRoller
1,1,23,1,225,1,1,1,5,36.601,-121.881,2ndPlow
1,1,24,1,225,1,1,1,2,36.602,-121.88,2ndPSG
1,1,31,1,225,1,1,1,2,36.588,-121.88,3rdPL
1,1,32,1,225,1,1,1,4,36.589,-121.881,3rdRoller
1,1,33,1,225,1,1,1,5,36.586,-121.881,3rdPlow
1,1,34,1,225,1,1,1,2,36.587,-121.88,3rdPSG
1,1,7,1,225,1,6,1,1,36.5956,-121.87701,Co1SG
1,1,4,1,225,1,7,12,1,36.596,-121.878,CoSupSgt
1,1,77,1,225,1,3,14,0,36.595,-121.879,CoEvac
<html>
<head>
<title>Constructive Entity DIS Placement</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="scripts/dis.js"></script>
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
<body onLoad="initialize()">
<div>
<h2>Constructive Simulation DIS Entity</H2><p>
This web page sends Entity State PDUs with the values below.
Fill out the form, and click "Submit." The page will send ESDPUs
with those values to the web server over a websocket, and the server
will transmit them on the local network.<p>
The Javascript in the web page will send the ESPDUs with the frequency
indicated (in milliseconds).
</div>
<div id="data">
<form id="EspduForm" action="form_action.asp">
<b>Entity Type Information; Russian T-72 by Default</b><br>
Kind: <input type="text" name="entitykind" id="entitykind" value="1"><br>
Domain: <input type="text" name="domain" id="domain" value="1"><br>
Country <input type="text" name="country" id="country" value="222"><br>
Category<input type="text" name="category" id="category" value="1"><br>
Subcategory<input type="text" name="subcategory" id="subcategory" value="2"><br>
Specific<input type="text" name="specific" id="specific" value="1"><br>
Extra<input type="text" name="extra" id="extra" value="1"><br><br>
<b>Entity ID site and application</b><br>
Site<input type="text" name="site" id="site" value="48"><br>
Application<input type="text" name="application" id="application" value="23"><br>
<br>
<b>Location</b></br>
Latitude (Decimal degrees):<input type="text" name="latitude" id="latitude" value="36.595"><br>
Longitude<input type="text" name="longitude" id="longitude" value="-121.877"><br>
Altitude (meters)<input type="text" name="altitude" id="altitude" value="10"><br>
28.425
<br>
<b>Marking</b>
Marking<input type="text" name="marking" id="marking" value="MyEntity"><br>
<br>
<br>
<b>Send Frequency </b><br>
Send Frequency (ms)<input type="text" name="sendfrequency" id="sendfrequency" value="5000"><br>
<input type="button" name="submit" value="Start Sending PDUs" onClick="constructiveSend(this.form)" >
</form>
</div>
<SCRIPT type="text/javascript" src ="scripts/main.js"></SCRIPT>
</body>
</html>
This diff is collapsed.
<!--
Note that if you want to use this web page from clients other than the
one running on the same host as the web browser, you MUST change the
url the websocket connects to.
A demo that uses google map's Javascript api and web sockets. We receive
updates in IEEE 1278 DIS binary format, and place icons on the map for each
entity's location. The icons are clickable for more info. Typically the server
will be forwarding information, including from the server-local network, for such
information as may be being put out by VBS2 or the like.
Does the conversion from DIS global (geocentric/earth-centered, earth-fixed)
to lat/lon/alt.
-->
<!DOCTYPE html>
<html>
<head>
<title>Google Maps</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<style type="text/css">
html {height:100%}
body { height:100%; margin:0; padding:0 }
#map-canvas{height:100% }
</style>
<!-- Binary DIS implementation, also coordinate system conversion utilities -->
<script type="text/javascript" src="dis.js"></script>
<!-- Note: this is using an Google Maps API key linked to me, DMcG. For serious use, go to -->
<!-- https://code.google.com/apis/console and get your own api key. Using this key is fine for demo purposes. -->
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=AIzaSyAZihiWY3ho8hHfkhu9_6mcMSkxSvpjbTI&sensor=true"></script>
<!--script type="text/javascript" src="javascript/DisAppearance.js"></script-->
</head>
<body>
<div id="map-canvas"></div>
<SCRIPT type="text/javascript">
/** This works if you're running client and server on one host. To
* have it work with a remote server, replace localhost with the IP
* or name of the server.
*/
//var WEBSOCKET_URL="ws://192.168.60.204/ws";
//var WEBSOCKET_URL="ws://172.20.82.141:8282";
//var WEBSOCKET_URL="ws://172.20.152.19:8485";
var WEBSOCKET_URL="ws://track.movesinstitute.org:80";
var map;
var websocket;
/** A likely map location */
var montereyLocation = new google.maps.LatLng(36.595, -121.877);
var orlandoLocation = new google.maps.LatLng(28.425, -81.47);
/** Marker for the entity represented by this web browser's location */
var ourMarker;
/** current location of the device running this browser, as defined by geolocation api.
* This is the W3C geolocation position object, not the google maps object.
* coords.latitude, coords.longitude, coords.altitude are among the properties.
*/
var browserPosition;
/** Hash table Used to keep track of all entities in the world */
var allEntities = {};
/** EntityStatePdu for the entity represented by this page. This is
* periodically sent as a heartbeat, so others can find us. */
var espdu = new dis.EntityStatePdu();
espdu.marking.setMarking("IITSECDemo");
//console.log(espdu.marking);
//console.log(JSON.stringify(espdu));
/** Used to convert DIS earth-centered coordinates to lat/lon/alt */
var conversion = new dis.CoordinateConversion();
/** benchmarking */
var messageCount = 0; var startTime = new Date();
/** icon path*/
var iconBase = '/images';
// Set the initialize function to run on page load
google.maps.event.addDomListener(window, 'load', initialize);
/**
* Initialize the map and websocket
*
* @returns {undefined}
*/
function initialize()
{
var coordinateConversion = new dis.CoordinateConversion();
var position = {};
position.lat = 50.430436041848;
position.lon = 45.4806844718347;
position.alt = 16.2087463214993;
var xyz = coordinateConversion.getXYZfromLatLonAltDegrees(position);
console.log("xyz for postion is ", xyz);
var geocentric = {};
geocentric.x = 2854437.74;
geocentric.y = 2902738.86;
geocentric.z = 4893439.36;
var geodetic = coordinateConversion.convertDisToLatLongInDegrees(geocentric);
console.log("geodetic for the same position: ", geodetic);
// periodically prune entities that we haven't heard from lately
window.setInterval(prune, 60000);
// The region of the map that's visible, and where it's centered.
var mapOptions =
{
center: montereyLocation,
zoom:14,
mapTypeId:google.maps.MapTypeId.SATELLITE
};
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
// Compatiability checks--not all web browsers support Websockets.
// note that the host portion of the URL (localhost here) MUST
// be changed to a DNS name or IP to reach it from off-host. The
// existing localhost is just there for development purposes.
if(window.WebSocket)
websocket = new WebSocket(WEBSOCKET_URL);
else if(Window.MozWebSocket)
websocket = new MozWebSocket(WEBSOCKET_URL);
else
alert("This web browser does not support web sockets");
// Set the format we want to use to receive binary messages
websocket.binaryType = 'arraybuffer';
// Attach functions to the the web socket for various events
websocket.onopen = function(evt){console.log("Opened websocket");};//console.log("websocket onopen");};
websocket.onclose = function(evt){console.log("websocket close", evt);};
websocket.onerror = function(evt){console.log("websocket error", evt.data);};
/** Handle the messages sent from the server to us here. We receive binary
* DIS from the server over the web socket.
* @param {event} evt The receive event object. Contains the binary data to decode
*/
websocket.onmessage = function(evt)
{
console.log("Raw message: ", evt);
// Factory object for creating new PDUs from binary data
var pduFactory = new dis.PduFactory();
// InputStream is modeled on a Java input stream. Pass it binary data,
// and we will read through it, while input stream maintains a current
// place marker
//console.log(evt.data);
//var inputStream = new dis.InputStream(evt.data);
var disMessage = pduFactory.createPdu(evt.data);
//console.log(disMessage);
// You can trap the various types of PDU here, and
// probably call a specific function to handle each
// type of message. For now we return on everything but
// espdus.
if(disMessage.pduType != 1)
return;
// Some instrumentation for performance. This is useful if hooked
// up to an AIS feed, for example, which generates a lot of traffic.
messageCount++;
if(messageCount % 500 === 0)
{
var timeNow = new Date();
var difference = timeNow.getTime() - startTime.getTime();
console.log("Packets per second for 20K packets: ", 20000 / difference * 1000);
startTime = new Date();
//console.log(JSON.stringify(disMessage));
}
// Retrieve the entity ID from the DIS message, convert it to a JSON
// string, and then use that as a sleazy key into a "hash table" consisting
// of object attributes.
var entityID = disMessage.entityID;
var eidString = JSON.stringify(entityID);
// Convert from DIS global coordinates to latitude/longtitude
var latLonAlt = conversion.convertDisToLatLongInDegrees(disMessage.entityLocation);
// We have an attribute on this object named the JSON text string, with a
// value of the marker data. Look that up.
var theMarker = allEntities[eidString];
// If it's not found, that means it's the first time we've heard of it. Create
// a new one.
if(theMarker === undefined)
{
theMarker = {};
var entityMarking = disMessage.marking.getMarking();
var contentString = "<b>Entity ID:</b>" + JSON.stringify(disMessage.entityID) + "<br>";
contentString = contentString + "<b>Marking:</b>" + entityMarking + "<br>";
contentString = contentString + "<b>Entity Type:</b>" + JSON.stringify(disMessage.entityType) + "<br>";
contentString = contentString + "<b>Location:</b>" + latLonAlt.latitude + ", " +latLonAlt.longitude + ", " + latLonAlt.altitude + "<br>"
var infowindow = new google.maps.InfoWindow({content: contentString});
var newEntityLocation = new google.maps.LatLng(latLonAlt.latitude, latLonAlt.longitude);
// The marker (with the default icon) is automatically added
// to the map when created
var marker = makeMarker('tank', newEntityLocation);
// var marker = new google.maps.Marker({
// map:map,
// draggable:true,
// animation:google.maps.Animation.DROP,
// position: newEntityLocation,
// title:"Entity From Network",
// icon: 'tank.png'
// });
var iconIsBig = false;
// add a function to be called when the user clicks on the icon
google.maps.event.addListener(marker, 'click', function()
{
if (iconIsBig){
infowindow.close(map, marker);
marker.setIcon('tank.png');
iconIsBig=false;
}else {
infowindow.open(map,marker);
marker.setIcon('tankBig.png');
iconIsBig=true;
}
});
theMarker.marker = marker;
//console.log("new theMarker:", theMarker);
allEntities[eidString] = theMarker;
};
// The marker for the entity has either just been added, or recognized as already
// existing. In either event, update it's position on the map.
// Update the marker position
theMarker.marker.setPosition(new google.maps.LatLng(latLonAlt.latitude, latLonAlt.longitude) );
theMarker.lastEspdu = disMessage;
theMarker.lastHeardFrom = new Date();
}; // end of onmessage
}
/**
* Removes icons from the map if we haven't heard from in some amount of time
*/
function prune()
{
var TIMEOUT = 120000; // 2 min
var now = new Date();
for (var anEntity in allEntities)
{
var entityInfo = allEntities[anEntity];
if(now.getTime() - entityInfo.lastHeardFrom.getTime() > TIMEOUT)
{
var markerInfo = allEntities[anEntity];
markerInfo.marker.setMap(null);
delete allEntities[anEntity];
}
}
}
function makeMarker(imageName,position){
var marker = new google.maps.Marker({
map:map,
draggable:true,
animation:google.maps.Animation.DROP,
position: position,
title:"Entity From Network",
icon: imageName +'.png'
});
return marker;
}
</SCRIPT>
</body>
</html>
projects/Assignments/FinalProjects/2018March/SasalaMaroon/Final Project/russian-tank.png

41.3 KiB

/** This works if you're running client and server on one host. To
* have it work with a remote server, replace localhost with the IP
* or name of the server.
*/
var WEBSOCKET_URL="ws://track.movesinstitute.org:80";
var websocket;
var timerID = 0;
/** A likely map location */
var montereyLocation = {'latitude':36.595, 'longitude':-121.877};
var allDisEntities = new Object();
var pduFactory = new dis.PduFactory();
var espdu = new dis.EntityStatePdu();
var rifleMunition = new dis.EntityType();
var damageHits = 0;
espdu.entityID.entity = Math.round(Math.random() * 64000);
/**
* Called when the user clicks the "submit" button. Starts a task
* to retrieve the field values, and periodically send ESPDUs based
* on this.
*
* @param {type} form
* @returns {undefined}
*/
function constructiveSend(form)
{
// On a second button press, kill the old send timer and
// start a new one farther down, so we don't have two
// timers sending
if(timerID != 0)
{
console.log("timerID:", timerID)
clearInterval(timerID);
console.log("Killed old periodic send task")
}
// Fill out entity type info
espdu.entityType.entityKind = parseInt(document.getElementById("entitykind").value);
espdu.entityType.domain = parseInt(document.getElementById("domain").value);
espdu.entityType.country = parseInt(document.getElementById("country").value);
espdu.entityType.category = parseInt(document.getElementById("category").value);
espdu.entityType.subcategory = parseInt(document.getElementById("subcategory").value);
espdu.entityType.specific = parseInt(document.getElementById("specific").value);
espdu.entityType.extra = parseInt(document.getElementById("extra").value);
// Fill out entity ID
espdu.entityID.site = parseInt(document.getElementById("site").value);
espdu.entityID.application = parseInt(document.getElementById("application").value);
espdu.entityID.entity = Math.round(Math.random() * 65000);
// Marking
var convert = new dis.StringConversion();
espdu.marking.setMarking(document.getElementById("marking").value);
// Position
var lat = parseFloat(document.getElementById("latitude").value);
var lon = parseFloat(document.getElementById("longitude").value);
var alt = parseFloat(document.getElementById("altitude").value);
// Convert lat/lon/alt to DIS coordinates
var conversion = new dis.CoordinateConversion();
latLonAlt = {};
latLonAlt.lat = lat;
latLonAlt.lon = lon;
latLonAlt.alt = alt;
console.log("Geodetic location:", latLonAlt);
var disCoordinates = conversion.getXYZfromLatLonAltDegrees(latLonAlt);
espdu.entityLocation.x = disCoordinates.x;
espdu.entityLocation.y = disCoordinates.y;
espdu.entityLocation.z = disCoordinates.z;
console.log("Location:", disCoordinates);
// How often to send
var frequency = parseInt(document.getElementById("sendfrequency").value);
// start a repeating task to send it
timerID = setInterval(sendPdu, frequency);
}
/**
* Called by the timer task. Marshal and send a PDU
*
* @returns {undefined}
*/
function sendPdu()
{
var dataBuffer = new ArrayBuffer(1000); // typically 144 bytes, make it bigger for safety
var outputStream = new dis.OutputStream(dataBuffer);
espdu.encodeToBinary(outputStream);
var trimmedData = outputStream.toByteArray();
websocket.send(trimmedData);
console.log("Sent pdu ", espdu);
}
/**
* Initialize websocket
*
* @returns {undefined}
*/
function initialize()
{
websocket = new WebSocket(WEBSOCKET_URL);
// Set the format we want to use to receive binary messages
websocket.binaryType = 'arraybuffer';
// Attach functions to the the web socket for various events
websocket.onopen = function(evt){console.log("Opened websocket");};//console.log("websocket onopen");};
websocket.onclose = function(evt){console.log("websocket close", evt);};
websocket.onerror = function(evt){console.log("websocket error", evt.data);};
// We don't really need to receive anything, just blindly send
websocket.onmessage = function(evt)
{
var aPdu = pduFactory.createPdu(evt.data);
//console.log("PDU:", aPdu);
switch(aPdu.pduType)
{
case 1:
entityStatePduHandler(aPdu);
break;
case 2:
console.log("Fire PDU:", aPdu);
firePduHandler(aPdu);
break;
case 3:
console.log("Detonation PDU");
detonationPduHandler(aPdu);
break;
default:
break;
}
}
}
/**
* Call this function to process an entity state pdu
*
* @param {EntityStatePdu} espdu
* @returns {void}
*/
function entityStatePduHandler(espdu)
{
if(espdu.pduType != 1)
{
console.log("Sent a non-espdu PDU to entityStatePduHandler");
return;
}
// Process an entity state PDU here
}
/**
* Call this function to process a FirePdu
*
* @param {FirePdu} firePdu
* @returns {void}
*/
function firePduHandler(firePdu)
{
if(firePdu.pduType != 2)
{
console.log("You sent a PDU that is not a fire PDU to firePduHandler");
return;
}
// Process PDU here
}
/**
* Call this function to process a detonation pdu
*
* @param {DetonationPdu} detonationPdu
* @returns {void}
*/
function detonationPduHandler(detonationPdu)
{
if(detonationPdu.pduType != 3)
{
console.log("You sent a PDU that is not a detonation pdu to detonationPduHandler");
return;
}
// Handle the detonation PDU here
}
/**
* Write code to assess damage to our entity here. Assume
* that we are killed by two or more 5.56 rifle rounds that
* hit us. We receive the detonation PDU, which contains the
* target ID and the munition. if 1) we're the target, and
* 2) the munition is a rifle round, and (3) the impact
* is in the general area, assume we've been shot. You can
* make use of the entityIDsEqual() and munitionsEqual()
* functions.
*
* @param {type} detonationPdu
* @returns {undefined}
*/
function assessDamageToOurEntities(detonationPdu)
{
console.log("Assessing damage for detonation:", detonationPdu);
}
function entityIDsEqual(eid1, eid2)
{
if(eid1.site === eid2.site &&
eid1.application === eid2.application &&
eid1.entity === eid2.entity)
{
return true;
}
return false;
}
function munitionsEqual(firstMunition, secondMunition)
{
if(firstMunition.domain === secondMunition.domain &&
firstMunition.entityKind === secondMunition.entityKind &&
firstMunition.country === secondMunition.country &&
firstMunition.category === secondMunition.category &&
firstMunition.subcategory === secondMunition.subcategory &&
firstMunition.specific === secondMunition.specific &&
firstMunition.extra === secondMunition.extra)
{
return true;
}
return false;
}
//listen to muticast
//Multicast Client receiving sent messages
var PORT = 3000;
var MCAST_ADDR = "239.1.2.3"; //same mcast address as Server
var HOST = '172.20.159.255'; //this is your own IP
var dgram = require('dgram');
var client = dgram.createSocket('udp4');
//set up WebSocket repeater
const WebSocket = require('ws');
const websocket = new WebSocket('ws://track.movesinstitute.org:80');
websocket.onopen = function(evt){console.log("Opened websocket");};//console.log("websocket onopen");};
websocket.onclose = function(evt){console.log("websocket close", evt);};
websocket.onerror = function(evt){console.log("websocket error", evt.data);};
client.on('listening', function () {
var address = client.address();
console.log('UDP Client listening on ' + address.address + ":" + address.port);
client.setBroadcast(true)
client.setMulticastTTL(128);
client.addMembership(MCAST_ADDR);
});
client.on('message', function (message, remote) {
console.log('MCast Msg: From: ' + remote.address + ':' + remote.port +' - ' + message);
websocket.send(message);
});
client.bind(PORT, HOST);
language: node_js
node_js:
- "6"
- "node"
script: npm run travis
cache:
yarn: true
The MIT License (MIT)
Copyright (c) 2017 Samuel Reed <samuel.trace.reed@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{"/Users/samuelreed/git/forks/async-throttle/index.js":{"path":"/Users/samuelreed/git/forks/async-throttle/index.js","s":{"1":1,"2":7,"3":1,"4":6,"5":6,"6":6,"7":6,"8":6,"9":6,"10":1,"11":1,"12":3,"13":13,"14":13,"15":13,"16":1,"17":19,"18":1,"19":45,"20":6,"21":39,"22":13,"23":13,"24":13,"25":13,"26":39,"27":18,"28":6,"29":6,"30":1,"31":6,"32":6,"33":6,"34":1,"35":13,"36":13,"37":1},"b":{"1":[1,6],"2":[6,5],"3":[6,5],"4":[6,39],"5":[13,26],"6":[18,21],"7":[6,0]},"f":{"1":7,"2":3,"3":13,"4":19,"5":45,"6":6,"7":13},"fnMap":{"1":{"name":"Queue","line":3,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":24}}},"2":{"name":"(anonymous_2)","line":22,"loc":{"start":{"line":22,"column":24},"end":{"line":22,"column":41}}},"3":{"name":"(anonymous_3)","line":23,"loc":{"start":{"line":23,"column":28},"end":{"line":23,"column":39}}},"4":{"name":"(anonymous_4)","line":31,"loc":{"start":{"line":31,"column":7},"end":{"line":31,"column":18}}},"5":{"name":"(anonymous_5)","line":36,"loc":{"start":{"line":36,"column":23},"end":{"line":36,"column":34}}},"6":{"name":"(anonymous_6)","line":55,"loc":{"start":{"line":55,"column":25},"end":{"line":55,"column":38}}},"7":{"name":"done","line":62,"loc":{"start":{"line":62,"column":0},"end":{"line":62,"column":16}}}},"statementMap":{"1":{"start":{"line":3,"column":0},"end":{"line":14,"column":1}},"2":{"start":{"line":4,"column":2},"end":{"line":6,"column":3}},"3":{"start":{"line":5,"column":4},"end":{"line":5,"column":30}},"4":{"start":{"line":8,"column":2},"end":{"line":8,"column":26}},"5":{"start":{"line":9,"column":2},"end":{"line":9,"column":53}},"6":{"start":{"line":10,"column":2},"end":{"line":10,"column":19}},"7":{"start":{"line":11,"column":2},"end":{"line":11,"column":17}},"8":{"start":{"line":12,"column":2},"end":{"line":12,"column":16}},"9":{"start":{"line":13,"column":2},"end":{"line":13,"column":31}},"10":{"start":{"line":16,"column":0},"end":{"line":20,"column":2}},"11":{"start":{"line":22,"column":0},"end":{"line":28,"column":3}},"12":{"start":{"line":23,"column":2},"end":{"line":27,"column":4}},"13":{"start":{"line":24,"column":4},"end":{"line":24,"column":75}},"14":{"start":{"line":25,"column":4},"end":{"line":25,"column":16}},"15":{"start":{"line":26,"column":4},"end":{"line":26,"column":24}},"16":{"start":{"line":30,"column":0},"end":{"line":34,"column":3}},"17":{"start":{"line":32,"column":4},"end":{"line":32,"column":43}},"18":{"start":{"line":36,"column":0},"end":{"line":53,"column":2}},"19":{"start":{"line":37,"column":2},"end":{"line":39,"column":3}},"20":{"start":{"line":38,"column":4},"end":{"line":38,"column":11}},"21":{"start":{"line":40,"column":2},"end":{"line":45,"column":3}},"22":{"start":{"line":41,"column":4},"end":{"line":41,"column":32}},"23":{"start":{"line":42,"column":4},"end":{"line":42,"column":19}},"24":{"start":{"line":43,"column":4},"end":{"line":43,"column":20}},"25":{"start":{"line":44,"column":4},"end":{"line":44,"column":16}},"26":{"start":{"line":47,"column":2},"end":{"line":52,"column":3}},"27":{"start":{"line":48,"column":4},"end":{"line":51,"column":5}},"28":{"start":{"line":49,"column":6},"end":{"line":49,"column":30}},"29":{"start":{"line":50,"column":6},"end":{"line":50,"column":27}},"30":{"start":{"line":55,"column":0},"end":{"line":60,"column":2}},"31":{"start":{"line":56,"column":2},"end":{"line":59,"column":3}},"32":{"start":{"line":57,"column":4},"end":{"line":57,"column":22}},"33":{"start":{"line":58,"column":4},"end":{"line":58,"column":16}},"34":{"start":{"line":62,"column":0},"end":{"line":65,"column":1}},"35":{"start":{"line":63,"column":2},"end":{"line":63,"column":17}},"36":{"start":{"line":64,"column":2},"end":{"line":64,"column":14}},"37":{"start":{"line":67,"column":0},"end":{"line":67,"column":23}}},"branchMap":{"1":{"line":4,"type":"if","locations":[{"start":{"line":4,"column":2},"end":{"line":4,"column":2}},{"start":{"line":4,"column":2},"end":{"line":4,"column":2}}]},"2":{"line":8,"type":"binary-expr","locations":[{"start":{"line":8,"column":12},"end":{"line":8,"column":19}},{"start":{"line":8,"column":23},"end":{"line":8,"column":25}}]},"3":{"line":9,"type":"binary-expr","locations":[{"start":{"line":9,"column":21},"end":{"line":9,"column":40}},{"start":{"line":9,"column":44},"end":{"line":9,"column":52}}]},"4":{"line":37,"type":"if","locations":[{"start":{"line":37,"column":2},"end":{"line":37,"column":2}},{"start":{"line":37,"column":2},"end":{"line":37,"column":2}}]},"5":{"line":40,"type":"if","locations":[{"start":{"line":40,"column":2},"end":{"line":40,"column":2}},{"start":{"line":40,"column":2},"end":{"line":40,"column":2}}]},"6":{"line":47,"type":"if","locations":[{"start":{"line":47,"column":2},"end":{"line":47,"column":2}},{"start":{"line":47,"column":2},"end":{"line":47,"column":2}}]},"7":{"line":56,"type":"if","locations":[{"start":{"line":56,"column":2},"end":{"line":56,"column":2}},{"start":{"line":56,"column":2},"end":{"line":56,"column":2}}]}}}}
\ No newline at end of file
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for async-throttle/</title>
<meta charset="utf-8">
<link rel="stylesheet" href="../prettify.css">
<link rel="stylesheet" href="../base.css">
<style type='text/css'>
div.coverage-summary .sorter {
background-image: url(../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class="header high">
<h1>Code coverage report for <span class="entity">async-throttle/</span></h1>
<h2>
Statements: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Branches: <span class="metric">92.86% <small>(13 / 14)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Functions: <span class="metric">100% <small>(7 / 7)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Lines: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Ignored: <span class="metric"><span class="ignore-none">none</span></span> &nbsp;&nbsp;&nbsp;&nbsp;
</h2>
<div class="path"><a href="../index.html">All files</a> &#187; async-throttle/</div>
</div>
<div class="body">
<div class="coverage-summary">
<table>
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file high" data-value="index.js"><a href="index.js.html">index.js</a></td>
<td data-value="100" class="pic high"><span class="cover-fill cover-full" style="width: 100px;"></span><span class="cover-empty" style="width:0px;"></span></td>
<td data-value="100" class="pct high">100%</td>
<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
<td data-value="92.86" class="pct high">92.86%</td>
<td data-value="14" class="abs high">(13&nbsp;/&nbsp;14)</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="7" class="abs high">(7&nbsp;/&nbsp;7)</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="footer">
<div class="meta">Generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Sep 11 2017 11:14:14 GMT-0500 (CDT)</div>
</div>
<script src="../prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="../sorter.js"></script>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for async-throttle/index.js</title>
<meta charset="utf-8">
<link rel="stylesheet" href="../prettify.css">
<link rel="stylesheet" href="../base.css">
<style type='text/css'>
div.coverage-summary .sorter {
background-image: url(../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class="header high">
<h1>Code coverage report for <span class="entity">async-throttle/index.js</span></h1>
<h2>
Statements: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Branches: <span class="metric">92.86% <small>(13 / 14)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Functions: <span class="metric">100% <small>(7 / 7)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Lines: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Ignored: <span class="metric"><span class="ignore-none">none</span></span> &nbsp;&nbsp;&nbsp;&nbsp;
</h2>
<div class="path"><a href="../index.html">All files</a> &#187; <a href="index.html">async-throttle/</a> &#187; index.js</div>
</div>
<div class="body">
<pre><table class="coverage">
<tr><td class="line-count">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68</td><td class="line-coverage"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-yes">7</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-yes">3</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">19</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-yes">45</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">39</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">39</span>
<span class="cline-any cline-yes">18</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-yes">6</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-yes">13</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">'use strict';
&nbsp;
function Queue(options) {
if (!(this instanceof Queue)) {
return new Queue(options);
}
&nbsp;
options = options || {};
this.concurrency = options.concurrency || Infinity;
this.pending = 0;
this.jobs = [];
this.cbs = [];
this._done = done.bind(this);
}
&nbsp;
var arrayAddMethods = [
'push',
'unshift',
'splice'
];
&nbsp;
arrayAddMethods.forEach(function(method) {
Queue.prototype[method] = function() {
var methodResult = Array.prototype[method].apply(this.jobs, arguments);
this._run();
return methodResult;
};
});
&nbsp;
Object.defineProperty(Queue.prototype, 'length', {
get: function() {
return this.pending + this.jobs.length;
}
});
&nbsp;
Queue.prototype._run = function() {
if (this.pending === this.concurrency) {
return;
}
if (this.jobs.length) {
var job = this.jobs.shift();
this.pending++;
job(this._done);
this._run();
}
&nbsp;
if (this.pending === 0) {
while (this.cbs.length !== 0) {
var cb = this.cbs.pop();
process.nextTick(cb);
}
}
};
&nbsp;
Queue.prototype.onDone = function(cb) {
<span class="missing-if-branch" title="else path not taken" >E</span>if (typeof cb === 'function') {
this.cbs.push(cb);
this._run();
}
};
&nbsp;
function done() {
this.pending--;
this._run();
}
&nbsp;
module.exports = Queue;
&nbsp;</pre></td></tr>
</table></pre>
</div>
<div class="footer">
<div class="meta">Generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Sep 11 2017 11:14:14 GMT-0500 (CDT)</div>
</div>
<script src="../prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="../sorter.js"></script>
</body>
</html>
body, html {
margin:0; padding: 0;
}
body {
font-family: Helvetica Neue, Helvetica,Arial;
font-size: 10pt;
}
div.header, div.footer {
background: #eee;
padding: 1em;
}
div.header {
z-index: 100;
position: fixed;
top: 0;
border-bottom: 1px solid #666;
width: 100%;
}
div.footer {
border-top: 1px solid #666;
}
div.body {
margin-top: 10em;
}
div.meta {
font-size: 90%;
text-align: center;
}
h1, h2, h3 {
font-weight: normal;
}
h1 {
font-size: 12pt;
}
h2 {
font-size: 10pt;
}
pre {
font-family: Consolas, Menlo, Monaco, monospace;
margin: 0;
padding: 0;
line-height: 1.3;
font-size: 14px;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
div.path { font-size: 110%; }
div.path a:link, div.path a:visited { color: #000; }
table.coverage { border-collapse: collapse; margin:0; padding: 0 }
table.coverage td {
margin: 0;
padding: 0;
color: #111;
vertical-align: top;
}
table.coverage td.line-count {
width: 50px;
text-align: right;
padding-right: 5px;
}
table.coverage td.line-coverage {
color: #777 !important;
text-align: right;
border-left: 1px solid #666;
border-right: 1px solid #666;
}
table.coverage td.text {
}
table.coverage td span.cline-any {
display: inline-block;
padding: 0 5px;
width: 40px;
}
table.coverage td span.cline-neutral {
background: #eee;
}
table.coverage td span.cline-yes {
background: #b5d592;
color: #999;
}
table.coverage td span.cline-no {
background: #fc8c84;
}
.cstat-yes { color: #111; }
.cstat-no { background: #fc8c84; color: #111; }
.fstat-no { background: #ffc520; color: #111 !important; }
.cbranch-no { background: yellow !important; color: #111; }
.cstat-skip { background: #ddd; color: #111; }
.fstat-skip { background: #ddd; color: #111 !important; }
.cbranch-skip { background: #ddd !important; color: #111; }
.missing-if-branch {
display: inline-block;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: black;
color: yellow;
}
.skip-if-branch {
display: none;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: #ccc;
color: white;
}
.missing-if-branch .typ, .skip-if-branch .typ {
color: inherit !important;
}
.entity, .metric { font-weight: bold; }
.metric { display: inline-block; border: 1px solid #333; padding: 0.3em; background: white; }
.metric small { font-size: 80%; font-weight: normal; color: #666; }
div.coverage-summary table { border-collapse: collapse; margin: 3em; font-size: 110%; }
div.coverage-summary td, div.coverage-summary table th { margin: 0; padding: 0.25em 1em; border-top: 1px solid #666; border-bottom: 1px solid #666; }
div.coverage-summary th { text-align: left; border: 1px solid #666; background: #eee; font-weight: normal; }
div.coverage-summary th.file { border-right: none !important; }
div.coverage-summary th.pic { border-left: none !important; text-align: right; }
div.coverage-summary th.pct { border-right: none !important; }
div.coverage-summary th.abs { border-left: none !important; text-align: right; }
div.coverage-summary td.pct { text-align: right; border-left: 1px solid #666; }
div.coverage-summary td.abs { text-align: right; font-size: 90%; color: #444; border-right: 1px solid #666; }
div.coverage-summary td.file { border-left: 1px solid #666; white-space: nowrap; }
div.coverage-summary td.pic { min-width: 120px !important; }
div.coverage-summary a:link { text-decoration: none; color: #000; }
div.coverage-summary a:visited { text-decoration: none; color: #777; }
div.coverage-summary a:hover { text-decoration: underline; }
div.coverage-summary tfoot td { border-top: 1px solid #666; }
div.coverage-summary .sorter {
height: 10px;
width: 7px;
display: inline-block;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
div.coverage-summary .sorted .sorter {
background-position: 0 -20px;
}
div.coverage-summary .sorted-desc .sorter {
background-position: 0 -10px;
}
.high { background: #b5d592 !important; }
.medium { background: #ffe87c !important; }
.low { background: #fc8c84 !important; }
span.cover-fill, span.cover-empty {
display:inline-block;
border:1px solid #444;
background: white;
height: 12px;
}
span.cover-fill {
background: #ccc;
border-right: 1px solid #444;
}
span.cover-empty {
background: white;
border-left: none;
}
span.cover-full {
border-right: none !important;
}
pre.prettyprint {
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.com { color: #999 !important; }
.ignore-none { color: #999; font-weight: normal; }
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for All files</title>
<meta charset="utf-8">
<link rel="stylesheet" href="prettify.css">
<link rel="stylesheet" href="base.css">
<style type='text/css'>
div.coverage-summary .sorter {
background-image: url(sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class="header high">
<h1>Code coverage report for <span class="entity">All files</span></h1>
<h2>
Statements: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Branches: <span class="metric">92.86% <small>(13 / 14)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Functions: <span class="metric">100% <small>(7 / 7)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Lines: <span class="metric">100% <small>(37 / 37)</small></span> &nbsp;&nbsp;&nbsp;&nbsp;
Ignored: <span class="metric"><span class="ignore-none">none</span></span> &nbsp;&nbsp;&nbsp;&nbsp;
</h2>
<div class="path"></div>
</div>
<div class="body">
<div class="coverage-summary">
<table>
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file high" data-value="async-throttle/"><a href="async-throttle/index.html">async-throttle/</a></td>
<td data-value="100" class="pic high"><span class="cover-fill cover-full" style="width: 100px;"></span><span class="cover-empty" style="width:0px;"></span></td>
<td data-value="100" class="pct high">100%</td>
<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
<td data-value="92.86" class="pct high">92.86%</td>
<td data-value="14" class="abs high">(13&nbsp;/&nbsp;14)</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="7" class="abs high">(7&nbsp;/&nbsp;7)</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="37" class="abs high">(37&nbsp;/&nbsp;37)</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="footer">
<div class="meta">Generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Sep 11 2017 11:14:14 GMT-0500 (CDT)</div>
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="sorter.js"></script>
</body>
</html>
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.ignoreCase){ac=true}else{if(/[a-z]/i.test(ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){S=true;ac=false;break}}}var Y={b:8,t:9,n:10,v:11,f:12,r:13};function ab(ah){var ag=ah.charCodeAt(0);if(ag!==92){return ag}var af=ah.charAt(1);ag=Y[af];if(ag){return ag}else{if("0"<=af&&af<="7"){return parseInt(ah.substring(1),8)}else{if(af==="u"||af==="x"){return parseInt(ah.substring(2),16)}else{return ah.charCodeAt(1)}}}}function T(af){if(af<32){return(af<16?"\\x0":"\\x")+af.toString(16)}var ag=String.fromCharCode(af);if(ag==="\\"||ag==="-"||ag==="["||ag==="]"){ag="\\"+ag}return ag}function X(am){var aq=am.substring(1,am.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));var ak=[];var af=[];var ao=aq[0]==="^";for(var ar=ao?1:0,aj=aq.length;ar<aj;++ar){var ah=aq[ar];if(/\\[bdsw]/i.test(ah)){ak.push(ah)}else{var ag=ab(ah);var al;if(ar+2<aj&&"-"===aq[ar+1]){al=ab(aq[ar+2]);ar+=2}else{al=ag}af.push([ag,al]);if(!(al<65||ag>122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;ar<af.length;++ar){var at=af[ar];if(at[0]<=ap[1]+1){ap[1]=Math.max(ap[1],at[1])}else{ai.push(ap=at)}}var an=["["];if(ao){an.push("^")}an.push.apply(an,ak);for(var ar=0;ar<ai.length;++ar){var at=ai[ar];an.push(T(at[0]));if(at[1]>at[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){an[af]=-1}}}}for(var ak=1;ak<an.length;++ak){if(-1===an[ak]){an[ak]=++ad}}for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am;if(an[am]===undefined){aj[ak]="(?:"}}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){aj[ak]="\\"+an[am]}}}}for(var ak=0,am=0;ak<ah;++ak){if("^"===aj[ak]&&"^"!==aj[ak+1]){aj[ak]=""}}if(al.ignoreCase&&S){for(var ak=0;ak<ah;++ak){var ag=aj[ak];var ai=ag.charAt(0);if(ag.length>=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.global||ae.multiline){throw new Error(""+ae)}aa.push("(?:"+W(ae)+")")}return new RegExp(aa.join("|"),ac?"gi":"g")}function a(V){var U=/(?:^|\s)nocode(?:\s|$)/;var X=[];var T=0;var Z=[];var W=0;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=document.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Y=S&&"pre"===S.substring(0,3);function aa(ab){switch(ab.nodeType){case 1:if(U.test(ab.className)){return}for(var ae=ab.firstChild;ae;ae=ae.nextSibling){aa(ae)}var ad=ab.nodeName;if("BR"===ad||"LI"===ad){X[W]="\n";Z[W<<1]=T++;Z[(W++<<1)|1]=ab}break;case 3:case 4:var ac=ab.nodeValue;if(ac.length){if(!Y){ac=ac.replace(/[ \t\r\n]+/g," ")}else{ac=ac.replace(/\r\n?/g,"\n")}X[W]=ac;Z[W<<1]=T;T+=ac.length;Z[(W++<<1)|1]=ab}break}}aa(V);return{sourceCode:X.join("").replace(/\n$/,""),spans:Z}}function B(S,U,W,T){if(!U){return}var V={sourceCode:U,basePos:S};W(V);T.push.apply(T,V.decorations)}var v=/\S/;function o(S){var V=undefined;for(var U=S.firstChild;U;U=U.nextSibling){var T=U.nodeType;V=(T===1)?(V?S:U):(T===3)?(v.test(U.nodeValue)?S:V):V}return V===S?undefined:V}function g(U,T){var S={};var V;(function(){var ad=U.concat(T);var ah=[];var ag={};for(var ab=0,Z=ad.length;ab<Z;++ab){var Y=ad[ab];var ac=Y[3];if(ac){for(var ae=ac.length;--ae>=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae<aq;++ae){var ag=an[ae];var ap=aj[ag];var ai=void 0;var am;if(typeof ap==="string"){am=false}else{var aa=S[ag.charAt(0)];if(aa){ai=ag.match(aa[1]);ap=aa[0]}else{for(var ao=0;ao<X;++ao){aa=T[ao];ai=ag.match(aa[1]);if(ai){ap=aa[0];break}}if(!ai){ap=F}}am=ap.length>=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y<W.length;++Y){ae(W[Y])}if(ag===(ag|0)){W[0].setAttribute("value",ag)}var aa=ac.createElement("OL");aa.className="linenums";var X=Math.max(0,((ag-1))|0)||0;for(var Y=0,T=W.length;Y<T;++Y){af=W[Y];af.className="L"+((Y+X)%10);if(!af.firstChild){af.appendChild(ac.createTextNode("\xA0"))}aa.appendChild(af)}V.appendChild(aa)}function D(ac){var aj=/\bMSIE\b/.test(navigator.userAgent);var am=/\n/g;var al=ac.sourceCode;var an=al.length;var V=0;var aa=ac.spans;var T=aa.length;var ah=0;var X=ac.decorations;var Y=X.length;var Z=0;X[Y]=an;var ar,aq;for(aq=ar=0;aq<Y;){if(X[aq]!==X[aq+2]){X[ar++]=X[aq++];X[ar++]=X[aq++]}else{aq+=2}}Y=ar;for(aq=ar=0;aq<Y;){var at=X[aq];var ab=X[aq+1];var W=aq+2;while(W+2<=Y&&X[W+1]===ab){W+=2}X[ar++]=at;X[ar++]=ab;aq=W}Y=X.length=ar;var ae=null;while(ah<T){var af=aa[ah];var S=aa[ah+2]||an;var ag=X[Z];var ap=X[Z+2]||an;var W=Math.min(S,ap);var ak=aa[ah+1];var U;if(ak.nodeType!==1&&(U=al.substring(V,W))){if(aj){U=U.replace(am,"\r")}ak.nodeValue=U;var ai=ak.ownerDocument;var ao=ai.createElement("SPAN");ao.className=X[Z+1];var ad=ak.parentNode;ad.replaceChild(ao,ak);ao.appendChild(ak);if(V<S){aa[ah+1]=ak=ai.createTextNode(al.substring(W,S));ad.insertBefore(ak,ao.nextSibling)}}V=W;if(V>=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*</.test(S)?"default-markup":"default-code"}return t[T]}c(K,["default-code"]);c(g([],[[F,/^[^<?]+/],[E,/^<!\w[^>]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa<ac.length;++aa){for(var Z=0,V=ac[aa].length;Z<V;++Z){T.push(ac[aa][Z])}}ac=null;var W=Date;if(!W.now){W={now:function(){return +(new Date)}}}var X=0;var S;var ab=/\blang(?:uage)?-([\w.]+)(?!\S)/;var ae=/\bprettyprint\b/;function U(){var ag=(window.PR_SHOULD_USE_CONTINUATION?W.now()+250:Infinity);for(;X<T.length&&W.now()<ag;X++){var aj=T[X];var ai=aj.className;if(ai.indexOf("prettyprint")>=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X<T.length){setTimeout(U,250)}else{if(ad){ad()}}}U()}window.prettyPrintOne=y;window.prettyPrint=b;window.PR={createSimpleLexer:g,registerLangHandler:c,sourceDecorator:i,PR_ATTRIB_NAME:P,PR_ATTRIB_VALUE:n,PR_COMMENT:j,PR_DECLARATION:E,PR_KEYWORD:z,PR_LITERAL:G,PR_NOCODE:N,PR_PLAIN:F,PR_PUNCTUATION:L,PR_SOURCE:J,PR_STRING:C,PR_TAG:m,PR_TYPE:O}})();PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^<script\b[^>]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment