From 861c306351bf6107a843220bb201e8ea81d77e7f Mon Sep 17 00:00:00 2001 From: Anne van Rossum Date: Thu, 21 Feb 2013 18:32:49 +0100 Subject: [PATCH] Version gets info from the drone --- libs/proj4js.js | 1816 +++++++++++++++ node_modules/json-over-tcp/.npmignore | 1 + node_modules/json-over-tcp/.travis.yml | 5 + node_modules/json-over-tcp/LICENSE-MIT | 22 + node_modules/json-over-tcp/README.md | 129 ++ .../json-over-tcp/example/helloWorld.js | 44 + node_modules/json-over-tcp/grunt.js | 59 + node_modules/json-over-tcp/index.js | 14 + node_modules/json-over-tcp/lib/protocol.js | 150 ++ node_modules/json-over-tcp/lib/server.js | 74 + node_modules/json-over-tcp/lib/socket.js | 105 + .../json-over-tcp/node_modules/its/.npmignore | 2 + .../node_modules/its/.travis.yml | 5 + .../node_modules/its/MIT-LICENSE.txt | 20 + .../json-over-tcp/node_modules/its/README.md | 73 + .../node_modules/its/component.json | 9 + .../node_modules/its/dist/its.js | 3 + .../json-over-tcp/node_modules/its/grunt.js | 83 + .../json-over-tcp/node_modules/its/index.js | 1 + .../json-over-tcp/node_modules/its/lib/its.js | 190 ++ .../node_modules/its/package.json | 52 + .../node_modules/its/test/its.html | 14 + .../node_modules/its/test/its.js | 212 ++ .../node_modules/its/test/lib/qunit.js | 1977 +++++++++++++++++ node_modules/json-over-tcp/package.json | 47 + .../json-over-tcp/test/protocol_test.js | 125 ++ .../json-over-tcp/test/server_test.js | 69 + .../json-over-tcp/test/socket_test.js | 108 + package.json | 2 +- server.js | 72 +- static/index.html | 14 + static/model.js | 80 +- 32 files changed, 5558 insertions(+), 19 deletions(-) create mode 100644 libs/proj4js.js create mode 100644 node_modules/json-over-tcp/.npmignore create mode 100644 node_modules/json-over-tcp/.travis.yml create mode 100644 node_modules/json-over-tcp/LICENSE-MIT create mode 100644 node_modules/json-over-tcp/README.md create mode 100644 node_modules/json-over-tcp/example/helloWorld.js create mode 100644 node_modules/json-over-tcp/grunt.js create mode 100644 node_modules/json-over-tcp/index.js create mode 100644 node_modules/json-over-tcp/lib/protocol.js create mode 100644 node_modules/json-over-tcp/lib/server.js create mode 100644 node_modules/json-over-tcp/lib/socket.js create mode 100644 node_modules/json-over-tcp/node_modules/its/.npmignore create mode 100644 node_modules/json-over-tcp/node_modules/its/.travis.yml create mode 100644 node_modules/json-over-tcp/node_modules/its/MIT-LICENSE.txt create mode 100644 node_modules/json-over-tcp/node_modules/its/README.md create mode 100644 node_modules/json-over-tcp/node_modules/its/component.json create mode 100644 node_modules/json-over-tcp/node_modules/its/dist/its.js create mode 100644 node_modules/json-over-tcp/node_modules/its/grunt.js create mode 100644 node_modules/json-over-tcp/node_modules/its/index.js create mode 100644 node_modules/json-over-tcp/node_modules/its/lib/its.js create mode 100644 node_modules/json-over-tcp/node_modules/its/package.json create mode 100644 node_modules/json-over-tcp/node_modules/its/test/its.html create mode 100644 node_modules/json-over-tcp/node_modules/its/test/its.js create mode 100644 node_modules/json-over-tcp/node_modules/its/test/lib/qunit.js create mode 100644 node_modules/json-over-tcp/package.json create mode 100644 node_modules/json-over-tcp/test/protocol_test.js create mode 100644 node_modules/json-over-tcp/test/server_test.js create mode 100644 node_modules/json-over-tcp/test/socket_test.js diff --git a/libs/proj4js.js b/libs/proj4js.js new file mode 100644 index 0000000..2f7f94b --- /dev/null +++ b/libs/proj4js.js @@ -0,0 +1,1816 @@ +/* +Author: Mike Adair madairATdmsolutions.ca + Richard Greenwood rich@greenwoodmap.com +License: LGPL as per: http://www.gnu.org/copyleft/lesser.html + +$Id: Proj.js 2956 2007-07-09 12:17:52Z steven $ +*/ + +/** + * Namespace: Proj4js + * + * Proj4js is a JavaScript library to transform point coordinates from one + * coordinate system to another, including datum transformations. + * + * This library is a port of both the Proj.4 and GCTCP C libraries to JavaScript. + * Enabling these transformations in the browser allows geographic data stored + * in different projections to be combined in browser-based web mapping + * applications. + * + * Proj4js must have access to coordinate system initialization strings (which + * are the same as for PROJ.4 command line). Thes can be included in your + * application using a + + def is a CS definition in PROJ.4 WKT format, for example: + +proj="tmerc" //longlat, etc. + +a=majorRadius + +b=minorRadius + +lat0=somenumber + +long=somenumber +*/ +Proj4js.defs = { + // These are so widely used, we'll go ahead and throw them in + // without requiring a separate .js file + 'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees", + 'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees", + 'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees", + 'EPSG:3875': "+title= Google Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs" +}; +Proj4js.defs['EPSG:3785'] = Proj4js.defs['EPSG:3875']; //maintain backward compat, official code is 3875 +Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3875']; +Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3875']; +Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3875']; + +Proj4js.common = { + PI : 3.141592653589793238, //Math.PI, + HALF_PI : 1.570796326794896619, //Math.PI*0.5, + TWO_PI : 6.283185307179586477, //Math.PI*2, + FORTPI : 0.78539816339744833, + R2D : 57.29577951308232088, + D2R : 0.01745329251994329577, + SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */ + EPSLN : 1.0e-10, + MAX_ITER : 20, + // following constants from geocent.c + COS_67P5 : 0.38268343236508977, /* cosine of 67.5 degrees */ + AD_C : 1.0026000, /* Toms region 1 constant */ + + /* datum_type values */ + PJD_UNKNOWN : 0, + PJD_3PARAM : 1, + PJD_7PARAM : 2, + PJD_GRIDSHIFT: 3, + PJD_WGS84 : 4, // WGS84 or equivalent + PJD_NODATUM : 5, // WGS84 or equivalent + SRS_WGS84_SEMIMAJOR : 6378137.0, // only used in grid shift transforms + + // ellipoid pj_set_ell.c + SIXTH : .1666666666666666667, /* 1/6 */ + RA4 : .04722222222222222222, /* 17/360 */ + RA6 : .02215608465608465608, /* 67/3024 */ + RV4 : .06944444444444444444, /* 5/72 */ + RV6 : .04243827160493827160, /* 55/1296 */ + +// Function to compute the constant small m which is the radius of +// a parallel of latitude, phi, divided by the semimajor axis. +// ----------------------------------------------------------------- + msfnz : function(eccent, sinphi, cosphi) { + var con = eccent * sinphi; + return cosphi/(Math.sqrt(1.0 - con * con)); + }, + +// Function to compute the constant small t for use in the forward +// computations in the Lambert Conformal Conic and the Polar +// Stereographic projections. +// ----------------------------------------------------------------- + tsfnz : function(eccent, phi, sinphi) { + var con = eccent * sinphi; + var com = .5 * eccent; + con = Math.pow(((1.0 - con) / (1.0 + con)), com); + return (Math.tan(.5 * (this.HALF_PI - phi))/con); + }, + +// Function to compute the latitude angle, phi2, for the inverse of the +// Lambert Conformal Conic and Polar Stereographic projections. +// ---------------------------------------------------------------- + phi2z : function(eccent, ts) { + var eccnth = .5 * eccent; + var con, dphi; + var phi = this.HALF_PI - 2 * Math.atan(ts); + for (var i = 0; i <= 15; i++) { + con = eccent * Math.sin(phi); + dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi; + phi += dphi; + if (Math.abs(dphi) <= .0000000001) return phi; + } + alert("phi2z has NoConvergence"); + return (-9999); + }, + +/* Function to compute constant small q which is the radius of a + parallel of latitude, phi, divided by the semimajor axis. +------------------------------------------------------------*/ + qsfnz : function(eccent,sinphi) { + var con; + if (eccent > 1.0e-7) { + con = eccent * sinphi; + return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con)))); + } else { + return(2.0 * sinphi); + } + }, + +/* Function to eliminate roundoff errors in asin +----------------------------------------------*/ + asinz : function(x) { + if (Math.abs(x)>1.0) { + x=(x>1.0)?1.0:-1.0; + } + return Math.asin(x); + }, + +// following functions from gctpc cproj.c for transverse mercator projections + e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));}, + e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));}, + e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));}, + e3fn : function(x) {return(x*x*x*(35.0/3072.0));}, + mlfn : function(e0,e1,e2,e3,phi) {return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));}, + + srat : function(esinp, exp) { + return(Math.pow((1.0-esinp)/(1.0+esinp), exp)); + }, + +// Function to return the sign of an argument + sign : function(x) { if (x < 0.0) return(-1); else return(1);}, + +// Function to adjust longitude to -180 to 180; input in radians + adjust_lon : function(x) { + x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) ); + return x; + }, + +// IGNF - DGR : algorithms used by IGN France + +// Function to adjust latitude to -90 to 90; input in radians + adjust_lat : function(x) { + x= (Math.abs(x) < this.HALF_PI) ? x: (x - (this.sign(x)*this.PI) ); + return x; + }, + +// Latitude Isometrique - close to tsfnz ... + latiso : function(eccent, phi, sinphi) { + if (Math.abs(phi) > this.HALF_PI) return +Number.NaN; + if (phi==this.HALF_PI) return Number.POSITIVE_INFINITY; + if (phi==-1.0*this.HALF_PI) return -1.0*Number.POSITIVE_INFINITY; + + var con= eccent*sinphi; + return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0; + }, + + fL : function(x,L) { + return 2.0*Math.atan(x*Math.exp(L)) - this.HALF_PI; + }, + +// Inverse Latitude Isometrique - close to ph2z + invlatiso : function(eccent, ts) { + var phi= this.fL(1.0,ts); + var Iphi= 0.0; + var con= 0.0; + do { + Iphi= phi; + con= eccent*Math.sin(Iphi); + phi= this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts) + } while (Math.abs(phi-Iphi)>1.0e-12); + return phi; + }, + +// Needed for Gauss Schreiber +// Original: Denis Makarov (info@binarythings.com) +// Web Site: http://www.binarythings.com + sinh : function(x) + { + var r= Math.exp(x); + r= (r-1.0/r)/2.0; + return r; + }, + + cosh : function(x) + { + var r= Math.exp(x); + r= (r+1.0/r)/2.0; + return r; + }, + + tanh : function(x) + { + var r= Math.exp(x); + r= (r-1.0/r)/(r+1.0/r); + return r; + }, + + asinh : function(x) + { + var s= (x>= 0? 1.0:-1.0); + return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) )); + }, + + acosh : function(x) + { + return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0)); + }, + + atanh : function(x) + { + return Math.log((x-1.0)/(x+1.0))/2.0; + }, + +// Grande Normale + gN : function(a,e,sinphi) + { + var temp= e*sinphi; + return a/Math.sqrt(1.0 - temp*temp); + }, + + //code from the PROJ.4 pj_mlfn.c file; this may be useful for other projections + pj_enfn: function(es) { + var en = new Array(); + en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08))); + en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08))); + var t = es * es; + en[2] = t * (this.C44 - es * (this.C46 + es * this.C48)); + t *= es; + en[3] = t * (this.C66 - es * this.C68); + en[4] = t * es * this.C88; + return en; + }, + + pj_mlfn: function(phi, sphi, cphi, en) { + cphi *= sphi; + sphi *= sphi; + return(en[0] * phi - cphi * (en[1] + sphi*(en[2]+ sphi*(en[3] + sphi*en[4])))); + }, + + pj_inv_mlfn: function(arg, es, en) { + var k = 1./(1.-es); + var phi = arg; + for (var i = Proj4js.common.MAX_ITER; i ; --i) { /* rarely goes over 2 iterations */ + var s = Math.sin(phi); + var t = 1. - es * s * s; + //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg; + //phi -= t * (t * Math.sqrt(t)) * k; + t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k; + phi -= t; + if (Math.abs(t) < Proj4js.common.EPSLN) + return phi; + } + Proj4js.reportError("cass:pj_inv_mlfn: Convergence error"); + return phi; + }, + +/* meridinal distance for ellipsoid and inverse +** 8th degree - accurate to < 1e-5 meters when used in conjuction +** with typical major axis values. +** Inverse determines phi to EPS (1e-11) radians, about 1e-6 seconds. +*/ + C00: 1.0, + C02: .25, + C04: .046875, + C06: .01953125, + C08: .01068115234375, + C22: .75, + C44: .46875, + C46: .01302083333333333333, + C48: .00712076822916666666, + C66: .36458333333333333333, + C68: .00569661458333333333, + C88: .3076171875 + +}; + +/** datum object +*/ +Proj4js.datum = Proj4js.Class({ + + initialize : function(proj) { + this.datum_type = Proj4js.common.PJD_WGS84; //default setting + if (proj.datumCode && proj.datumCode == 'none') { + this.datum_type = Proj4js.common.PJD_NODATUM; + } + if (proj && proj.datum_params) { + for (var i=0; i 3) { + if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 || + proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) { + this.datum_type = Proj4js.common.PJD_7PARAM; + proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD; + proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD; + proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD; + proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0; + } + } + } + if (proj) { + this.a = proj.a; //datum object also uses these values + this.b = proj.b; + this.es = proj.es; + this.ep2 = proj.ep2; + this.datum_params = proj.datum_params; + } + }, + + /****************************************************************/ + // cs_compare_datums() + // Returns TRUE if the two datums match, otherwise FALSE. + compare_datums : function( dest ) { + if( this.datum_type != dest.datum_type ) { + return false; // false, datums are not equal + } else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) { + // the tolerence for es is to ensure that GRS80 and WGS84 + // are considered identical + return false; + } else if( this.datum_type == Proj4js.common.PJD_3PARAM ) { + return (this.datum_params[0] == dest.datum_params[0] + && this.datum_params[1] == dest.datum_params[1] + && this.datum_params[2] == dest.datum_params[2]); + } else if( this.datum_type == Proj4js.common.PJD_7PARAM ) { + return (this.datum_params[0] == dest.datum_params[0] + && this.datum_params[1] == dest.datum_params[1] + && this.datum_params[2] == dest.datum_params[2] + && this.datum_params[3] == dest.datum_params[3] + && this.datum_params[4] == dest.datum_params[4] + && this.datum_params[5] == dest.datum_params[5] + && this.datum_params[6] == dest.datum_params[6]); + } else if ( this.datum_type == Proj4js.common.PJD_GRIDSHIFT || + dest.datum_type == Proj4js.common.PJD_GRIDSHIFT ) { + alert("ERROR: Grid shift transformations are not implemented."); + return false + } else { + return true; // datums are equal + } + }, // cs_compare_datums() + + /* + * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates + * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z), + * according to the current ellipsoid parameters. + * + * Latitude : Geodetic latitude in radians (input) + * Longitude : Geodetic longitude in radians (input) + * Height : Geodetic height, in meters (input) + * X : Calculated Geocentric X coordinate, in meters (output) + * Y : Calculated Geocentric Y coordinate, in meters (output) + * Z : Calculated Geocentric Z coordinate, in meters (output) + * + */ + geodetic_to_geocentric : function(p) { + var Longitude = p.x; + var Latitude = p.y; + var Height = p.z ? p.z : 0; //Z value not always supplied + var X; // output + var Y; + var Z; + + var Error_Code=0; // GEOCENT_NO_ERROR; + var Rn; /* Earth radius at location */ + var Sin_Lat; /* Math.sin(Latitude) */ + var Sin2_Lat; /* Square of Math.sin(Latitude) */ + var Cos_Lat; /* Math.cos(Latitude) */ + + /* + ** Don't blow up if Latitude is just a little out of the value + ** range as it may just be a rounding issue. Also removed longitude + ** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001. + */ + if( Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) { + Latitude = -Proj4js.common.HALF_PI; + } else if( Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) { + Latitude = Proj4js.common.HALF_PI; + } else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) { + /* Latitude out of range */ + Proj4js.reportError('geocent:lat out of range:'+Latitude); + return null; + } + + if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI); + Sin_Lat = Math.sin(Latitude); + Cos_Lat = Math.cos(Latitude); + Sin2_Lat = Sin_Lat * Sin_Lat; + Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat)); + X = (Rn + Height) * Cos_Lat * Math.cos(Longitude); + Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude); + Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat; + + p.x = X; + p.y = Y; + p.z = Z; + return Error_Code; + }, // cs_geodetic_to_geocentric() + + + geocentric_to_geodetic : function (p) { +/* local defintions and variables */ +/* end-criterium of loop, accuracy of sin(Latitude) */ +var genau = 1.E-12; +var genau2 = (genau*genau); +var maxiter = 30; + + var P; /* distance between semi-minor axis and location */ + var RR; /* distance between center and location */ + var CT; /* sin of geocentric latitude */ + var ST; /* cos of geocentric latitude */ + var RX; + var RK; + var RN; /* Earth radius at location */ + var CPHI0; /* cos of start or old geodetic latitude in iterations */ + var SPHI0; /* sin of start or old geodetic latitude in iterations */ + var CPHI; /* cos of searched geodetic latitude */ + var SPHI; /* sin of searched geodetic latitude */ + var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */ + var At_Pole; /* indicates location is in polar region */ + var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */ + + var X = p.x; + var Y = p.y; + var Z = p.z ? p.z : 0.0; //Z value not always supplied + var Longitude; + var Latitude; + var Height; + + At_Pole = false; + P = Math.sqrt(X*X+Y*Y); + RR = Math.sqrt(X*X+Y*Y+Z*Z); + +/* special cases for latitude and longitude */ + if (P/this.a < genau) { + +/* special case, if P=0. (X=0., Y=0.) */ + At_Pole = true; + Longitude = 0.0; + +/* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis + * of ellipsoid (=center of mass), Latitude becomes PI/2 */ + if (RR/this.a < genau) { + Latitude = Proj4js.common.HALF_PI; + Height = -this.b; + return; + } + } else { +/* ellipsoidal (geodetic) longitude + * interval: -PI < Longitude <= +PI */ + Longitude=Math.atan2(Y,X); + } + +/* -------------------------------------------------------------- + * Following iterative algorithm was developped by + * "Institut f�r Erdmessung", University of Hannover, July 1988. + * Internet: www.ife.uni-hannover.de + * Iterative computation of CPHI,SPHI and Height. + * Iteration of CPHI and SPHI to 10**-12 radian resp. + * 2*10**-7 arcsec. + * -------------------------------------------------------------- + */ + CT = Z/RR; + ST = P/RR; + RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST); + CPHI0 = ST*(1.0-this.es)*RX; + SPHI0 = CT*RX; + iter = 0; + +/* loop to find sin(Latitude) resp. Latitude + * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */ + do + { + iter++; + RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0); + +/* ellipsoidal (geodetic) height */ + Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0); + + RK = this.es*RN/(RN+Height); + RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST); + CPHI = ST*(1.0-RK)*RX; + SPHI = CT*RX; + SDPHI = SPHI*CPHI0-CPHI*SPHI0; + CPHI0 = CPHI; + SPHI0 = SPHI; + } + while (SDPHI*SDPHI > genau2 && iter < maxiter); + +/* ellipsoidal (geodetic) latitude */ + Latitude=Math.atan(SPHI/Math.abs(CPHI)); + + p.x = Longitude; + p.y = Latitude; + p.z = Height; + return p; + }, // cs_geocentric_to_geodetic() + + /** Convert_Geocentric_To_Geodetic + * The method used here is derived from 'An Improved Algorithm for + * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996 + */ + geocentric_to_geodetic_noniter : function (p) { + var X = p.x; + var Y = p.y; + var Z = p.z ? p.z : 0; //Z value not always supplied + var Longitude; + var Latitude; + var Height; + + var W; /* distance from Z axis */ + var W2; /* square of distance from Z axis */ + var T0; /* initial estimate of vertical component */ + var T1; /* corrected estimate of vertical component */ + var S0; /* initial estimate of horizontal component */ + var S1; /* corrected estimate of horizontal component */ + var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */ + var Sin3_B0; /* cube of Math.sin(B0) */ + var Cos_B0; /* Math.cos(B0) */ + var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */ + var Cos_p1; /* Math.cos(phi1) */ + var Rn; /* Earth radius at location */ + var Sum; /* numerator of Math.cos(phi1) */ + var At_Pole; /* indicates location is in polar region */ + + X = parseFloat(X); // cast from string to float + Y = parseFloat(Y); + Z = parseFloat(Z); + + At_Pole = false; + if (X != 0.0) + { + Longitude = Math.atan2(Y,X); + } + else + { + if (Y > 0) + { + Longitude = Proj4js.common.HALF_PI; + } + else if (Y < 0) + { + Longitude = -Proj4js.common.HALF_PI; + } + else + { + At_Pole = true; + Longitude = 0.0; + if (Z > 0.0) + { /* north pole */ + Latitude = Proj4js.common.HALF_PI; + } + else if (Z < 0.0) + { /* south pole */ + Latitude = -Proj4js.common.HALF_PI; + } + else + { /* center of earth */ + Latitude = Proj4js.common.HALF_PI; + Height = -this.b; + return; + } + } + } + W2 = X*X + Y*Y; + W = Math.sqrt(W2); + T0 = Z * Proj4js.common.AD_C; + S0 = Math.sqrt(T0 * T0 + W2); + Sin_B0 = T0 / S0; + Cos_B0 = W / S0; + Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0; + T1 = Z + this.b * this.ep2 * Sin3_B0; + Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0; + S1 = Math.sqrt(T1*T1 + Sum * Sum); + Sin_p1 = T1 / S1; + Cos_p1 = Sum / S1; + Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1); + if (Cos_p1 >= Proj4js.common.COS_67P5) + { + Height = W / Cos_p1 - Rn; + } + else if (Cos_p1 <= -Proj4js.common.COS_67P5) + { + Height = W / -Cos_p1 - Rn; + } + else + { + Height = Z / Sin_p1 + Rn * (this.es - 1.0); + } + if (At_Pole == false) + { + Latitude = Math.atan(Sin_p1 / Cos_p1); + } + + p.x = Longitude; + p.y = Latitude; + p.z = Height; + return p; + }, // geocentric_to_geodetic_noniter() + + /****************************************************************/ + // pj_geocentic_to_wgs84( p ) + // p = point to transform in geocentric coordinates (x,y,z) + geocentric_to_wgs84 : function ( p ) { + + if( this.datum_type == Proj4js.common.PJD_3PARAM ) + { + // if( x[io] == HUGE_VAL ) + // continue; + p.x += this.datum_params[0]; + p.y += this.datum_params[1]; + p.z += this.datum_params[2]; + + } + else if (this.datum_type == Proj4js.common.PJD_7PARAM) + { + var Dx_BF =this.datum_params[0]; + var Dy_BF =this.datum_params[1]; + var Dz_BF =this.datum_params[2]; + var Rx_BF =this.datum_params[3]; + var Ry_BF =this.datum_params[4]; + var Rz_BF =this.datum_params[5]; + var M_BF =this.datum_params[6]; + // if( x[io] == HUGE_VAL ) + // continue; + var x_out = M_BF*( p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF; + var y_out = M_BF*( Rz_BF*p.x + p.y - Rx_BF*p.z) + Dy_BF; + var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y + p.z) + Dz_BF; + p.x = x_out; + p.y = y_out; + p.z = z_out; + } + }, // cs_geocentric_to_wgs84 + + /****************************************************************/ + // pj_geocentic_from_wgs84() + // coordinate system definition, + // point to transform in geocentric coordinates (x,y,z) + geocentric_from_wgs84 : function( p ) { + + if( this.datum_type == Proj4js.common.PJD_3PARAM ) + { + //if( x[io] == HUGE_VAL ) + // continue; + p.x -= this.datum_params[0]; + p.y -= this.datum_params[1]; + p.z -= this.datum_params[2]; + + } + else if (this.datum_type == Proj4js.common.PJD_7PARAM) + { + var Dx_BF =this.datum_params[0]; + var Dy_BF =this.datum_params[1]; + var Dz_BF =this.datum_params[2]; + var Rx_BF =this.datum_params[3]; + var Ry_BF =this.datum_params[4]; + var Rz_BF =this.datum_params[5]; + var M_BF =this.datum_params[6]; + var x_tmp = (p.x - Dx_BF) / M_BF; + var y_tmp = (p.y - Dy_BF) / M_BF; + var z_tmp = (p.z - Dz_BF) / M_BF; + //if( x[io] == HUGE_VAL ) + // continue; + + p.x = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp; + p.y = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp; + p.z = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp; + } //cs_geocentric_from_wgs84() + } +}); + +/** point object, nothing fancy, just allows values to be + passed back and forth by reference rather than by value. + Other point classes may be used as long as they have + x and y properties, which will get modified in the transform method. +*/ +Proj4js.Point = Proj4js.Class({ + + /** + * Constructor: Proj4js.Point + * + * Parameters: + * - x {float} or {Array} either the first coordinates component or + * the full coordinates + * - y {float} the second component + * - z {float} the third component, optional. + */ + initialize : function(x,y,z) { + if (typeof x == 'object') { + this.x = x[0]; + this.y = x[1]; + this.z = x[2] || 0.0; + } else if (typeof x == 'string' && typeof y == 'undefined') { + var coords = x.split(','); + this.x = parseFloat(coords[0]); + this.y = parseFloat(coords[1]); + this.z = parseFloat(coords[2]) || 0.0; + } else { + this.x = x; + this.y = y; + this.z = z || 0.0; + } + }, + + /** + * APIMethod: clone + * Build a copy of a Proj4js.Point object. + * + * Return: + * {Proj4js}.Point the cloned point. + */ + clone : function() { + return new Proj4js.Point(this.x, this.y, this.z); + }, + + /** + * APIMethod: toString + * Return a readable string version of the point + * + * Return: + * {String} String representation of Proj4js.Point object. + * (ex. "x=5,y=42") + */ + toString : function() { + return ("x=" + this.x + ",y=" + this.y); + }, + + /** + * APIMethod: toShortString + * Return a short string version of the point. + * + * Return: + * {String} Shortened String representation of Proj4js.Point object. + * (ex. "5, 42") + */ + toShortString : function() { + return (this.x + ", " + this.y); + } +}); + +Proj4js.PrimeMeridian = { + "greenwich": 0.0, //"0dE", + "lisbon": -9.131906111111, //"9d07'54.862\"W", + "paris": 2.337229166667, //"2d20'14.025\"E", + "bogota": -74.080916666667, //"74d04'51.3\"W", + "madrid": -3.687938888889, //"3d41'16.58\"W", + "rome": 12.452333333333, //"12d27'8.4\"E", + "bern": 7.439583333333, //"7d26'22.5\"E", + "jakarta": 106.807719444444, //"106d48'27.79\"E", + "ferro": -17.666666666667, //"17d40'W", + "brussels": 4.367975, //"4d22'4.71\"E", + "stockholm": 18.058277777778, //"18d3'29.8\"E", + "athens": 23.7163375, //"23d42'58.815\"E", + "oslo": 10.722916666667 //"10d43'22.5\"E" +}; + +Proj4js.Ellipsoid = { + "MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"}, + "SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"}, + "GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"}, + "IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"}, + "airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"}, + "APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"}, + "NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"}, + "mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"}, + "andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"}, + "aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"}, + "GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"}, + "bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"}, + "bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"}, + "clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"}, + "clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."}, + "CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"}, + "delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"}, + "engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"}, + "evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"}, + "evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"}, + "evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"}, + "evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"}, + "evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"}, + "fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"}, + "fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"}, + "fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"}, + "helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"}, + "hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"}, + "intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"}, + "kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"}, + "lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"}, + "mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"}, + "new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"}, + "plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"}, + "krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"}, + "SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"}, + "walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"}, + "WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"}, + "WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"}, + "WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"}, + "WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"}, + "sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"} +}; + +Proj4js.Datum = { + "WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84"}, + "GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"}, + "NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"}, + "NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"}, + "potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"}, + "carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"}, + "hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"}, + "ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"}, + "nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"}, + "OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"} +}; + +Proj4js.WGS84 = new Proj4js.Proj('WGS84'); +Proj4js.Datum['OSB36'] = Proj4js.Datum['OSGB36']; //as returned from spatialreference.org + +//lookup table to go from the projection name in WKT to the Proj4js projection name +//build this out as required +Proj4js.wktProjections = { + "Lambert Tangential Conformal Conic Projection": "lcc", + "Mercator": "merc", + "Popular Visualisation Pseudo Mercator": "merc", + "Mercator_1SP": "merc", + "Transverse_Mercator": "tmerc", + "Transverse Mercator": "tmerc", + "Lambert Azimuthal Equal Area": "laea", + "Universal Transverse Mercator System": "utm" +}; + + diff --git a/node_modules/json-over-tcp/.npmignore b/node_modules/json-over-tcp/.npmignore new file mode 100644 index 0000000..08b2553 --- /dev/null +++ b/node_modules/json-over-tcp/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/json-over-tcp/.travis.yml b/node_modules/json-over-tcp/.travis.yml new file mode 100644 index 0000000..921956d --- /dev/null +++ b/node_modules/json-over-tcp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 +before_install: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/json-over-tcp/LICENSE-MIT b/node_modules/json-over-tcp/LICENSE-MIT new file mode 100644 index 0000000..79d9275 --- /dev/null +++ b/node_modules/json-over-tcp/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Ozan Turgut + +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. \ No newline at end of file diff --git a/node_modules/json-over-tcp/README.md b/node_modules/json-over-tcp/README.md new file mode 100644 index 0000000..943d0ef --- /dev/null +++ b/node_modules/json-over-tcp/README.md @@ -0,0 +1,129 @@ +# jot (json-over-tcp) [![Build Status](https://secure.travis-ci.org/ozanturgut/json-over-tcp.png?branch=master)](http://travis-ci.org/ozanturgut/json-over-tcp) + +Node.js TCP server/client messaging in JSON. + +This library provides a server and a socket class (with APIs that are very similar to the net package in Node.js) which communicate +by sending each other JSON messages. + +You "write" JSON objects to the socket, and the "data" events on the other end of the socket emits the JSON object you wrote. + +## A Short Illustration +``` javascript +// assume that I have a jot server listening somewhere and I created a connection to it called "connection" +var someObject = { + "this property is null": null, + 1928: 3734, + turtle: { + neck: "sweater" + } +}; + +connection.write(someObject); +// Whatever is listening to this connection on the server-side will now recieve a "data" event with an object that +// has the same values as "someObject". +``` + + +## A Real Example +``` javascript +// This script will output "Client's question: Hello, world?" and "Server's answer: 42" in alternating order +// every second until the script is stopped. + +var someRandomPort = 8099, + jot = require('json-over-tcp'); + +var server = jot.createServer(someRandomPort); +server.on('listening', createConnection); +server.on('connection', newConnectionHandler); + +// Triggered whenever something connects to the server +function newConnectionHandler(socket){ + // Whenever a connection sends us an object... + socket.on('data', function(data){ + // Output the question property of the client's message to the console + console.log("Client's question: " + data.question); + + // Wait one second, then write an answer to the client's socket + setTimeout(function(){ + socket.write({answer: 42}); + }, 1000); + }); +}; + +// Creates one connection to the server when the server starts listening +function createConnection(){ + // Start a connection to the server + var socket = jot.connect(someRandomPort, function(){ + // Send the initial message once connected + socket.write({question: "Hello, world?"}); + }); + + // Whenever the server sends us an object... + socket.on('data', function(data){ + // Output the answer property of the server's message to the console + console.log("Server's answer: " + data.answer); + + // Wait one second, then write a question to the socket + setTimeout(function(){ + // Notice that we "write" a JSON object to the socket + socket.write({question: "Hello, world?"}); + }, 1000); + }); +} + +// Start listening +server.listen(someRandomPort); +``` + +## API +The factory functions below behave similar to node's net package (but they return jot versions of the server or socket). +### ```jot.createServer([options], [connectionListener])``` +See [```net.createServer([options], [connectionListener])```](http://nodejs.org/api/net.html#net_net_createserver_options_connectionlistener). +### ```jot.connect(options, [connectionListener])``` +See [```net.connect(options, [connectionListener])```](http://nodejs.org/api/net.html#net_net_connect_options_connectionlistener). +### ```jot.createConnection(options, [connectionListener])``` +See [```net.createConnection(options, [connectionListener])```](http://nodejs.org/api/net.html#net_net_connect_options_connectionlistener). +### ```jot.connect(port, [host], [connectListener])``` +See [```net.connect(port, [host], [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener). +### ```jot.createConnection(options, [connectionListener])``` +See [```net.createConnection(port, [host], [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener). +### ```jot.connect(path, [connectListener])``` +See [```net.connect(path, [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_path_connectlistener). +### ```jot.createConnection(path, [connectListener])``` +See [```net.createConnection(path, [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_path_connectlistener). +### ```jot.createProtocol(stream)``` +Factory function for creating a jot protocol object. +### ```jot.createSocket([options])``` +Factory function for creating a jot socket. + +### ```jot.Server``` +>The server API is the same as the [```Server``` API in the native 'net' module](http://nodejs.org/api/net.html#net_class_net_server) with the following differences: +##### ```Event: 'connection'``` +Emits a jot socket (see it's API below) instead of a plain tcp socket. + +### ```jot.Socket``` +>The socket API is the same as the [```Socket``` API in the native 'net' module](http://nodejs.org/api/net.html#net_class_net_socket) with the following differences: +##### ```Event: 'data'``` +Emits a JSON object which was sent by the other end of the socket. +##### ```write(obj)``` +Sends an object to the other end of the socket. This method doesn't accept any of the other parameters as the plain tcp socket. + +### ```jot.Protocol``` +> The protocol object is what serializes/deserializes JSON data over the wire. +##### new Protocol(stream) +Takes in a [```Stream```](http://nodejs.org/api/stream.html) object and reads/writes JSON objects using it's a simple protocol (a protocol signature, message length, and stringified JSON). +##### ```write(obj)``` +Writes an object which can be stringified to the stream. +##### ```on``` +Bind to an event (```'data'``` is the only one ever emitted). +##### ```removeListener``` +Remove a bound listener. +##### ```Event: 'data'``` +Emits a JSON object whenever a stream message is recieved. + +## Protocol +If you would like to implement the protocol yourself, the server will expect the following in order in the byte stream: + +1. 16-bit unsigned little-endian integer with 206 as the value. This is the protocol signature, if a message is sent without this signature a protocol error will be raised. +2. A 32-bit unsigned little-endian integer with the length of the message being sent as the value. +3. A UTF-8 string with the stringified JSON as the value (the message). diff --git a/node_modules/json-over-tcp/example/helloWorld.js b/node_modules/json-over-tcp/example/helloWorld.js new file mode 100644 index 0000000..e0d2aff --- /dev/null +++ b/node_modules/json-over-tcp/example/helloWorld.js @@ -0,0 +1,44 @@ +var someRandomPort = 8099, + jsonOverTCP = require('../'); + +var server = jsonOverTCP.createServer(someRandomPort); +server.on('listening', createConnection); +server.on('connection', newConnectionHandler); + +// Triggered when something connects to the server +function newConnectionHandler(socket){ + // Whenever a connection sends us an object... + socket.on('data', function(data){ + // Output the question property of the client's message to the console + console.log("Client's question: " + data.question); + + // Wait one second, then write an answer to the client's socket + setTimeout(function(){ + socket.write({answer: 42}); + }, 1000); + }); +}; + +// Creates one connection when the server starts listening +function createConnection(){ + // Start a connection to the server + var socket = jsonOverTCP.connect(someRandomPort, function(){ + // Send the initial message once connected + socket.write({question: "Hello, world?"}); + }); + + // Whenever the server sends us an object... + socket.on('data', function(data){ + // Output the answer property of the server's message to the console + console.log("Server's answer: " + data.answer); + + // Wait one second, then write a question to the socket + setTimeout(function(){ + // Notice that we "write" a JSON object to the socket + socket.write({question: "Hello, world?"}); + }, 1000); + }); +} + +// Start listening +server.listen(someRandomPort); \ No newline at end of file diff --git a/node_modules/json-over-tcp/grunt.js b/node_modules/json-over-tcp/grunt.js new file mode 100644 index 0000000..d6f6db5 --- /dev/null +++ b/node_modules/json-over-tcp/grunt.js @@ -0,0 +1,59 @@ +var JSHINT_NODE = { + node: true, + es5: true +}; + +var LINT_OPTIONS = { + quotmark: 'single', + camelcase: true, + strict: true, + trailing: true, + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true +}; + +module.exports = function(grunt) { + // Project configuration. + grunt.initConfig({ + pkg: '', + files: { + lib: ['lib/*.js'], + test: ['test/*_test.js'] + }, + meta: { + banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + }, + lint: { + lib: '', + test: '' + }, + + test: { + lib: '' + }, + + jshint: { + lib: { + options: JSHINT_NODE + }, + test: { + options: JSHINT_NODE + }, + options: LINT_OPTIONS, + globals: {} + } + }); + + grunt.registerTask('default', 'lint test'); +}; \ No newline at end of file diff --git a/node_modules/json-over-tcp/index.js b/node_modules/json-over-tcp/index.js new file mode 100644 index 0000000..3c4918d --- /dev/null +++ b/node_modules/json-over-tcp/index.js @@ -0,0 +1,14 @@ +var server = require('./lib/server.js'), + socket = require('./lib/socket.js'), + protocol = require('./lib/protocol.js'); + +exports.Server = server.Server; +exports.createServer = server.create; + +exports.Protocol = protocol.Protocol; +exports.createProtocol = protocol.create; +exports.ProtocolError = protocol.ProtocolError; + +exports.Socket = socket.Socket; +exports.createSocket = socket.create; +exports.createConnection = exports.connect = socket.connect; diff --git a/node_modules/json-over-tcp/lib/protocol.js b/node_modules/json-over-tcp/lib/protocol.js new file mode 100644 index 0000000..a4e653d --- /dev/null +++ b/node_modules/json-over-tcp/lib/protocol.js @@ -0,0 +1,150 @@ +"use strict"; + +var net = require('net'), + its = require('its'), + EventEmitter = require('events').EventEmitter; + +exports.create = function(stream){ + var protocol = new Protocol(stream); + return protocol; +}; + +var ProtocolError = exports.ProtocolError = function(){ + Error.apply(this, arguments); +}; +ProtocolError.prototype = Object.create(Error.prototype); + +var Protocol = exports.Protocol = function(stream){ + its.object(stream, "A stream is required"); + + var self = this; + + stream.on('data', function(data){ + self._read(data, 0); + }); + + this._emitter = new EventEmitter(); + this._tempBuff = new Buffer(4); + this._tempBuffLen = 0; + this._stream = stream; + + this._buffer = void 0; + this._bufferOffset = 0; + this._bufferLength = 0; +}; + +Protocol.prototype._SIGNATURE = 206; // must be less than 65536 + +Protocol.prototype.write = function(obj){ + var message = JSON.stringify(obj), + messageLength, + buffer; + + if(message === void 0) return; + + messageLength = Buffer.byteLength(message, 'utf8'); + buffer = new Buffer(messageLength + 6); + + buffer.writeUInt16LE(this._SIGNATURE, 0); + buffer.writeUInt32LE(messageLength, 2); + buffer.write(message, 6); + + this._stream.write(buffer); +}; + +Protocol.prototype._read = function(packet){ + var packetLength = packet.length, + packetOffset = 0, + bufferRemainderLength, + packetRemainderLength; + + its.type(packet instanceof Buffer, 'Packet must be a Buffer instance.'); + + for(;;){ // Forever until break + if(this._bufferLength === 0){ // If we're waiting to parse a new message + if(!this._signatureFound){ + if(packetOffset + 2 > packetLength){ // If we're at a packet boundary + packet.copy(this._tempBuff, 0, packetOffset, packetLength); + this._tempBuffLen = packetLength - packetOffset; + break; + } else if(this._tempBuffLen > 0){ // If we were just at a packet boundary + packet.copy(this._tempBuff, this._tempBuffLen, 0, 1); + this._signatureFound = this._tempBuff.readUInt16LE(packetOffset) === this._SIGNATURE; + this._tempBuffLen = 0; + packetOffset += 1; + } else { + this._signatureFound = packet.readUInt16LE(packetOffset) === this._SIGNATURE; + packetOffset += 2; + } + + if(!this._signatureFound){ + this._emitter.emit('error', new ProtocolError('Was expected message start signature')); + this._cancel(); + } + + this._signatureFound = true; + } + + if(packetOffset + 4 > packetLength){ // If we're at a packet boundary + packet.copy(this._tempBuff, 0, packetOffset, packetLength); + this._tempBuffLen = packetLength - packetOffset; + break; + } else if(this._tempBuffLen > 0){ // If we were just at a packet boundary + packet.copy(this._tempBuff, this._tempBuffLen, 0, 4 - this._tempBuffLen); + packetOffset += 4 - (this._tempBuffLen); + + this._bufferLength = this._tempBuff.readUInt32LE(0); + this._tempBuffLen = 0; + } else { + this._bufferLength = packet.readUInt32LE(packetOffset); + packetOffset += 4; + } + + + this._buffer = new Buffer(this._bufferLength); + this._bufferOffset = 0; + + if(packetOffset === packetLength) break; + } + + bufferRemainderLength = this._bufferLength - this._bufferOffset; + packetRemainderLength = packetLength - packetOffset; + + if(bufferRemainderLength > packetRemainderLength){ + packet.copy(this._buffer, this._bufferOffset, packetOffset, packetLength); + this._bufferOffset += packetRemainderLength; + break; // packet consumed + } else if (bufferRemainderLength === packetRemainderLength) { + packet.copy(this._buffer, this._bufferOffset, packetOffset, packetLength); + this._parseBuffer(); + break; // packet consumed + } else { // bufferRemainderLength < packetRemainderLength + packet.copy(this._buffer, this._bufferOffset, packetOffset, packetOffset + bufferRemainderLength); + this._parseBuffer(); + packetOffset += bufferRemainderLength; + } + } +}; + +Protocol.prototype._cancel = function(){ + this._bufferLength = 0; // reset buffer + this._buffer = void 0; + this._signatureFound = false; +}; + +Protocol.prototype._parseBuffer = function(){ + var jsonString = this._buffer.toString('utf-8'), + data = JSON.parse(jsonString); + + this._emitter.emit('data', data); + this._bufferLength = 0; // reset buffer + this._signatureFound = false; +}; + +Protocol.prototype.on = function(event, callback){ + this._emitter.on(event, callback); +}; + +Protocol.prototype.removeListener = function(event, callback){ + this._emitter.removeListener(event, callback); +}; diff --git a/node_modules/json-over-tcp/lib/server.js b/node_modules/json-over-tcp/lib/server.js new file mode 100644 index 0000000..c40e1a0 --- /dev/null +++ b/node_modules/json-over-tcp/lib/server.js @@ -0,0 +1,74 @@ +"use strict"; + +var net = require('net'), + EventEmitter = require('events').EventEmitter, + createSocket = require('./socket.js').create; + +exports.create = function(options, listener){ + var server = new Server(options, listener); + return server; +}; + +var Server = exports.Server = function(options, listener){ + var self = this; + this._server = new net.Server(options, listener); + this._emitter = new EventEmitter(); + + Object.defineProperty(this, 'connections', { + get: function() { + return self._server.connections; + }, + enumerable: true + }); + + this._server.on('connection', this._connectionHandler.bind(this)); + this._server.on('listening', function(){ + self._emitter.emit('listening'); + }); + this._server.on('close', function(){ + self._emitter.emit('close'); + }); + this._server.on('error', function(e){ + self._emitter.emit('error', e); + }); +}; + +Server.prototype.listen = function(){ + this._server.listen.apply(this._server, arguments); + return this; +}; + +Server.prototype.close = function(){ + this._server.close.apply(this._server, arguments); + return this; +}; + +Server.prototype.address = function(){ + return this._server.address.apply(this._server, arguments); +}; + +Server.prototype.addListener = Server.prototype.on = function(){ + this._emitter.on.apply(this._emitter, arguments); + return this; +}; + +Server.prototype.once = function(){ + this._emitter.once.apply(this._emitter, arguments); + return this; +}; + +Server.prototype.removeListener = function(){ + this._emitter.removeListener.apply(this._emitter, arguments); + return this; +}; + +Server.prototype._connectionHandler = function(socket){ + if (this.maxConnections && this._connections >= this.maxConnections) { + socket.close(); + return; + } + + var protocolSocket = createSocket(socket); + + this._emitter.emit('connection', protocolSocket); +}; diff --git a/node_modules/json-over-tcp/lib/socket.js b/node_modules/json-over-tcp/lib/socket.js new file mode 100644 index 0000000..e601a61 --- /dev/null +++ b/node_modules/json-over-tcp/lib/socket.js @@ -0,0 +1,105 @@ +"use strict"; + +var net = require('net'), + EventEmitter = require('events').EventEmitter, + createProtocol = require('./protocol.js').create; + +exports.create = function(socketOrOptions){ + var socket = new Socket(socketOrOptions); + return socket; +}; + +exports.connect = function(){ + var socket = new Socket(net.connect.apply(void 0, arguments)); + return socket; +}; + +var Socket = exports.Socket = function(socketOrOptions){ + var self = this; + + if(socketOrOptions instanceof net.Socket){ + this._socket = socketOrOptions; + } else { + socketOrOptions = socketOrOptions || {}; + this._socket = new net.Socket(socketOrOptions); + } + + this._emitter = new EventEmitter(); + this._protocol = createProtocol(this._socket); + + this._protocol.on('data', function(data){ + self._emitter.emit('data', data); + }); + + this._protocol.on('error', function(err){ + self._emitter.emit('error', err); + self.end(); + }); + + // Relay some of the socket events that don't need to be handled + [ 'connect', + 'end', + 'close', + 'timeout', + 'drain', + 'error' + ].forEach(function(event){ + self._socket.on(event, function(data){ + self._emitter.emit(event, data); + }); + }); + + // Relay some of the socket properties that don't need to be handled + [ 'remoteAddress', + 'remotePort', + 'bytesRead', + 'bytesWritten', + 'bufferSize' + ].forEach(function(propertyName){ + Object.defineProperty(self, propertyName, { + get: function() { + return self._socket[propertyName]; + }, + enumerable: true + }); + }); + + // Relay some of the socket functions that don't need to be handled + [ 'connect', + 'destroy', + 'pause', + 'resume', + 'setTimeout', + 'setNoDelay', + 'setKeepAlive', + 'address' + ].forEach(function(functionName){ + self[functionName] = function(){ + return self._socket[functionName].apply(self._socket, arguments); + }; + }); +}; + +Socket.prototype.write = function(data){ + this._protocol.write(data); +}; + +Socket.prototype.end = function(data){ + if(data){ + this.write(data); + } + + this._socket.end(); +}; + +Socket.prototype.addListener = Socket.prototype.on = function(){ + return this._emitter.on.apply(this._emitter, arguments); +}; + +Socket.prototype.once = function(){ + return this._emitter.once.apply(this._emitter, arguments); +}; + +Socket.prototype.removeListener = function(){ + return this._emitter.removeListener.apply(this._emitter, arguments); +}; \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/.npmignore b/node_modules/json-over-tcp/node_modules/its/.npmignore new file mode 100644 index 0000000..3eee819 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/.npmignore @@ -0,0 +1,2 @@ +node_modules +build diff --git a/node_modules/json-over-tcp/node_modules/its/.travis.yml b/node_modules/json-over-tcp/node_modules/its/.travis.yml new file mode 100644 index 0000000..921956d --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 +before_install: + - npm install -g grunt-cli \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/MIT-LICENSE.txt b/node_modules/json-over-tcp/node_modules/its/MIT-LICENSE.txt new file mode 100644 index 0000000..f2a646d --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2012 Ozan Turgut + +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. \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/README.md b/node_modules/json-over-tcp/node_modules/its/README.md new file mode 100644 index 0000000..9b51053 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/README.md @@ -0,0 +1,73 @@ +# its [![Build Status](https://secure.travis-ci.org/ozanturgut/its.png?branch=master)](http://travis-ci.org/ozanturgut/its) + +Its a utility to simplify common precondition or state checking. It's useful for signaling +to calling methods when they've made invalid calls to a method. + +## Usage +There are four available functions: +* `its(expression [, errorType] [, messageTemplate [, messageArgs...]])` for throwing custom errors +* `its.defined(expression [, messageTemplate [, messageArgs...]])` for throwing reference errors +* `its.range(expression [, messageTemplate [, messageArgs...]])` for throwing range errors +* `its.type(expression [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.undefined(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.null(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.boolean(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.array(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.object(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.func(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.args(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.string(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.number(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.date(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + * `its.regexp(obj [, messageTemplate [, messageArgs...]])` for throwing type errors + +`expression` is a boolean value which determines whether the precondition will throw an error or not. + +`messageTemplate` is a message with 0 or more '%s' placeholders for message arguments + +`messageArgs` is a variable argument (0 or more) to fill the placeholders in the message template + +`errorType` is used for throwing custom error objects. These objects should inherit from `Error`. + +## Examples +```javascript +// Things that should pass +its.string('hi'); // returns true +its.func(function(){}); // returns true +its.date(new Date); //returns true +its.defined("anything"); // returns "anything" +its.type(typeof "something" === "string"); // returns true +its.range(1 < 2 && 1 > 0); // returns true +its(1 === 1); // returns true +its(1 === 1, ReferenceError); // throws true + +// Things that shouldn't pass +its.defined(void 0); // throws ReferenceError +its.type(typeof "something" === "number"); // throws TypeError +its.range(1 < 2 && 1 > 2); // throws RangeError +its(1 !== 1); // throws Error +its(1 === void 0, ReferenceError); // throws ReferenceError + +// Messages +its.defined(void 0, "This doesn't look right."); // throws ReferenceError with a message of "This doesn't look right." +its.defined(void 0, "This doesn't look %s.", "right"); // throws ReferenceError with a message of "This doesn't look right." +its.defined(void 0, "%s doesn't look %s.", "This", "right"); // throws ReferenceError with a message of "This doesn't look right." + +// What real use may look like +var addOnlyNumbersBelow100 = function(number1, number2){ + its.number(number1); + its.number(number2); + its.range(number1 < 100); + its.range(number2 < 100); + return number1 + number2; +}; + +addOnlyNumbersBelow100(10, 20); // returns 30 +addOnlyNumbersBelow100(10, 338484); // throws RangeError +addOnlyNumbersBelow100("10", 338484); // throws TypeError +``` + +## Developing +its uses grunt to build. +* `grunt` - Builds the standard and minified version of precondition in the dist folder +* `grunt test` - Builds precondition and runs unit tests (requires PhantomJS) diff --git a/node_modules/json-over-tcp/node_modules/its/component.json b/node_modules/json-over-tcp/node_modules/its/component.json new file mode 100644 index 0000000..07c5ab0 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/component.json @@ -0,0 +1,9 @@ +{ + "name": "its", + "version": "1.0.1", + "main": "./dist/its.js", + "repository": { + "type": "git", + "url": "git://github.com/ozanturgut/its.git" + } +} \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/dist/its.js b/node_modules/json-over-tcp/node_modules/its/dist/its.js new file mode 100644 index 0000000..d1d047b --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/dist/its.js @@ -0,0 +1,3 @@ +/*! its - v1.0.2 - 2013-01-23 +* Copyright 2013 Ozan Turgut; Licensed MIT */ +its=function(){var e=function(e,t){e.exports=t;var n=Array.prototype.slice,r=Object.prototype.toString,i=/%s/,s=function(e,t){var n=[],r=e.split(i),s=0,o=r.length;for(;s3?s(arguments[2],n.call(arguments,3)):arguments[2]):new Error(arguments.length>2?s(t,n.call(arguments,2)):t);return e};return o.type=function(e,t){if(e===!1)throw new TypeError(arguments.length>2?s(t,n.call(arguments,2)):t);return e},o.undefined=function(e){return o.type.apply(null,[e===void 0].concat(n.call(arguments,1)))},o.null=function(e){return o.type.apply(null,[e===null].concat(n.call(arguments,1)))},o.boolean=function(e){return o.type.apply(null,[e===!0||e===!1||r.call(e)==="[object Boolean]"].concat(n.call(arguments,1)))},o.array=function(e){return o.type.apply(null,[r.call(e)==="[object Array]"].concat(n.call(arguments,1)))},o.object=function(e){return o.type.apply(null,[e===Object(e)].concat(n.call(arguments,1)))},function(){var e=[["args","Arguments"],["func","Function"],["string","String"],["number","Number"],["date","Date"],["regexp","RegExp"]],t=0,i=e.length;for(;t2?s(t,n.call(arguments,2)):t);return e},o.range=function(e,t){if(e===!1)throw new RangeError(arguments.length>2?s(t,n.call(arguments,2)):t);return e},e.exports}({},{});return e}(); \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/grunt.js b/node_modules/json-over-tcp/node_modules/its/grunt.js new file mode 100644 index 0000000..8518c24 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/grunt.js @@ -0,0 +1,83 @@ +// JS Hint options +var JSHINT_BROWSER = { + browser: true, + es5: true +}; + +var JSHINT_NODE = { + node: true, + es5: true +}; + +module.exports = function(grunt) { + // Project configuration. + grunt.initConfig({ + pkg: '', + meta: { + banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + + '* Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + }, + hug: { + build:{ + src: './lib/<%= pkg.name %>.js', + dest: 'build/<%= pkg.name %>.js', + exports: './lib/<%= pkg.name %>.js', + exportedVariable: '<%= pkg.name %>' + } + }, + min: { + dist: { + src: ['', ''], + dest: 'dist/<%= pkg.name %>.js' + } + }, + clean: { + build: { + src: [ 'build', 'dist' ] + } + }, + lint: { + all: ['lib/**/*.js'] + }, + qunit: { + all: ['test/**/*.html'] + }, + jshint: { + server: { + options: JSHINT_NODE + }, + grunt: { + options: JSHINT_NODE + }, + client: { + options: JSHINT_BROWSER + }, + + options: { + node:true, + strict: false, + camelcase: true, + curly: true, + es5:true, + eqeqeq: true, + loopfunc:true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true + }, + globals: {} + } + }); + + grunt.loadNpmTasks('grunt-hug'); + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.registerTask('test', 'default qunit'); + grunt.registerTask('default', 'clean lint hug min'); +}; \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/index.js b/node_modules/json-over-tcp/node_modules/its/index.js new file mode 100644 index 0000000..c1164a0 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/its.js'); \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/lib/its.js b/node_modules/json-over-tcp/node_modules/its/lib/its.js new file mode 100644 index 0000000..0c89914 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/lib/its.js @@ -0,0 +1,190 @@ +// Helpers +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +var templateRegEx = /%s/; // The template placeholder, used to split message templates + +/** A basic templating function. + + Takes a string with 0 or more '%s' placeholders and an array to populate it with. + + @param {String} messageTemplate A string which may or may not have 0 or more '%s' to denote argument placement + @param {Array} [messageArguments] Items to populate the template with + + @example + templatedMessage("Hello"); // returns "Hello" + templatedMessage("Hello, %s", ["world"]); // returns "Hello, world" + templatedMessage("Hello, %s. It's %s degrees outside.", ["world", 72]); // returns "Hello, world. It's 72 degrees outside" + + @returns {String} The resolved message +*/ +var templatedMessage = function(messageTemplate, messageArguments){ + var result = [], + messageArray = messageTemplate.split(templateRegEx), + index = 0, + length = messageArray.length; + + for(; index < length; index++){ + result.push(messageArray[index]); + result.push(messageArguments[index]); + } + + return result.join(''); +}; + + +/** Generic check function which throws an error if a given expression is false +* +* The params list is a bit confusing, check the examples to see the available ways of calling this function +* +* @param {Boolean} expression The determinant of whether an exception is thrown +* @param {String|Object} [messageOrErrorType] A message or an ErrorType object to throw if expression is false +* @param {String|Object} [messageOrMessageArgs] A message, message template, or a message argument +* @param {...Object} [messageArgs] Arguments for a provided message template +* +* @returns {Boolean} Returns the expression passed +* @throws {Error} +* +* @example +* its(0 < 10); // returns true +* its(0 > 10); // throws Error with no message +* its(0 > 10, "Something went wrong!"); // throws Error with message: "Something went wrong!" +* its(0 > 10, "%s went %s!", "something", "wrong"); // throws Error with message: "Something went wrong!" +* its(0 > 10, RangeError, "%s went %s!", "something", "wrong"); // throws RangeError with message: "Something went wrong!" +* its(0 > 10, RangeError); // throws RangeError with no message +*/ +var its = module.exports = function(expression, messageOrErrorType){ + if(expression === false){ + if(messageOrErrorType && typeof messageOrErrorType !== "string"){ // Check if custom error object passed + throw messageOrErrorType(arguments.length > 3 ? templatedMessage(arguments[2], slice.call(arguments,3)) : arguments[2]); + } else { + throw new Error(arguments.length > 2 ? templatedMessage(messageOrErrorType, slice.call(arguments,2)) : messageOrErrorType); + } + } + return expression; +}; + +/** Throws a TypeError if a given expression is false +* +* @param {Boolean} expression The determinant of whether an exception is thrown +* @param {String} [message] A message or message template for the error (if it gets thrown) +* @param {...Object} [messageArgs] Arguments for a provided message template +* +* @returns {Boolean} Returns the expression passed +* @throws {TypeError} +* +* @example +* its.type(typeof "Team" === "string"); // returns true +* its.type(typeof "Team" === "number"); // throws TypeError with no message +* its.type(void 0, "Something went wrong!"); // throws TypeError with message: "Something went wrong!" +* its.type(void 0, "%s went %s!", "something", "wrong"); // throws TypeError with message: "Something went wrong!" +*/ +its.type = function(expression, message){ + if(expression === false){ + throw new TypeError(arguments.length > 2 ? templatedMessage(message, slice.call(arguments,2)) : message); + } + return expression; +}; + +// Helpers +its.undefined = function(expression){ + return its.type.apply(null, [expression === void 0].concat(slice.call(arguments, 1))); +}; + +its.null = function(expression){ + return its.type.apply(null, [expression === null].concat(slice.call(arguments, 1))); +}; + +its.boolean = function(expression){ + return its.type.apply(null, [expression === true || expression === false || toString.call(expression) === "[object Boolean]"].concat(slice.call(arguments, 1))); +}; + +its.array = function(expression){ + return its.type.apply(null, [toString.call(expression) === "[object Array]"].concat(slice.call(arguments, 1))); +}; + +its.object = function(expression){ + return its.type.apply(null, [expression === Object(expression)].concat(slice.call(arguments, 1))); +}; + +/** This block creates +* its.function +* its.string +* its.number +* its.date +* its.regexp +*/ +(function(){ + var types = [ + ['args','Arguments'], + ['func', 'Function'], + ['string', 'String'], + ['number', 'Number'], + ['date', 'Date'], + ['regexp', 'RegExp'] + ], + index = 0, + length = types.length; + + for(; index < length; index++){ + (function(){ + var theType = types[index]; + its[theType[0]] = function(expression){ + return its.type.apply(null, [toString.call(expression) === '[object ' + theType[1] + ']'].concat(slice.call(arguments, 1))); + }; + }()); + } +}()); + +// optimization from underscore.js by documentcloud -- underscorejs.org +if (typeof (/./) !== 'function') { + its.func = function(expression) { + return its.type.apply(null, [typeof expression === "function"].concat(slice.call(arguments, 1))); + }; +} + +/** Throws a ReferenceError if a given expression is false +* +* @param {Boolean} expression The determinant of whether an exception is thrown +* @param {String} [message] A message or message template for the error (if it gets thrown) +* @param {...Object} [messageArgs] Arguments for a provided message template +* +* @returns {Object} Returns the expression passed +* @throws {ReferenceError} +* +* @example +* its.defined("Something"); // returns true +* its.defined(void 0); // throws ReferenceError with no message +* its.defined(void 0, "Something went wrong!"); // throws ReferenceError with message: "Something went wrong!" +* its.defined(void 0, "%s went %s!", "something", "wrong"); // throws ReferenceError with message: "Something went wrong!" +*/ +its.defined = function(expression, message){ + if(expression === void 0){ + throw new ReferenceError(arguments.length > 2 ? templatedMessage(message, slice.call(arguments,2)) : message); + } + + return expression; +}; + +/** Throws a RangeError if a given expression is false +* +* @param {Boolean} expression The determinant of whether an exception is thrown +* @param {String} [message] A message or message template for the error (if it gets thrown) +* @param {...Object} [messageArgs] Arguments for a provided message template +* +* @returns {Boolean} Returns the expression passed +* @throws {RangeError} +* +* @example +* its.range(1 > 0); // returns true +* its.range(1 < 2); // throws RangeError with no message +* its.range(1 < 2 && 1 > 2, "Something went wrong!"); // throws RangeError with message: "Something went wrong!" +* its.range(1 < 2 && 1 > 2, "%s went %s!", "something", "wrong"); // throws RangeError with message: "Something went wrong!" +*/ +its.range = function(expression, message){ + if(expression === false){ + throw new RangeError(arguments.length > 2 ? templatedMessage(message, slice.call(arguments,2)) : message); + } + + return expression; +}; \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/package.json b/node_modules/json-over-tcp/node_modules/its/package.json new file mode 100644 index 0000000..f3094d6 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/package.json @@ -0,0 +1,52 @@ +{ + "name": "its", + "version": "1.0.2", + "description": "Preconditions for safe coding", + "main": "index.js", + "scripts": { + "test": "grunt test" + }, + "devDependencies": { + "grunt": "~0.3.15", + "grunt-hug": "~0.4.0", + "grunt-contrib-clean": "~0.3.1" + }, + "repository": { + "type": "git", + "url": "https://github.com/ozanturgut/its.git" + }, + "keywords": [ + "test", + "it", + "its", + "is", + "assertion", + "assert", + "precondition" + ], + "author": { + "name": "Ozan Turgut", + "email": "ozanturgut@gmail.com" + }, + "contributors": [ + { + "name": "Ozan Turgut", + "email": "ozanturgut@gmail.com" + }, + { + "name": "tv", + "email": "tv@shackspace.de" + } + ], + "licenses": [ + { + "type": "MIT" + } + ], + "readme": "# its [![Build Status](https://secure.travis-ci.org/ozanturgut/its.png?branch=master)](http://travis-ci.org/ozanturgut/its)\r\n\r\nIts a utility to simplify common precondition or state checking. It's useful for signaling\r\nto calling methods when they've made invalid calls to a method.\r\n\r\n## Usage\r\nThere are four available functions:\r\n* `its(expression [, errorType] [, messageTemplate [, messageArgs...]])` for throwing custom errors\r\n* `its.defined(expression [, messageTemplate [, messageArgs...]])` for throwing reference errors\r\n* `its.range(expression [, messageTemplate [, messageArgs...]])` for throwing range errors\r\n* `its.type(expression [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.undefined(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.null(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.boolean(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.array(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.object(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.func(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.args(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.string(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.number(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.date(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n * `its.regexp(obj [, messageTemplate [, messageArgs...]])` for throwing type errors\r\n\r\n`expression` is a boolean value which determines whether the precondition will throw an error or not.\r\n\r\n`messageTemplate` is a message with 0 or more '%s' placeholders for message arguments\r\n\r\n`messageArgs` is a variable argument (0 or more) to fill the placeholders in the message template\r\n\r\n`errorType` is used for throwing custom error objects. These objects should inherit from `Error`.\r\n\r\n## Examples\r\n```javascript\r\n// Things that should pass\r\nits.string('hi'); // returns true\r\nits.func(function(){}); // returns true\r\nits.date(new Date); //returns true\r\nits.defined(\"anything\"); // returns \"anything\"\r\nits.type(typeof \"something\" === \"string\"); // returns true\r\nits.range(1 < 2 && 1 > 0); // returns true\r\nits(1 === 1); // returns true\r\nits(1 === 1, ReferenceError); // throws true\r\n\r\n// Things that shouldn't pass\r\nits.defined(void 0); // throws ReferenceError\r\nits.type(typeof \"something\" === \"number\"); // throws TypeError\r\nits.range(1 < 2 && 1 > 2); // throws RangeError\r\nits(1 !== 1); // throws Error\r\nits(1 === void 0, ReferenceError); // throws ReferenceError\r\n\r\n// Messages\r\nits.defined(void 0, \"This doesn't look right.\"); // throws ReferenceError with a message of \"This doesn't look right.\"\r\nits.defined(void 0, \"This doesn't look %s.\", \"right\"); // throws ReferenceError with a message of \"This doesn't look right.\"\r\nits.defined(void 0, \"%s doesn't look %s.\", \"This\", \"right\"); // throws ReferenceError with a message of \"This doesn't look right.\"\r\n\r\n// What real use may look like\r\nvar addOnlyNumbersBelow100 = function(number1, number2){\r\n\tits.number(number1);\r\n\tits.number(number2);\r\n\tits.range(number1 < 100);\r\n\tits.range(number2 < 100);\r\n\treturn number1 + number2;\r\n};\r\n\r\naddOnlyNumbersBelow100(10, 20); // returns 30\r\naddOnlyNumbersBelow100(10, 338484); // throws RangeError\r\naddOnlyNumbersBelow100(\"10\", 338484); // throws TypeError\r\n```\r\n\r\n## Developing\r\nits uses grunt to build.\r\n* `grunt` - Builds the standard and minified version of precondition in the dist folder\r\n* `grunt test` - Builds precondition and runs unit tests (requires PhantomJS)\r\n", + "_id": "its@1.0.2", + "dist": { + "shasum": "8fa0cb7c49205a28ec99be1e00b38a935ce7c78e" + }, + "_from": "its@~1.0.0" +} diff --git a/node_modules/json-over-tcp/node_modules/its/test/its.html b/node_modules/json-over-tcp/node_modules/its/test/its.html new file mode 100644 index 0000000..3e7f632 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/test/its.html @@ -0,0 +1,14 @@ + + + + + + + + + + +
+
test markup
+ + \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/test/its.js b/node_modules/json-over-tcp/node_modules/its/test/its.js new file mode 100644 index 0000000..01d0683 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/test/its.js @@ -0,0 +1,212 @@ +test("precondition exists", 4, function() { + ok(its !== void 0); + ok(its.defined !== void 0); + ok(its.range !== void 0); + ok(its.type !== void 0); +}); + +test("is", 7, function() { + var testMessage = "Test Message"; + var testTemplate = "Test %s, %s."; + var testTemplateArg1 = "one"; + var testTemplateArg2 = "two"; + var testTemplateRendered = "Test one, two."; + + ok(its(1 === 1) === true); + + try{ + its(1 !== 1); + } catch(e){ + ok(e instanceof Error, "Error is not an instance of Error"); + } + + try{ + its(1 !== 1, TypeError); + } catch(e){ + ok(e instanceof TypeError, "Error is not an instance of custom error type"); + } + + try{ + its(1 !== 1, TypeError, testMessage); + } catch(e){ + ok(e instanceof TypeError, "Error is not an instance of custom error type"); + ok(e.message === testMessage, "Message is incorrect"); + } + + try{ + its(1 !== 1, TypeError, testTemplate, testTemplateArg1, testTemplateArg2); + } catch(e){ + ok(e instanceof TypeError, "Error is not an instance of custom error type"); + ok(e.message === testTemplateRendered, "Templated message is incorrect"); + } +}); + +test("its.defined", 6, function() { + var testMessage = "Test Message"; + var testTemplate = "Test %s, %s."; + var testTemplateArg1 = "one"; + var testTemplateArg2 = "two"; + var testTemplateRendered = "Test one, two."; + + ok(its.defined(false) === false); + + try{ + its.defined(void 0); + } catch(e){ + ok(e instanceof ReferenceError, "Error is not an instance of ReferenceError"); + } + + try{ + its.defined(void 0, testMessage); + } catch(e){ + ok(e instanceof ReferenceError, "Error is not an instance of ReferenceError"); + ok(e.message === testMessage, "Message is incorrect"); + } + + try{ + its.defined(void 0, testTemplate, testTemplateArg1, testTemplateArg2); + } catch(e){ + ok(e instanceof ReferenceError, "Error is not an instance of ReferenceError"); + ok(e.message === testTemplateRendered, "Templated message is incorrect"); + } +}); + +test("its.type", function() { + var testMessage = "Test Message"; + var testTemplate = "Test %s, %s."; + var testTemplateArg1 = "one"; + var testTemplateArg2 = "two"; + var testTemplateRendered = "Test one, two."; + + ok(its.type(typeof "something" === "string") === true, "Manual type test - positive"); + + try{ its.type(typeof "something" === "number");} + catch(e) {ok(e instanceof TypeError, "Manual type test - negative");} + + try{ + its.type(typeof "something" === "number", testMessage); + } catch(e){ + ok(e instanceof TypeError, "Error is not an instance of TypeError"); + ok(e.message === testMessage, "Message is incorrect"); + } + + try{ + its.type(typeof "something" === "number", testTemplate, testTemplateArg1, testTemplateArg2); + } catch(e){ + ok(e instanceof TypeError, "Error is not an instance of TypeError"); + ok(e.message === testTemplateRendered, "Templated message is incorrect"); + } + + // HELPERS + + // its.undefined + try{ its.undefined(null);} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.undefined(void 0); + + // its.null + try{ its.null(void 0);} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.null(null); + + // its.boolean + try{ its.boolean(0);} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.boolean(true); + its.boolean(false); + its.boolean(new Boolean()); + + // its.array + try{ its.array({});} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + try{ (function(){its.array(arguments);}(1,2,3))} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.array([]); + + // its.object + try{ its.object(1);} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + try{its.object();} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.object({}); + its.object([]); + its.object(new Date); + its.object(function(){}); + + // its.args + try{ its.args({});} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.args((function(){return arguments}())); + + // its.function + try{ its.func({});} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.func(function(){}); + + // its.string + try{ its.string(1);} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.string(""); + + // its.number + try{ its.number("1");} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.number(1); + its.number(Infinity); + its.number(NaN); + + // its.date + try{ its.date(1);} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.date(new Date); + + // its.regexp + try{ its.regexp("");} + catch(e){ ok(e instanceof TypeError, "Error is not an instance of TypeError");} + + its.regexp(/./); + its.regexp(new RegExp(".")); +}); + + +test("its.range", 6, function() { + var testMessage = "Test Message"; + var testTemplate = "Test %s, %s."; + var testTemplateArg1 = "one"; + var testTemplateArg2 = "two"; + var testTemplateRendered = "Test one, two."; + + ok(its.range(1 > 0) === true); + + try{ + its.range(1 < 0); + } catch(e){ + ok(e instanceof RangeError, "Error is not an instance of RangeError"); + } + + try{ + its.range(1 < 0, testMessage); + } catch(e){ + ok(e instanceof RangeError, "Error is not an instance of RangeError"); + ok(e.message === testMessage, "Message is incorrect"); + } + + try{ + its.range(1 < 0, testTemplate, testTemplateArg1, testTemplateArg2); + } catch(e){ + ok(e instanceof RangeError, "Error is not an instance of RangeError"); + ok(e.message === testTemplateRendered, "Templated message is incorrect"); + } +}); \ No newline at end of file diff --git a/node_modules/json-over-tcp/node_modules/its/test/lib/qunit.js b/node_modules/json-over-tcp/node_modules/its/test/lib/qunit.js new file mode 100644 index 0000000..38c6f99 --- /dev/null +++ b/node_modules/json-over-tcp/node_modules/its/test/lib/qunit.js @@ -0,0 +1,1977 @@ +/** + * QUnit v1.10.0 - A JavaScript Unit Testing Framework + * + * http://qunitjs.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +(function( window ) { + +var QUnit, + config, + onErrorFnPrev, + testId = 0, + fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""), + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + // Keep a local reference to Date (GH-283) + Date = window.Date, + defined = { + setTimeout: typeof window.setTimeout !== "undefined", + sessionStorage: (function() { + var x = "qunit-test-string"; + try { + sessionStorage.setItem( x, x ); + sessionStorage.removeItem( x ); + return true; + } catch( e ) { + return false; + } + }()) +}; + +function Test( settings ) { + extend( this, settings ); + this.assertions = []; + this.testNumber = ++Test.count; +} + +Test.count = 0; + +Test.prototype = { + init: function() { + var a, b, li, + tests = id( "qunit-tests" ); + + if ( tests ) { + b = document.createElement( "strong" ); + b.innerHTML = this.name; + + // `a` initialized at top of scope + a = document.createElement( "a" ); + a.innerHTML = "Rerun"; + a.href = QUnit.url({ testNumber: this.testNumber }); + + li = document.createElement( "li" ); + li.appendChild( b ); + li.appendChild( a ); + li.className = "running"; + li.id = this.id = "qunit-test-output" + testId++; + + tests.appendChild( li ); + } + }, + setup: function() { + if ( this.module !== config.previousModule ) { + if ( config.previousModule ) { + runLoggingCallbacks( "moduleDone", QUnit, { + name: config.previousModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + }); + } + config.previousModule = this.module; + config.moduleStats = { all: 0, bad: 0 }; + runLoggingCallbacks( "moduleStart", QUnit, { + name: this.module + }); + } else if ( config.autorun ) { + runLoggingCallbacks( "moduleStart", QUnit, { + name: this.module + }); + } + + config.current = this; + + this.testEnvironment = extend({ + setup: function() {}, + teardown: function() {} + }, this.moduleTestEnvironment ); + + runLoggingCallbacks( "testStart", QUnit, { + name: this.testName, + module: this.module + }); + + // allow utility functions to access the current test environment + // TODO why?? + QUnit.current_testEnvironment = this.testEnvironment; + + if ( !config.pollution ) { + saveGlobal(); + } + if ( config.notrycatch ) { + this.testEnvironment.setup.call( this.testEnvironment ); + return; + } + try { + this.testEnvironment.setup.call( this.testEnvironment ); + } catch( e ) { + QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); + } + }, + run: function() { + config.current = this; + + var running = id( "qunit-testresult" ); + + if ( running ) { + running.innerHTML = "Running:
" + this.name; + } + + if ( this.async ) { + QUnit.stop(); + } + + if ( config.notrycatch ) { + this.callback.call( this.testEnvironment, QUnit.assert ); + return; + } + + try { + this.callback.call( this.testEnvironment, QUnit.assert ); + } catch( e ) { + QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + e.message, extractStacktrace( e, 0 ) ); + // else next test will carry the responsibility + saveGlobal(); + + // Restart the tests if they're blocking + if ( config.blocking ) { + QUnit.start(); + } + } + }, + teardown: function() { + config.current = this; + if ( config.notrycatch ) { + this.testEnvironment.teardown.call( this.testEnvironment ); + return; + } else { + try { + this.testEnvironment.teardown.call( this.testEnvironment ); + } catch( e ) { + QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); + } + } + checkPollution(); + }, + finish: function() { + config.current = this; + if ( config.requireExpects && this.expected == null ) { + QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack ); + } else if ( this.expected != null && this.expected != this.assertions.length ) { + QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack ); + } else if ( this.expected == null && !this.assertions.length ) { + QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack ); + } + + var assertion, a, b, i, li, ol, + test = this, + good = 0, + bad = 0, + tests = id( "qunit-tests" ); + + config.stats.all += this.assertions.length; + config.moduleStats.all += this.assertions.length; + + if ( tests ) { + ol = document.createElement( "ol" ); + + for ( i = 0; i < this.assertions.length; i++ ) { + assertion = this.assertions[i]; + + li = document.createElement( "li" ); + li.className = assertion.result ? "pass" : "fail"; + li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" ); + ol.appendChild( li ); + + if ( assertion.result ) { + good++; + } else { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + + // store result when possible + if ( QUnit.config.reorder && defined.sessionStorage ) { + if ( bad ) { + sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad ); + } else { + sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName ); + } + } + + if ( bad === 0 ) { + ol.style.display = "none"; + } + + // `b` initialized at top of scope + b = document.createElement( "strong" ); + b.innerHTML = this.name + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; + + addEvent(b, "click", function() { + var next = b.nextSibling.nextSibling, + display = next.style.display; + next.style.display = display === "none" ? "block" : "none"; + }); + + addEvent(b, "dblclick", function( e ) { + var target = e && e.target ? e.target : window.event.srcElement; + if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { + target = target.parentNode; + } + if ( window.location && target.nodeName.toLowerCase() === "strong" ) { + window.location = QUnit.url({ testNumber: test.testNumber }); + } + }); + + // `li` initialized at top of scope + li = id( this.id ); + li.className = bad ? "fail" : "pass"; + li.removeChild( li.firstChild ); + a = li.firstChild; + li.appendChild( b ); + li.appendChild ( a ); + li.appendChild( ol ); + + } else { + for ( i = 0; i < this.assertions.length; i++ ) { + if ( !this.assertions[i].result ) { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + } + + runLoggingCallbacks( "testDone", QUnit, { + name: this.testName, + module: this.module, + failed: bad, + passed: this.assertions.length - bad, + total: this.assertions.length + }); + + QUnit.reset(); + + config.current = undefined; + }, + + queue: function() { + var bad, + test = this; + + synchronize(function() { + test.init(); + }); + function run() { + // each of these can by async + synchronize(function() { + test.setup(); + }); + synchronize(function() { + test.run(); + }); + synchronize(function() { + test.teardown(); + }); + synchronize(function() { + test.finish(); + }); + } + + // `bad` initialized at top of scope + // defer when previous test run passed, if storage is available + bad = QUnit.config.reorder && defined.sessionStorage && + +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName ); + + if ( bad ) { + run(); + } else { + synchronize( run, true ); + } + } +}; + +// Root QUnit object. +// `QUnit` initialized at top of scope +QUnit = { + + // call on start of module test to prepend name to all tests + module: function( name, testEnvironment ) { + config.currentModule = name; + config.currentModuleTestEnvironment = testEnvironment; + config.modules[name] = true; + }, + + asyncTest: function( testName, expected, callback ) { + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + + QUnit.test( testName, expected, callback, true ); + }, + + test: function( testName, expected, callback, async ) { + var test, + name = "" + escapeInnerText( testName ) + ""; + + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + + if ( config.currentModule ) { + name = "" + config.currentModule + ": " + name; + } + + test = new Test({ + name: name, + testName: testName, + expected: expected, + async: async, + callback: callback, + module: config.currentModule, + moduleTestEnvironment: config.currentModuleTestEnvironment, + stack: sourceFromStacktrace( 2 ) + }); + + if ( !validTest( test ) ) { + return; + } + + test.queue(); + }, + + // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. + expect: function( asserts ) { + if (arguments.length === 1) { + config.current.expected = asserts; + } else { + return config.current.expected; + } + }, + + start: function( count ) { + config.semaphore -= count || 1; + // don't start until equal number of stop-calls + if ( config.semaphore > 0 ) { + return; + } + // ignore if start is called more often then stop + if ( config.semaphore < 0 ) { + config.semaphore = 0; + } + // A slight delay, to avoid any current callbacks + if ( defined.setTimeout ) { + window.setTimeout(function() { + if ( config.semaphore > 0 ) { + return; + } + if ( config.timeout ) { + clearTimeout( config.timeout ); + } + + config.blocking = false; + process( true ); + }, 13); + } else { + config.blocking = false; + process( true ); + } + }, + + stop: function( count ) { + config.semaphore += count || 1; + config.blocking = true; + + if ( config.testTimeout && defined.setTimeout ) { + clearTimeout( config.timeout ); + config.timeout = window.setTimeout(function() { + QUnit.ok( false, "Test timed out" ); + config.semaphore = 1; + QUnit.start(); + }, config.testTimeout ); + } + } +}; + +// Asssert helpers +// All of these must call either QUnit.push() or manually do: +// - runLoggingCallbacks( "log", .. ); +// - config.current.assertions.push({ .. }); +QUnit.assert = { + /** + * Asserts rough true-ish result. + * @name ok + * @function + * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); + */ + ok: function( result, msg ) { + if ( !config.current ) { + throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) ); + } + result = !!result; + + var source, + details = { + module: config.current.module, + name: config.current.testName, + result: result, + message: msg + }; + + msg = escapeInnerText( msg || (result ? "okay" : "failed" ) ); + msg = "" + msg + ""; + + if ( !result ) { + source = sourceFromStacktrace( 2 ); + if ( source ) { + details.source = source; + msg += "
Source:
" + escapeInnerText( source ) + "
"; + } + } + runLoggingCallbacks( "log", QUnit, details ); + config.current.assertions.push({ + result: result, + message: msg + }); + }, + + /** + * Assert that the first two arguments are equal, with an optional message. + * Prints out both actual and expected values. + * @name equal + * @function + * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" ); + */ + equal: function( actual, expected, message ) { + QUnit.push( expected == actual, actual, expected, message ); + }, + + /** + * @name notEqual + * @function + */ + notEqual: function( actual, expected, message ) { + QUnit.push( expected != actual, actual, expected, message ); + }, + + /** + * @name deepEqual + * @function + */ + deepEqual: function( actual, expected, message ) { + QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); + }, + + /** + * @name notDeepEqual + * @function + */ + notDeepEqual: function( actual, expected, message ) { + QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message ); + }, + + /** + * @name strictEqual + * @function + */ + strictEqual: function( actual, expected, message ) { + QUnit.push( expected === actual, actual, expected, message ); + }, + + /** + * @name notStrictEqual + * @function + */ + notStrictEqual: function( actual, expected, message ) { + QUnit.push( expected !== actual, actual, expected, message ); + }, + + throws: function( block, expected, message ) { + var actual, + ok = false; + + // 'expected' is optional + if ( typeof expected === "string" ) { + message = expected; + expected = null; + } + + config.current.ignoreGlobalErrors = true; + try { + block.call( config.current.testEnvironment ); + } catch (e) { + actual = e; + } + config.current.ignoreGlobalErrors = false; + + if ( actual ) { + // we don't want to validate thrown error + if ( !expected ) { + ok = true; + // expected is a regexp + } else if ( QUnit.objectType( expected ) === "regexp" ) { + ok = expected.test( actual ); + // expected is a constructor + } else if ( actual instanceof expected ) { + ok = true; + // expected is a validation function which returns true is validation passed + } else if ( expected.call( {}, actual ) === true ) { + ok = true; + } + + QUnit.push( ok, actual, null, message ); + } else { + QUnit.pushFailure( message, null, 'No exception was thrown.' ); + } + } +}; + +/** + * @deprecate since 1.8.0 + * Kept assertion helpers in root for backwards compatibility + */ +extend( QUnit, QUnit.assert ); + +/** + * @deprecated since 1.9.0 + * Kept global "raises()" for backwards compatibility + */ +QUnit.raises = QUnit.assert.throws; + +/** + * @deprecated since 1.0.0, replaced with error pushes since 1.3.0 + * Kept to avoid TypeErrors for undefined methods. + */ +QUnit.equals = function() { + QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" ); +}; +QUnit.same = function() { + QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" ); +}; + +// We want access to the constructor's prototype +(function() { + function F() {} + F.prototype = QUnit; + QUnit = new F(); + // Make F QUnit's constructor so that we can add to the prototype later + QUnit.constructor = F; +}()); + +/** + * Config object: Maintain internal state + * Later exposed as QUnit.config + * `config` initialized at top of scope + */ +config = { + // The queue of tests to run + queue: [], + + // block until document ready + blocking: true, + + // when enabled, show only failing tests + // gets persisted through sessionStorage and can be changed in UI via checkbox + hidepassed: false, + + // by default, run previously failed tests first + // very useful in combination with "Hide passed tests" checked + reorder: true, + + // by default, modify document.title when suite is done + altertitle: true, + + // when enabled, all tests must call expect() + requireExpects: false, + + // add checkboxes that are persisted in the query-string + // when enabled, the id is set to `true` as a `QUnit.config` property + urlConfig: [ + { + id: "noglobals", + label: "Check for Globals", + tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings." + }, + { + id: "notrycatch", + label: "No try-catch", + tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings." + } + ], + + // Set of all modules. + modules: {}, + + // logging callback queues + begin: [], + done: [], + log: [], + testStart: [], + testDone: [], + moduleStart: [], + moduleDone: [] +}; + +// Initialize more QUnit.config and QUnit.urlParams +(function() { + var i, + location = window.location || { search: "", protocol: "file:" }, + params = location.search.slice( 1 ).split( "&" ), + length = params.length, + urlParams = {}, + current; + + if ( params[ 0 ] ) { + for ( i = 0; i < length; i++ ) { + current = params[ i ].split( "=" ); + current[ 0 ] = decodeURIComponent( current[ 0 ] ); + // allow just a key to turn on a flag, e.g., test.html?noglobals + current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; + urlParams[ current[ 0 ] ] = current[ 1 ]; + } + } + + QUnit.urlParams = urlParams; + + // String search anywhere in moduleName+testName + config.filter = urlParams.filter; + + // Exact match of the module name + config.module = urlParams.module; + + config.testNumber = parseInt( urlParams.testNumber, 10 ) || null; + + // Figure out if we're running the tests from a server or not + QUnit.isLocal = location.protocol === "file:"; +}()); + +// Export global variables, unless an 'exports' object exists, +// in that case we assume we're in CommonJS (dealt with on the bottom of the script) +if ( typeof exports === "undefined" ) { + extend( window, QUnit ); + + // Expose QUnit object + window.QUnit = QUnit; +} + +// Extend QUnit object, +// these after set here because they should not be exposed as global functions +extend( QUnit, { + config: config, + + // Initialize the configuration options + init: function() { + extend( config, { + stats: { all: 0, bad: 0 }, + moduleStats: { all: 0, bad: 0 }, + started: +new Date(), + updateRate: 1000, + blocking: false, + autostart: true, + autorun: false, + filter: "", + queue: [], + semaphore: 0 + }); + + var tests, banner, result, + qunit = id( "qunit" ); + + if ( qunit ) { + qunit.innerHTML = + "

" + escapeInnerText( document.title ) + "

" + + "

" + + "
" + + "

" + + "
    "; + } + + tests = id( "qunit-tests" ); + banner = id( "qunit-banner" ); + result = id( "qunit-testresult" ); + + if ( tests ) { + tests.innerHTML = ""; + } + + if ( banner ) { + banner.className = ""; + } + + if ( result ) { + result.parentNode.removeChild( result ); + } + + if ( tests ) { + result = document.createElement( "p" ); + result.id = "qunit-testresult"; + result.className = "result"; + tests.parentNode.insertBefore( result, tests ); + result.innerHTML = "Running...
     "; + } + }, + + // Resets the test setup. Useful for tests that modify the DOM. + reset: function() { + var fixture = id( "qunit-fixture" ); + if ( fixture ) { + fixture.innerHTML = config.fixture; + } + }, + + // Trigger an event on an element. + // @example triggerEvent( document.body, "click" ); + triggerEvent: function( elem, type, event ) { + if ( document.createEvent ) { + event = document.createEvent( "MouseEvents" ); + event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + + elem.dispatchEvent( event ); + } else if ( elem.fireEvent ) { + elem.fireEvent( "on" + type ); + } + }, + + // Safe object type checking + is: function( type, obj ) { + return QUnit.objectType( obj ) == type; + }, + + objectType: function( obj ) { + if ( typeof obj === "undefined" ) { + return "undefined"; + // consider: typeof null === object + } + if ( obj === null ) { + return "null"; + } + + var type = toString.call( obj ).match(/^\[object\s(.*)\]$/)[1] || ""; + + switch ( type ) { + case "Number": + if ( isNaN(obj) ) { + return "nan"; + } + return "number"; + case "String": + case "Boolean": + case "Array": + case "Date": + case "RegExp": + case "Function": + return type.toLowerCase(); + } + if ( typeof obj === "object" ) { + return "object"; + } + return undefined; + }, + + push: function( result, actual, expected, message ) { + if ( !config.current ) { + throw new Error( "assertion outside test context, was " + sourceFromStacktrace() ); + } + + var output, source, + details = { + module: config.current.module, + name: config.current.testName, + result: result, + message: message, + actual: actual, + expected: expected + }; + + message = escapeInnerText( message ) || ( result ? "okay" : "failed" ); + message = "" + message + ""; + output = message; + + if ( !result ) { + expected = escapeInnerText( QUnit.jsDump.parse(expected) ); + actual = escapeInnerText( QUnit.jsDump.parse(actual) ); + output += ""; + + if ( actual != expected ) { + output += ""; + output += ""; + } + + source = sourceFromStacktrace(); + + if ( source ) { + details.source = source; + output += ""; + } + + output += "
    Expected:
    " + expected + "
    Result:
    " + actual + "
    Diff:
    " + QUnit.diff( expected, actual ) + "
    Source:
    " + escapeInnerText( source ) + "
    "; + } + + runLoggingCallbacks( "log", QUnit, details ); + + config.current.assertions.push({ + result: !!result, + message: output + }); + }, + + pushFailure: function( message, source, actual ) { + if ( !config.current ) { + throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) ); + } + + var output, + details = { + module: config.current.module, + name: config.current.testName, + result: false, + message: message + }; + + message = escapeInnerText( message ) || "error"; + message = "" + message + ""; + output = message; + + output += ""; + + if ( actual ) { + output += ""; + } + + if ( source ) { + details.source = source; + output += ""; + } + + output += "
    Result:
    " + escapeInnerText( actual ) + "
    Source:
    " + escapeInnerText( source ) + "
    "; + + runLoggingCallbacks( "log", QUnit, details ); + + config.current.assertions.push({ + result: false, + message: output + }); + }, + + url: function( params ) { + params = extend( extend( {}, QUnit.urlParams ), params ); + var key, + querystring = "?"; + + for ( key in params ) { + if ( !hasOwn.call( params, key ) ) { + continue; + } + querystring += encodeURIComponent( key ) + "=" + + encodeURIComponent( params[ key ] ) + "&"; + } + return window.location.pathname + querystring.slice( 0, -1 ); + }, + + extend: extend, + id: id, + addEvent: addEvent + // load, equiv, jsDump, diff: Attached later +}); + +/** + * @deprecated: Created for backwards compatibility with test runner that set the hook function + * into QUnit.{hook}, instead of invoking it and passing the hook function. + * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here. + * Doing this allows us to tell if the following methods have been overwritten on the actual + * QUnit object. + */ +extend( QUnit.constructor.prototype, { + + // Logging callbacks; all receive a single argument with the listed properties + // run test/logs.html for any related changes + begin: registerLoggingCallback( "begin" ), + + // done: { failed, passed, total, runtime } + done: registerLoggingCallback( "done" ), + + // log: { result, actual, expected, message } + log: registerLoggingCallback( "log" ), + + // testStart: { name } + testStart: registerLoggingCallback( "testStart" ), + + // testDone: { name, failed, passed, total } + testDone: registerLoggingCallback( "testDone" ), + + // moduleStart: { name } + moduleStart: registerLoggingCallback( "moduleStart" ), + + // moduleDone: { name, failed, passed, total } + moduleDone: registerLoggingCallback( "moduleDone" ) +}); + +if ( typeof document === "undefined" || document.readyState === "complete" ) { + config.autorun = true; +} + +QUnit.load = function() { + runLoggingCallbacks( "begin", QUnit, {} ); + + // Initialize the config, saving the execution queue + var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter, + numModules = 0, + moduleFilterHtml = "", + urlConfigHtml = "", + oldconfig = extend( {}, config ); + + QUnit.init(); + extend(config, oldconfig); + + config.blocking = false; + + len = config.urlConfig.length; + + for ( i = 0; i < len; i++ ) { + val = config.urlConfig[i]; + if ( typeof val === "string" ) { + val = { + id: val, + label: val, + tooltip: "[no tooltip available]" + }; + } + config[ val.id ] = QUnit.urlParams[ val.id ]; + urlConfigHtml += ""; + } + + moduleFilterHtml += ""; + + // `userAgent` initialized at top of scope + userAgent = id( "qunit-userAgent" ); + if ( userAgent ) { + userAgent.innerHTML = navigator.userAgent; + } + + // `banner` initialized at top of scope + banner = id( "qunit-header" ); + if ( banner ) { + banner.innerHTML = "" + banner.innerHTML + " "; + } + + // `toolbar` initialized at top of scope + toolbar = id( "qunit-testrunner-toolbar" ); + if ( toolbar ) { + // `filter` initialized at top of scope + filter = document.createElement( "input" ); + filter.type = "checkbox"; + filter.id = "qunit-filter-pass"; + + addEvent( filter, "click", function() { + var tmp, + ol = document.getElementById( "qunit-tests" ); + + if ( filter.checked ) { + ol.className = ol.className + " hidepass"; + } else { + tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " "; + ol.className = tmp.replace( / hidepass /, " " ); + } + if ( defined.sessionStorage ) { + if (filter.checked) { + sessionStorage.setItem( "qunit-filter-passed-tests", "true" ); + } else { + sessionStorage.removeItem( "qunit-filter-passed-tests" ); + } + } + }); + + if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) { + filter.checked = true; + // `ol` initialized at top of scope + ol = document.getElementById( "qunit-tests" ); + ol.className = ol.className + " hidepass"; + } + toolbar.appendChild( filter ); + + // `label` initialized at top of scope + label = document.createElement( "label" ); + label.setAttribute( "for", "qunit-filter-pass" ); + label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." ); + label.innerHTML = "Hide passed tests"; + toolbar.appendChild( label ); + + urlConfigCheckboxes = document.createElement( 'span' ); + urlConfigCheckboxes.innerHTML = urlConfigHtml; + addEvent( urlConfigCheckboxes, "change", function( event ) { + var params = {}; + params[ event.target.name ] = event.target.checked ? true : undefined; + window.location = QUnit.url( params ); + }); + toolbar.appendChild( urlConfigCheckboxes ); + + if (numModules > 1) { + moduleFilter = document.createElement( 'span' ); + moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' ); + moduleFilter.innerHTML = moduleFilterHtml; + addEvent( moduleFilter, "change", function() { + var selectBox = moduleFilter.getElementsByTagName("select")[0], + selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value); + + window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } ); + }); + toolbar.appendChild(moduleFilter); + } + } + + // `main` initialized at top of scope + main = id( "qunit-fixture" ); + if ( main ) { + config.fixture = main.innerHTML; + } + + if ( config.autostart ) { + QUnit.start(); + } +}; + +addEvent( window, "load", QUnit.load ); + +// `onErrorFnPrev` initialized at top of scope +// Preserve other handlers +onErrorFnPrev = window.onerror; + +// Cover uncaught exceptions +// Returning true will surpress the default browser handler, +// returning false will let it run. +window.onerror = function ( error, filePath, linerNr ) { + var ret = false; + if ( onErrorFnPrev ) { + ret = onErrorFnPrev( error, filePath, linerNr ); + } + + // Treat return value as window.onerror itself does, + // Only do our handling if not surpressed. + if ( ret !== true ) { + if ( QUnit.config.current ) { + if ( QUnit.config.current.ignoreGlobalErrors ) { + return true; + } + QUnit.pushFailure( error, filePath + ":" + linerNr ); + } else { + QUnit.test( "global failure", extend( function() { + QUnit.pushFailure( error, filePath + ":" + linerNr ); + }, { validTest: validTest } ) ); + } + return false; + } + + return ret; +}; + +function done() { + config.autorun = true; + + // Log the last module results + if ( config.currentModule ) { + runLoggingCallbacks( "moduleDone", QUnit, { + name: config.currentModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + }); + } + + var i, key, + banner = id( "qunit-banner" ), + tests = id( "qunit-tests" ), + runtime = +new Date() - config.started, + passed = config.stats.all - config.stats.bad, + html = [ + "Tests completed in ", + runtime, + " milliseconds.
    ", + "", + passed, + " tests of ", + config.stats.all, + " passed, ", + config.stats.bad, + " failed." + ].join( "" ); + + if ( banner ) { + banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" ); + } + + if ( tests ) { + id( "qunit-testresult" ).innerHTML = html; + } + + if ( config.altertitle && typeof document !== "undefined" && document.title ) { + // show ✖ for good, ✔ for bad suite result in title + // use escape sequences in case file gets loaded with non-utf-8-charset + document.title = [ + ( config.stats.bad ? "\u2716" : "\u2714" ), + document.title.replace( /^[\u2714\u2716] /i, "" ) + ].join( " " ); + } + + // clear own sessionStorage items if all tests passed + if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) { + // `key` & `i` initialized at top of scope + for ( i = 0; i < sessionStorage.length; i++ ) { + key = sessionStorage.key( i++ ); + if ( key.indexOf( "qunit-test-" ) === 0 ) { + sessionStorage.removeItem( key ); + } + } + } + + // scroll back to top to show results + if ( window.scrollTo ) { + window.scrollTo(0, 0); + } + + runLoggingCallbacks( "done", QUnit, { + failed: config.stats.bad, + passed: passed, + total: config.stats.all, + runtime: runtime + }); +} + +/** @return Boolean: true if this test should be ran */ +function validTest( test ) { + var include, + filter = config.filter && config.filter.toLowerCase(), + module = config.module && config.module.toLowerCase(), + fullName = (test.module + ": " + test.testName).toLowerCase(); + + // Internally-generated tests are always valid + if ( test.callback && test.callback.validTest === validTest ) { + delete test.callback.validTest; + return true; + } + + if ( config.testNumber ) { + return test.testNumber === config.testNumber; + } + + if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) { + return false; + } + + if ( !filter ) { + return true; + } + + include = filter.charAt( 0 ) !== "!"; + if ( !include ) { + filter = filter.slice( 1 ); + } + + // If the filter matches, we need to honour include + if ( fullName.indexOf( filter ) !== -1 ) { + return include; + } + + // Otherwise, do the opposite + return !include; +} + +// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions) +// Later Safari and IE10 are supposed to support error.stack as well +// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack +function extractStacktrace( e, offset ) { + offset = offset === undefined ? 3 : offset; + + var stack, include, i, regex; + + if ( e.stacktrace ) { + // Opera + return e.stacktrace.split( "\n" )[ offset + 3 ]; + } else if ( e.stack ) { + // Firefox, Chrome + stack = e.stack.split( "\n" ); + if (/^error$/i.test( stack[0] ) ) { + stack.shift(); + } + if ( fileName ) { + include = []; + for ( i = offset; i < stack.length; i++ ) { + if ( stack[ i ].indexOf( fileName ) != -1 ) { + break; + } + include.push( stack[ i ] ); + } + if ( include.length ) { + return include.join( "\n" ); + } + } + return stack[ offset ]; + } else if ( e.sourceURL ) { + // Safari, PhantomJS + // hopefully one day Safari provides actual stacktraces + // exclude useless self-reference for generated Error objects + if ( /qunit.js$/.test( e.sourceURL ) ) { + return; + } + // for actual exceptions, this is useful + return e.sourceURL + ":" + e.line; + } +} +function sourceFromStacktrace( offset ) { + try { + throw new Error(); + } catch ( e ) { + return extractStacktrace( e, offset ); + } +} + +function escapeInnerText( s ) { + if ( !s ) { + return ""; + } + s = s + ""; + return s.replace( /[\&<>]/g, function( s ) { + switch( s ) { + case "&": return "&"; + case "<": return "<"; + case ">": return ">"; + default: return s; + } + }); +} + +function synchronize( callback, last ) { + config.queue.push( callback ); + + if ( config.autorun && !config.blocking ) { + process( last ); + } +} + +function process( last ) { + function next() { + process( last ); + } + var start = new Date().getTime(); + config.depth = config.depth ? config.depth + 1 : 1; + + while ( config.queue.length && !config.blocking ) { + if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) { + config.queue.shift()(); + } else { + window.setTimeout( next, 13 ); + break; + } + } + config.depth--; + if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { + done(); + } +} + +function saveGlobal() { + config.pollution = []; + + if ( config.noglobals ) { + for ( var key in window ) { + // in Opera sometimes DOM element ids show up here, ignore them + if ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) { + continue; + } + config.pollution.push( key ); + } + } +} + +function checkPollution( name ) { + var newGlobals, + deletedGlobals, + old = config.pollution; + + saveGlobal(); + + newGlobals = diff( config.pollution, old ); + if ( newGlobals.length > 0 ) { + QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") ); + } + + deletedGlobals = diff( old, config.pollution ); + if ( deletedGlobals.length > 0 ) { + QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") ); + } +} + +// returns a new Array with the elements that are in a but not in b +function diff( a, b ) { + var i, j, + result = a.slice(); + + for ( i = 0; i < result.length; i++ ) { + for ( j = 0; j < b.length; j++ ) { + if ( result[i] === b[j] ) { + result.splice( i, 1 ); + i--; + break; + } + } + } + return result; +} + +function extend( a, b ) { + for ( var prop in b ) { + if ( b[ prop ] === undefined ) { + delete a[ prop ]; + + // Avoid "Member not found" error in IE8 caused by setting window.constructor + } else if ( prop !== "constructor" || a !== window ) { + a[ prop ] = b[ prop ]; + } + } + + return a; +} + +function addEvent( elem, type, fn ) { + if ( elem.addEventListener ) { + elem.addEventListener( type, fn, false ); + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, fn ); + } else { + fn(); + } +} + +function id( name ) { + return !!( typeof document !== "undefined" && document && document.getElementById ) && + document.getElementById( name ); +} + +function registerLoggingCallback( key ) { + return function( callback ) { + config[key].push( callback ); + }; +} + +// Supports deprecated method of completely overwriting logging callbacks +function runLoggingCallbacks( key, scope, args ) { + //debugger; + var i, callbacks; + if ( QUnit.hasOwnProperty( key ) ) { + QUnit[ key ].call(scope, args ); + } else { + callbacks = config[ key ]; + for ( i = 0; i < callbacks.length; i++ ) { + callbacks[ i ].call( scope, args ); + } + } +} + +// Test for equality any JavaScript type. +// Author: Philippe Rathé +QUnit.equiv = (function() { + + // Call the o related callback with the given arguments. + function bindCallbacks( o, callbacks, args ) { + var prop = QUnit.objectType( o ); + if ( prop ) { + if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) { + return callbacks[ prop ].apply( callbacks, args ); + } else { + return callbacks[ prop ]; // or undefined + } + } + } + + // the real equiv function + var innerEquiv, + // stack to decide between skip/abort functions + callers = [], + // stack to avoiding loops from circular referencing + parents = [], + + getProto = Object.getPrototypeOf || function ( obj ) { + return obj.__proto__; + }, + callbacks = (function () { + + // for string, boolean, number and null + function useStrictEquality( b, a ) { + if ( b instanceof a.constructor || a instanceof b.constructor ) { + // to catch short annotaion VS 'new' annotation of a + // declaration + // e.g. var i = 1; + // var j = new Number(1); + return a == b; + } else { + return a === b; + } + } + + return { + "string": useStrictEquality, + "boolean": useStrictEquality, + "number": useStrictEquality, + "null": useStrictEquality, + "undefined": useStrictEquality, + + "nan": function( b ) { + return isNaN( b ); + }, + + "date": function( b, a ) { + return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf(); + }, + + "regexp": function( b, a ) { + return QUnit.objectType( b ) === "regexp" && + // the regex itself + a.source === b.source && + // and its modifers + a.global === b.global && + // (gmi) ... + a.ignoreCase === b.ignoreCase && + a.multiline === b.multiline && + a.sticky === b.sticky; + }, + + // - skip when the property is a method of an instance (OOP) + // - abort otherwise, + // initial === would have catch identical references anyway + "function": function() { + var caller = callers[callers.length - 1]; + return caller !== Object && typeof caller !== "undefined"; + }, + + "array": function( b, a ) { + var i, j, len, loop; + + // b could be an object literal here + if ( QUnit.objectType( b ) !== "array" ) { + return false; + } + + len = a.length; + if ( len !== b.length ) { + // safe and faster + return false; + } + + // track reference to avoid circular references + parents.push( a ); + for ( i = 0; i < len; i++ ) { + loop = false; + for ( j = 0; j < parents.length; j++ ) { + if ( parents[j] === a[i] ) { + loop = true;// dont rewalk array + } + } + if ( !loop && !innerEquiv(a[i], b[i]) ) { + parents.pop(); + return false; + } + } + parents.pop(); + return true; + }, + + "object": function( b, a ) { + var i, j, loop, + // Default to true + eq = true, + aProperties = [], + bProperties = []; + + // comparing constructors is more strict than using + // instanceof + if ( a.constructor !== b.constructor ) { + // Allow objects with no prototype to be equivalent to + // objects with Object as their constructor. + if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) || + ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) { + return false; + } + } + + // stack constructor before traversing properties + callers.push( a.constructor ); + // track reference to avoid circular references + parents.push( a ); + + for ( i in a ) { // be strict: don't ensures hasOwnProperty + // and go deep + loop = false; + for ( j = 0; j < parents.length; j++ ) { + if ( parents[j] === a[i] ) { + // don't go down the same path twice + loop = true; + } + } + aProperties.push(i); // collect a's properties + + if (!loop && !innerEquiv( a[i], b[i] ) ) { + eq = false; + break; + } + } + + callers.pop(); // unstack, we are done + parents.pop(); + + for ( i in b ) { + bProperties.push( i ); // collect b's properties + } + + // Ensures identical properties name + return eq && innerEquiv( aProperties.sort(), bProperties.sort() ); + } + }; + }()); + + innerEquiv = function() { // can take multiple arguments + var args = [].slice.apply( arguments ); + if ( args.length < 2 ) { + return true; // end transition + } + + return (function( a, b ) { + if ( a === b ) { + return true; // catch the most you can + } else if ( a === null || b === null || typeof a === "undefined" || + typeof b === "undefined" || + QUnit.objectType(a) !== QUnit.objectType(b) ) { + return false; // don't lose time with error prone cases + } else { + return bindCallbacks(a, callbacks, [ b, a ]); + } + + // apply transition with (1..n) arguments + }( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) ); + }; + + return innerEquiv; +}()); + +/** + * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | + * http://flesler.blogspot.com Licensed under BSD + * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008 + * + * @projectDescription Advanced and extensible data dumping for Javascript. + * @version 1.0.0 + * @author Ariel Flesler + * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html} + */ +QUnit.jsDump = (function() { + function quote( str ) { + return '"' + str.toString().replace( /"/g, '\\"' ) + '"'; + } + function literal( o ) { + return o + ""; + } + function join( pre, arr, post ) { + var s = jsDump.separator(), + base = jsDump.indent(), + inner = jsDump.indent(1); + if ( arr.join ) { + arr = arr.join( "," + s + inner ); + } + if ( !arr ) { + return pre + post; + } + return [ pre, inner + arr, base + post ].join(s); + } + function array( arr, stack ) { + var i = arr.length, ret = new Array(i); + this.up(); + while ( i-- ) { + ret[i] = this.parse( arr[i] , undefined , stack); + } + this.down(); + return join( "[", ret, "]" ); + } + + var reName = /^function (\w+)/, + jsDump = { + parse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance + stack = stack || [ ]; + var inStack, res, + parser = this.parsers[ type || this.typeOf(obj) ]; + + type = typeof parser; + inStack = inArray( obj, stack ); + + if ( inStack != -1 ) { + return "recursion(" + (inStack - stack.length) + ")"; + } + //else + if ( type == "function" ) { + stack.push( obj ); + res = parser.call( this, obj, stack ); + stack.pop(); + return res; + } + // else + return ( type == "string" ) ? parser : this.parsers.error; + }, + typeOf: function( obj ) { + var type; + if ( obj === null ) { + type = "null"; + } else if ( typeof obj === "undefined" ) { + type = "undefined"; + } else if ( QUnit.is( "regexp", obj) ) { + type = "regexp"; + } else if ( QUnit.is( "date", obj) ) { + type = "date"; + } else if ( QUnit.is( "function", obj) ) { + type = "function"; + } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) { + type = "window"; + } else if ( obj.nodeType === 9 ) { + type = "document"; + } else if ( obj.nodeType ) { + type = "node"; + } else if ( + // native arrays + toString.call( obj ) === "[object Array]" || + // NodeList objects + ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) ) + ) { + type = "array"; + } else { + type = typeof obj; + } + return type; + }, + separator: function() { + return this.multiline ? this.HTML ? "
    " : "\n" : this.HTML ? " " : " "; + }, + indent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing + if ( !this.multiline ) { + return ""; + } + var chr = this.indentChar; + if ( this.HTML ) { + chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); + } + return new Array( this._depth_ + (extra||0) ).join(chr); + }, + up: function( a ) { + this._depth_ += a || 1; + }, + down: function( a ) { + this._depth_ -= a || 1; + }, + setParser: function( name, parser ) { + this.parsers[name] = parser; + }, + // The next 3 are exposed so you can use them + quote: quote, + literal: literal, + join: join, + // + _depth_: 1, + // This is the list of parsers, to modify them, use jsDump.setParser + parsers: { + window: "[Window]", + document: "[Document]", + error: "[ERROR]", //when no parser is found, shouldn"t happen + unknown: "[Unknown]", + "null": "null", + "undefined": "undefined", + "function": function( fn ) { + var ret = "function", + name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];//functions never have name in IE + + if ( name ) { + ret += " " + name; + } + ret += "( "; + + ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" ); + return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" ); + }, + array: array, + nodelist: array, + "arguments": array, + object: function( map, stack ) { + var ret = [ ], keys, key, val, i; + QUnit.jsDump.up(); + if ( Object.keys ) { + keys = Object.keys( map ); + } else { + keys = []; + for ( key in map ) { + keys.push( key ); + } + } + keys.sort(); + for ( i = 0; i < keys.length; i++ ) { + key = keys[ i ]; + val = map[ key ]; + ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) ); + } + QUnit.jsDump.down(); + return join( "{", ret, "}" ); + }, + node: function( node ) { + var a, val, + open = QUnit.jsDump.HTML ? "<" : "<", + close = QUnit.jsDump.HTML ? ">" : ">", + tag = node.nodeName.toLowerCase(), + ret = open + tag; + + for ( a in QUnit.jsDump.DOMAttrs ) { + val = node[ QUnit.jsDump.DOMAttrs[a] ]; + if ( val ) { + ret += " " + a + "=" + QUnit.jsDump.parse( val, "attribute" ); + } + } + return ret + close + open + "/" + tag + close; + }, + functionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function + var args, + l = fn.length; + + if ( !l ) { + return ""; + } + + args = new Array(l); + while ( l-- ) { + args[l] = String.fromCharCode(97+l);//97 is 'a' + } + return " " + args.join( ", " ) + " "; + }, + key: quote, //object calls it internally, the key part of an item in a map + functionCode: "[code]", //function calls it internally, it's the content of the function + attribute: quote, //node calls it internally, it's an html attribute value + string: quote, + date: quote, + regexp: literal, //regex + number: literal, + "boolean": literal + }, + DOMAttrs: { + //attributes to dump from nodes, name=>realName + id: "id", + name: "name", + "class": "className" + }, + HTML: false,//if true, entities are escaped ( <, >, \t, space and \n ) + indentChar: " ",//indentation unit + multiline: true //if true, items in a collection, are separated by a \n, else just a space. + }; + + return jsDump; +}()); + +// from Sizzle.js +function getText( elems ) { + var i, elem, + ret = ""; + + for ( i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +} + +// from jquery.js +function inArray( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; +} + +/* + * Javascript Diff Algorithm + * By John Resig (http://ejohn.org/) + * Modified by Chu Alan "sprite" + * + * Released under the MIT license. + * + * More Info: + * http://ejohn.org/projects/javascript-diff-algorithm/ + * + * Usage: QUnit.diff(expected, actual) + * + * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick brown fox jumped jumps over" + */ +QUnit.diff = (function() { + function diff( o, n ) { + var i, + ns = {}, + os = {}; + + for ( i = 0; i < n.length; i++ ) { + if ( ns[ n[i] ] == null ) { + ns[ n[i] ] = { + rows: [], + o: null + }; + } + ns[ n[i] ].rows.push( i ); + } + + for ( i = 0; i < o.length; i++ ) { + if ( os[ o[i] ] == null ) { + os[ o[i] ] = { + rows: [], + n: null + }; + } + os[ o[i] ].rows.push( i ); + } + + for ( i in ns ) { + if ( !hasOwn.call( ns, i ) ) { + continue; + } + if ( ns[i].rows.length == 1 && typeof os[i] != "undefined" && os[i].rows.length == 1 ) { + n[ ns[i].rows[0] ] = { + text: n[ ns[i].rows[0] ], + row: os[i].rows[0] + }; + o[ os[i].rows[0] ] = { + text: o[ os[i].rows[0] ], + row: ns[i].rows[0] + }; + } + } + + for ( i = 0; i < n.length - 1; i++ ) { + if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && + n[ i + 1 ] == o[ n[i].row + 1 ] ) { + + n[ i + 1 ] = { + text: n[ i + 1 ], + row: n[i].row + 1 + }; + o[ n[i].row + 1 ] = { + text: o[ n[i].row + 1 ], + row: i + 1 + }; + } + } + + for ( i = n.length - 1; i > 0; i-- ) { + if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && + n[ i - 1 ] == o[ n[i].row - 1 ]) { + + n[ i - 1 ] = { + text: n[ i - 1 ], + row: n[i].row - 1 + }; + o[ n[i].row - 1 ] = { + text: o[ n[i].row - 1 ], + row: i - 1 + }; + } + } + + return { + o: o, + n: n + }; + } + + return function( o, n ) { + o = o.replace( /\s+$/, "" ); + n = n.replace( /\s+$/, "" ); + + var i, pre, + str = "", + out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ), + oSpace = o.match(/\s+/g), + nSpace = n.match(/\s+/g); + + if ( oSpace == null ) { + oSpace = [ " " ]; + } + else { + oSpace.push( " " ); + } + + if ( nSpace == null ) { + nSpace = [ " " ]; + } + else { + nSpace.push( " " ); + } + + if ( out.n.length === 0 ) { + for ( i = 0; i < out.o.length; i++ ) { + str += "" + out.o[i] + oSpace[i] + ""; + } + } + else { + if ( out.n[0].text == null ) { + for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) { + str += "" + out.o[n] + oSpace[n] + ""; + } + } + + for ( i = 0; i < out.n.length; i++ ) { + if (out.n[i].text == null) { + str += "" + out.n[i] + nSpace[i] + ""; + } + else { + // `pre` initialized at top of scope + pre = ""; + + for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) { + pre += "" + out.o[n] + oSpace[n] + ""; + } + str += " " + out.n[i].text + nSpace[i] + pre; + } + } + } + + return str; + }; +}()); + +// for CommonJS enviroments, export everything +if ( typeof exports !== "undefined" ) { + extend(exports, QUnit); +} + +// get at whatever the global object is, like window in browsers +}( (function() {return this;}.call()) )); \ No newline at end of file diff --git a/node_modules/json-over-tcp/package.json b/node_modules/json-over-tcp/package.json new file mode 100644 index 0000000..9c6c705 --- /dev/null +++ b/node_modules/json-over-tcp/package.json @@ -0,0 +1,47 @@ +{ + "name": "json-over-tcp", + "version": "0.3.1", + "description": "TCP server/client messaging in JSON", + "main": "index.js", + "dependencies": { + "its": "~1.0.0" + }, + "devDependencies": { + "grunt": "~0.3.15" + }, + "engines": { + "node": "*" + }, + "scripts": { + "test": "grunt test" + }, + "repository": { + "type": "git", + "url": "https://github.com/ozanturgut/json-over-tcp.git" + }, + "keywords": [ + "tcp", + "jot", + "json", + "json-over-tcp", + "server", + "client" + ], + "author": { + "name": "Ozan Turgut", + "email": "ozanturgut@gmail.com", + "url": "http://oztu.org/" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/ozanturgut/json-over-tcp/blob/master/LICENSE-MIT" + } + ], + "readme": "# jot (json-over-tcp) [![Build Status](https://secure.travis-ci.org/ozanturgut/json-over-tcp.png?branch=master)](http://travis-ci.org/ozanturgut/json-over-tcp)\r\n\r\nNode.js TCP server/client messaging in JSON.\r\n\r\nThis library provides a server and a socket class (with APIs that are very similar to the net package in Node.js) which communicate\r\nby sending each other JSON messages.\r\n\r\nYou \"write\" JSON objects to the socket, and the \"data\" events on the other end of the socket emits the JSON object you wrote.\r\n\r\n## A Short Illustration\r\n``` javascript\r\n// assume that I have a jot server listening somewhere and I created a connection to it called \"connection\"\r\nvar someObject = {\r\n \"this property is null\": null,\r\n 1928: 3734,\r\n turtle: {\r\n neck: \"sweater\"\r\n }\r\n};\r\n\r\nconnection.write(someObject);\r\n// Whatever is listening to this connection on the server-side will now recieve a \"data\" event with an object that\r\n// has the same values as \"someObject\".\r\n```\r\n\r\n\r\n## A Real Example\r\n``` javascript\r\n// This script will output \"Client's question: Hello, world?\" and \"Server's answer: 42\" in alternating order\r\n// every second until the script is stopped.\r\n\r\nvar someRandomPort = 8099,\r\n jot = require('json-over-tcp');\r\n\r\nvar server = jot.createServer(someRandomPort);\r\nserver.on('listening', createConnection);\r\nserver.on('connection', newConnectionHandler);\r\n\r\n// Triggered whenever something connects to the server\r\nfunction newConnectionHandler(socket){\r\n // Whenever a connection sends us an object...\r\n socket.on('data', function(data){\r\n // Output the question property of the client's message to the console\r\n console.log(\"Client's question: \" + data.question);\r\n\r\n // Wait one second, then write an answer to the client's socket\r\n setTimeout(function(){\r\n socket.write({answer: 42});\r\n }, 1000);\r\n });\r\n};\r\n\r\n// Creates one connection to the server when the server starts listening\r\nfunction createConnection(){\r\n // Start a connection to the server\r\n var socket = jot.connect(someRandomPort, function(){\r\n // Send the initial message once connected\r\n socket.write({question: \"Hello, world?\"});\r\n });\r\n \r\n // Whenever the server sends us an object...\r\n socket.on('data', function(data){\r\n // Output the answer property of the server's message to the console\r\n console.log(\"Server's answer: \" + data.answer);\r\n \r\n // Wait one second, then write a question to the socket\r\n setTimeout(function(){\r\n // Notice that we \"write\" a JSON object to the socket\r\n socket.write({question: \"Hello, world?\"});\r\n }, 1000);\r\n });\r\n}\r\n\r\n// Start listening\r\nserver.listen(someRandomPort);\r\n```\r\n\r\n## API\r\nThe factory functions below behave similar to node's net package (but they return jot versions of the server or socket).\r\n### ```jot.createServer([options], [connectionListener])```\r\nSee [```net.createServer([options], [connectionListener])```](http://nodejs.org/api/net.html#net_net_createserver_options_connectionlistener).\r\n### ```jot.connect(options, [connectionListener])```\r\nSee [```net.connect(options, [connectionListener])```](http://nodejs.org/api/net.html#net_net_connect_options_connectionlistener).\r\n### ```jot.createConnection(options, [connectionListener])```\r\nSee [```net.createConnection(options, [connectionListener])```](http://nodejs.org/api/net.html#net_net_connect_options_connectionlistener).\r\n### ```jot.connect(port, [host], [connectListener])```\r\nSee [```net.connect(port, [host], [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener).\r\n### ```jot.createConnection(options, [connectionListener])```\r\nSee [```net.createConnection(port, [host], [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener).\r\n### ```jot.connect(path, [connectListener])```\r\nSee [```net.connect(path, [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_path_connectlistener).\r\n### ```jot.createConnection(path, [connectListener])```\r\nSee [```net.createConnection(path, [connectListener])```](http://nodejs.org/api/net.html#net_net_connect_path_connectlistener).\r\n### ```jot.createProtocol(stream)```\r\nFactory function for creating a jot protocol object.\r\n### ```jot.createSocket([options])```\r\nFactory function for creating a jot socket.\r\n\r\n### ```jot.Server```\r\n>The server API is the same as the [```Server``` API in the native 'net' module](http://nodejs.org/api/net.html#net_class_net_server) with the following differences:\r\n##### ```Event: 'connection'``` \r\nEmits a jot socket (see it's API below) instead of a plain tcp socket.\r\n\r\n### ```jot.Socket```\r\n>The socket API is the same as the [```Socket``` API in the native 'net' module](http://nodejs.org/api/net.html#net_class_net_socket) with the following differences:\r\n##### ```Event: 'data'```\r\nEmits a JSON object which was sent by the other end of the socket.\r\n##### ```write(obj)```\r\nSends an object to the other end of the socket. This method doesn't accept any of the other parameters as the plain tcp socket.\r\n\r\n### ```jot.Protocol```\r\n> The protocol object is what serializes/deserializes JSON data over the wire.\r\n##### new Protocol(stream)\r\nTakes in a [```Stream```](http://nodejs.org/api/stream.html) object and reads/writes JSON objects using it's a simple protocol (a protocol signature, message length, and stringified JSON).\r\n##### ```write(obj)``` \r\nWrites an object which can be stringified to the stream.\r\n##### ```on``` \r\nBind to an event (```'data'``` is the only one ever emitted).\r\n##### ```removeListener``` \r\nRemove a bound listener.\r\n##### ```Event: 'data'``` \r\nEmits a JSON object whenever a stream message is recieved.\r\n\r\n## Protocol\r\nIf you would like to implement the protocol yourself, the server will expect the following in order in the byte stream:\r\n\r\n1. 16-bit unsigned little-endian integer with 206 as the value. This is the protocol signature, if a message is sent without this signature a protocol error will be raised.\r\n2. A 32-bit unsigned little-endian integer with the length of the message being sent as the value.\r\n3. A UTF-8 string with the stringified JSON as the value (the message).\r\n", + "_id": "json-over-tcp@0.3.1", + "dist": { + "shasum": "752805786448b1daa1f18932d525f4495c02b53b" + }, + "_from": "json-over-tcp@0.3.1" +} diff --git a/node_modules/json-over-tcp/test/protocol_test.js b/node_modules/json-over-tcp/test/protocol_test.js new file mode 100644 index 0000000..51be191 --- /dev/null +++ b/node_modules/json-over-tcp/test/protocol_test.js @@ -0,0 +1,125 @@ +"use strict"; + +var Stream = require('stream'); +var jsonOverTCP = require('../index.js'), + Protocol = jsonOverTCP.Protocol, + createProtocol = jsonOverTCP.createProtocol, + ProtocolError = jsonOverTCP.ProtocolError; + +var EchoStream = function(){ + Stream.apply(this, arguments); +}; +EchoStream.prototype = Object.create(Stream.prototype); + +EchoStream.prototype.writable = true; +EchoStream.prototype.write = function(data){ + this.emit('data', data); +}; + +var testData = {hello: "world", 42: null}; + +exports.protocol = { + create: function(test){ + test.expect(3); + + var stream = new Stream(); + var validProtocol = new Protocol(stream); + + test.ok(validProtocol instanceof Protocol, 'Unable to construct with valid params'); + + var validProtocol2 = createProtocol(stream); + test.ok(validProtocol2 instanceof Protocol, 'Unable to construct with valid params'); + + var error; + try{ + var invalidProtocol = new Protocol(); + } catch(e){ + error = e; + } + + test.ok(error instanceof TypeError, 'TypeError not thrown for invalid params'); + + test.done(); + }, + readWriteObject: function(test){ + test.expect(1); + + var stream = new EchoStream(); + + var protocol = new Protocol(stream); + + protocol.on('data', function(data){ + test.deepEqual(data, testData, "Serialization/deserialization failure"); + test.done(); + }); + + protocol.write(testData); + }, + readWriteString: function(test){ + test.expect(1); + var testData = "hello, world!"; + var stream = new EchoStream(); + + var protocol = new Protocol(stream); + + protocol.on('data', function(data){ + test.deepEqual(data, testData, "Serialization/deserialization failure"); + test.done(); + }); + + protocol.write(testData); + }, + invalidWrite: function(test){ + test.expect(0); + var testData = function(){ /* unserializable! */ }; + var stream = new EchoStream(); + + var protocol = new Protocol(stream); + + protocol.on('data', function(data){ + test.deepEqual(data, testData, "Serialization/deserialization failure"); + }); + + protocol.write(testData); + test.done(); + }, + invalidRead: function(test){ + test.expect(1); + var testData = function(){ /* unserializable! */ }; + var stream = new EchoStream(); + + var protocol = new Protocol(stream); + + var error; + try{ + stream.write(testData); + } catch(e){ + error = e; + } + + test.ok(error instanceof TypeError, "Invalid stream data didn't throw type error."); + + test.done(); + }, + invalidStreamData: function(test){ + test.expect(1); + var buffer = new Buffer(10); + buffer.write("poop"); + var stream = new EchoStream(); + + var protocol = new Protocol(stream); + protocol.on('data', function(data){ + console.log(data); + }); + var error; + try{ + stream.write(buffer); + } catch(e){ + error = e; + } + + test.ok(error instanceof ProtocolError, "Invalid stream data didn't throw type error."); + + test.done(); + } +}; \ No newline at end of file diff --git a/node_modules/json-over-tcp/test/server_test.js b/node_modules/json-over-tcp/test/server_test.js new file mode 100644 index 0000000..c58d1b5 --- /dev/null +++ b/node_modules/json-over-tcp/test/server_test.js @@ -0,0 +1,69 @@ +"use strict"; + +var net = require('net'); +var jsonOverTCP = require('../index.js'), + Server = jsonOverTCP.Server, + Socket = jsonOverTCP.Socket, + createServer = jsonOverTCP.createServer; + +var TEST_PORT = 8099; + +exports.protocol = { + create: function(test){ + test.expect(2); + + var server = new Server(); + test.ok(server instanceof Server, 'Unable to construct with valid params'); + + var server2 = createServer(); + test.ok(server2 instanceof Server, 'Unable to construct with valid params'); + + test.done(); + }, + listen: function(test){ + test.expect(1); + + var server = new Server(); + var timeout = setTimeout(function(){ + server.close(); + + test.ok(false, "Server failed to start listening"); + test.done(); + },1000); + + server.on('listening', function(){ + clearTimeout(timeout); + server.close(); + + test.ok(true); + test.done(); + }); + server.listen(TEST_PORT); + }, + connection: function(test){ + test.expect(1); + + var server = new Server(); + var connection; + + var timeout = setTimeout(function(){ + server.close(); + connection.destroy(); + test.ok(false, "Server failed to emit connected socket"); + test.done(); + }, 1000); + + server.on('connection', function(socket){ + clearTimeout(timeout); + server.close(); + connection.destroy(); + + test.ok(socket instanceof Socket, "Emitted connections must be instances of the protocol socket."); + test.done(); + }); + + server.listen(TEST_PORT, function(){ + connection = net.connect(TEST_PORT); + }); + } +}; \ No newline at end of file diff --git a/node_modules/json-over-tcp/test/socket_test.js b/node_modules/json-over-tcp/test/socket_test.js new file mode 100644 index 0000000..59279f0 --- /dev/null +++ b/node_modules/json-over-tcp/test/socket_test.js @@ -0,0 +1,108 @@ +"use strict"; + +var net = require('net'); +var jsonOverTCP = require('../index.js'), + Server = jsonOverTCP.Server, + Socket = jsonOverTCP.Socket, + createSocket = jsonOverTCP.createSocket; + +var TEST_PORT = 8099; +var testData = {hello: "world", 42: null}; + +exports.protocol = { + create: function(test){ + test.expect(2); + + var socket = new Socket(); + test.ok(socket instanceof Socket, 'Unable to construct with valid params'); + + var socket2 = createSocket(); + test.ok(socket2 instanceof Socket, 'Unable to construct with valid params'); + + test.done(); + }, + connect: function(test){ + test.expect(1); + + var server = new Server(), + socket; + + var timeout = setTimeout(function(){ + server.close(); + socket.destroy(); + test.ok(false, "Socket failed to connect to server"); + test.done(); + }, 1000); + + server.listen(TEST_PORT, function(){ + socket = new Socket(); + socket.connect(TEST_PORT, function(){ + clearTimeout(timeout); + socket.destroy(); + server.close(); + test.ok(true); + test.done(); + }); + }); + }, + sendData: function(test){ + test.expect(1); + + var server = new Server(), + socket; + + var timeout = setTimeout(function(){ + server.close(); + socket.destroy(); + test.ok(false, "Sending of data failed"); + test.done(); + }, 1000); + + server.on('connection', function(socket){ + socket.on('data', function(data){ + clearTimeout(timeout); + socket.destroy(); + server.close(); + test.deepEqual(data, testData); + test.done(); + }); + }); + + server.listen(TEST_PORT, function(){ + socket = new Socket(); + socket.connect(TEST_PORT, function(){ + socket.write(testData); + }); + }); + }, + recieveData: function(test){ + test.expect(1); + + var server = new Server(), + socket; + + var timeout = setTimeout(function(){ + server.close(); + socket.destroy(); + test.ok(false, "Sending of data failed"); + test.done(); + }, 1000); + + server.on('connection', function(socket){ + socket.write(testData); + }); + + server.listen(TEST_PORT, function(){ + socket = new Socket(); + socket.on('data', function(data){ + clearTimeout(timeout); + socket.destroy(); + server.close(); + test.deepEqual(data, testData); + test.done(); + }); + + socket.connect(TEST_PORT); + }); + } +}; \ No newline at end of file diff --git a/package.json b/package.json index d180e57..03a1827 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,6 @@ , "version" : "0.0.1" , "author" : "Nuno Job (http://nunojob.com)" , "keywords" : ["knockoutjs", "knockout", "express", "expressjs"] -, "dependencies" : {"express": "2.4.x"} +, "dependencies" : {"express": "2.4.x", "json-over-tcp": "0.3.1"} , "main" : "./server.js" } \ No newline at end of file diff --git a/server.js b/server.js index dad020d..fa0568e 100644 --- a/server.js +++ b/server.js @@ -1,7 +1,16 @@ var express = require('express') , app = module.exports = express.createServer() + //, net = require('net') + , jot = require('json-over-tcp') ; +var drone = { + uav_id: 0, + battery_left: 10 +}; + +var drones = new Array(); + app.configure(function(){ app.use(express.bodyParser()); app.use(app.router); @@ -9,24 +18,67 @@ app.configure(function(){ app.use(express.static(__dirname + '/libs')); //js files }); -app.get('/tasks', function (_,response) { - response.send( - [ { "title": "Wire the money to Panama", "isDone": true } - , { "title": "Get hair dye, beard trimmer, dark glasses and \"passport\"", "isDone": false} - , { "title": "Book taxi to airport", "isDone": false } - , { "title": "Arrange for someone to look after the cat", "isDone": false } - ]); -}); +app.post('/fire', function (request,response) { + response.send(request.body); //echo +}); -app.post('/tasks', function (request,response) { +app.post('/drone/:abort', function (request,response) { response.send(request.body); //echo }); -app.listen(process.argv[2]||8082); +/* + Provide API call for drone state information +*/ +app.get('/drone/:id', function (request,response) { + var droneJSON = JSON.stringify(drones[request.params.id]); + response.send(droneJSON); +}); + +app.listen(process.argv[2]||8080); + +var cmdPort = 8082; + +var server = jot.createServer(cmdPort); + + +server.on('connection', newConnectionHandler); + +function droneExists(uav_id) { + console.log("Find drone: " + uav_id); + for (var i = 0; i < drones.length; i++) { + if (drones[i].uav_id == uav_id) return true; + } + return false; +}; + +// Triggered whenever something connects to the server +function newConnectionHandler(socket){ + // Whenever a connection sends us an object... + socket.on('data', function(data){ + // Output the question property of the client's message to the console + console.log("UAV state: " + data.state); + console.log("Battery level: " + data.battery_left); + console.log("Check " + drones.length + " existing drones"); + if (!droneExists(data.uav_id)) { + //drone.uav_id = data.uav_id; + //drone.battery_left = data.battery_left; + drones.push(data); + } + // Wait one second, then write an answer to the client's socket + setTimeout(function(){ + socket.write({answer: 42}); + }, 1000); + }); + +}; + +// Start listening +server.listen(cmdPort); process.on('uncaughtException', function(err) { console.log(JSON.stringify(err)); }); + console.log('Start firefox and point it to http://localhost:8082'); diff --git a/static/index.html b/static/index.html index ffa184c..a60248e 100644 --- a/static/index.html +++ b/static/index.html @@ -2,6 +2,7 @@ + @@ -24,6 +25,19 @@

    UAV Swarm Operator Console

    +
    + + + + + + + + + + +
    ParameterValue
    diff --git a/static/model.js b/static/model.js index 7d914c3..fd84548 100644 --- a/static/model.js +++ b/static/model.js @@ -1,3 +1,43 @@ + +function droneparameter(parameter, value) { + var self = this; + self.parameter = ko.observable(parameter); + self.value = ko.observable(value); +} + +/* +http://gis.stackexchange.com/questions/5265/using-the-proj4js-library-to-convert-from-google-maps-to-projected-values +http://www.spatialmarkets.com/blog/2012/2/29/proj4js-and-on-the-fly-coordinate-conversion.html +*/ + +//collects the X and the Y in state plane, and returns a point with the lat/lng in it... +// check http://spatialreference.org/ref/epsg/32633/ +// from http://www.dmap.co.uk/utmworld.htm we are in zone 31U and not 31Q +function ConvertStatePlane(x,y) { + //Proj4js.defs["EPSG:3419"] = "+proj=lcc +lat_1=39.78333333333333 +lat_2=38.71666666666667 +lat_0=38.33333333333334 +lon_0=-98 +x_0=399999.99998984 +y_0=0 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs"; + Proj4js.defs["GOOGLE"]="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"; + Proj4js.defs["EPSG:4326"] = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"; + Proj4js.defs["EPSG:41001"] = "+title=simple mercator EPSG:41001 +proj=merc +lat_ts=0 +lon_0=0 +k=1.000000 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m"; + //Proj4js.defs["SR-ORG:111"] = "+proj=utm +zone=31 +ellps=clrk66 +units=m +no_defs"; + + //var source = new Proj4js.Proj('EPSG:3419'); + //var dest = new Proj4js.Proj('EPSG:4326'); + //var source = new Proj4js.Proj('SR-ORG:111'); // UTM + var source = new Proj4js.Proj("EPSG:41001"); // UTM + var dest = new Proj4js.Proj('EPSG:4326'); // Google maps + //var dest = new Proj4js.Proj("GOOGLE"); + + var point = new Proj4js.Point(x,y); + Proj4js.transform(source,dest,point); + + alert("Transformed: " + point.y + "," + point.x); + + return point; +} + +/* + Currently the function name "point" is a misnomer. It should be a drone object + */ function point(name, lat, long) { var self = this; // self.id = ko.observable(id); @@ -28,11 +68,11 @@ function point(name, lat, long) { }; self.abortMission = function() { - alert("Mission aborted for " + self.name() + ", return to base..."); + alert("Mission aborted for " + self.name() + ", return to base..."); }; self.startLanding = function() { - alert("Landing started for " + self.name() + "..."); + alert("Landing started for " + self.name() + "..."); }; google.maps.event.addListener(marker, 'mouseover', function() { @@ -42,7 +82,7 @@ function point(name, lat, long) { //if you need the poition while dragging google.maps.event.addListener(marker, 'drag', function() { var pos = marker.getPosition(); - var decimals = 6; + var decimals = 6; self.lat(Math.round(pos.lat()*Math.pow(10,decimals))/Math.pow(10,decimals)); self.long(Math.round(pos.lng()*Math.pow(10,decimals))/Math.pow(10,decimals)); }.bind(this)); @@ -50,7 +90,7 @@ function point(name, lat, long) { //if you just need to update it when the user is done dragging google.maps.event.addListener(marker, 'dragend', function() { var pos = marker.getPosition(); - var decimals = 6; + var decimals = 6; self.lat(Math.round(pos.lat()*Math.pow(10,decimals))/Math.pow(10,decimals)); self.long(Math.round(pos.lng()*Math.pow(10,decimals))/Math.pow(10,decimals)); }.bind(this)); @@ -62,7 +102,7 @@ var map = new google.maps.Map(document.getElementById('map'), { mapTypeId: google.maps.MapTypeId.TERRAIN }); -function viewModel() { +function DroneViewModel() { var self = this; self.chosenUAVId = ko.observable(); self.chosenUAV = ko.observable(); @@ -73,6 +113,10 @@ function viewModel() { new point('UAV 3', 51.450, 4.338), new point('UAV 4', 51.443, 4.337)]) + self.droneparameters = ko.observableArray([ + new droneparameter('Name','anonymous') + ]) + // mission abort of all selected planes self.abortMission = function() { self.chosenUAV().abortMission(); @@ -88,11 +132,31 @@ function viewModel() { self.chosenUAV(uav); }; - self.addUAV = function() { - self.points.push(new point('UAV X', 51.448, 4.34)); + self.addUAV = function(name, x, y) { + var coord = ConvertStatePlane(x,y); + self.points.push(new point(name, coord.x, coord.y)); }; + self.loadUAVs = function () { + $.getJSON('drone/0', function (dronelist) { + self.droneparameters.removeAll(); + $.each(dronelist, function (field, value) { + self.droneparameters.push(new droneparameter(field, value)); + }); + self.addUAV('Test', 8900, 10180); + //for (var i = 0; i < dronelist.length; i++) { + if (droneparameters.uav_id == 0) { + self.addUAV(uav_id, uav_x, uav_y); + } + //} + }); + }; }; + -ko.applyBindings(new viewModel()); +$(function () { + my = { viewModel: new DroneViewModel() }; + ko.applyBindings(my.viewModel); + my.viewModel.loadUAVs(); +});