1 line
407 KiB
Plaintext
1 line
407 KiB
Plaintext
{"version":3,"sources":["../yjs/node_modules/browser-pack/_prelude.js","node_modules/attachmediastream/attachmediastream.js","node_modules/filetransfer/filetransfer.js","node_modules/getscreenmedia/getscreenmedia.js","node_modules/getusermedia/index-browser.js","node_modules/hark/hark.js","node_modules/localmedia/index.js","node_modules/lodash._arrayeach/index.js","node_modules/lodash._arraymap/index.js","node_modules/lodash._basecallback/index.js","node_modules/lodash._baseeach/index.js","node_modules/lodash._baseget/index.js","node_modules/lodash._baseisequal/index.js","node_modules/lodash._bindcallback/index.js","node_modules/lodash._getnative/index.js","node_modules/lodash._topath/index.js","node_modules/lodash.foreach/index.js","node_modules/lodash.isarguments/index.js","node_modules/lodash.isarray/index.js","node_modules/lodash.istypedarray/index.js","node_modules/lodash.keys/index.js","node_modules/lodash.map/index.js","node_modules/lodash.pairs/index.js","node_modules/lodash.pluck/index.js","node_modules/mediastream-gain/mediastream-gain.js","node_modules/mockconsole/mockconsole.js","node_modules/rtcpeerconnection/rtcpeerconnection.js","node_modules/sdp-jingle-json/index.js","node_modules/sdp-jingle-json/lib/parsers.js","node_modules/sdp-jingle-json/lib/senders.js","node_modules/sdp-jingle-json/lib/tojson.js","node_modules/sdp-jingle-json/lib/tosdp.js","node_modules/simplewebrtc/peer.js","node_modules/simplewebrtc/simplewebrtc.js","node_modules/simplewebrtc/socketioconnection.js","node_modules/simplewebrtc/webrtc.js","node_modules/socket.io-client/dist/socket.io.js","node_modules/traceablepeerconnection/index.js","node_modules/webrtc-adapter-test/adapter.js","node_modules/webrtcsupport/index-browser.js","node_modules/wildemitter/wildemitter.js","src/WebRTC.js","../yjs/node_modules/inherits/inherits_browser.js","../yjs/node_modules/process/browser.js","../yjs/node_modules/util/support/isBufferBrowser.js","../yjs/node_modules/util/util.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACl1BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9cA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChyHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpiBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3FA;AACA;AACA;AACA;AACA;AACA;;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"y-webrtc.es6","sourceRoot":"/source/","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})","module.exports = function (stream, el, options) {\n var URL = window.URL;\n var opts = {\n autoplay: true,\n mirror: false,\n muted: false\n };\n var element = el || document.createElement('video');\n var item;\n\n if (options) {\n for (item in options) {\n opts[item] = options[item];\n }\n }\n\n if (opts.autoplay) element.autoplay = 'autoplay';\n if (opts.muted) element.muted = true;\n if (opts.mirror) {\n ['', 'moz', 'webkit', 'o', 'ms'].forEach(function (prefix) {\n var styleName = prefix ? prefix + 'Transform' : 'transform';\n element.style[styleName] = 'scaleX(-1)';\n });\n }\n\n // this first one should work most everywhere now\n // but we have a few fallbacks just in case.\n if (URL && URL.createObjectURL) {\n element.src = URL.createObjectURL(stream);\n } else if (element.srcObject) {\n element.srcObject = stream;\n } else if (element.mozSrcObject) {\n element.mozSrcObject = stream;\n } else {\n return false;\n }\n\n return element;\n};\n","var WildEmitter = require('wildemitter');\nvar util = require('util');\n\nfunction Sender(opts) {\n WildEmitter.call(this);\n var options = opts || {};\n this.config = {\n chunksize: 16384,\n pacing: 0\n };\n // set our config from options\n var item;\n for (item in options) {\n this.config[item] = options[item];\n }\n\n this.file = null;\n this.channel = null;\n}\nutil.inherits(Sender, WildEmitter);\n\nSender.prototype.send = function (file, channel) {\n var self = this;\n this.file = file;\n this.channel = channel;\n var sliceFile = function(offset) {\n var reader = new window.FileReader();\n reader.onload = (function() {\n return function(e) {\n self.channel.send(e.target.result);\n self.emit('progress', offset, file.size, e.target.result);\n if (file.size > offset + e.target.result.byteLength) {\n window.setTimeout(sliceFile, self.config.pacing, offset + self.config.chunksize);\n } else {\n self.emit('progress', file.size, file.size, null);\n self.emit('sentFile');\n }\n };\n })(file);\n var slice = file.slice(offset, offset + self.config.chunksize);\n reader.readAsArrayBuffer(slice);\n };\n window.setTimeout(sliceFile, 0, 0);\n};\n\nfunction Receiver() {\n WildEmitter.call(this);\n\n this.receiveBuffer = [];\n this.received = 0;\n this.metadata = {};\n this.channel = null;\n}\nutil.inherits(Receiver, WildEmitter);\n\nReceiver.prototype.receive = function (metadata, channel) {\n var self = this;\n\n if (metadata) {\n this.metadata = metadata;\n }\n this.channel = channel;\n // chrome only supports arraybuffers and those make it easier to calc the hash\n channel.binaryType = 'arraybuffer';\n this.channel.onmessage = function (event) {\n var len = event.data.byteLength;\n self.received += len;\n self.receiveBuffer.push(event.data);\n\n self.emit('progress', self.received, self.metadata.size, event.data);\n if (self.received === self.metadata.size) {\n self.emit('receivedFile', new window.Blob(self.receiveBuffer), self.metadata);\n self.receiveBuffer = []; // discard receivebuffer\n } else if (self.received > self.metadata.size) {\n // FIXME\n console.error('received more than expected, discarding...');\n self.receiveBuffer = []; // just discard...\n\n }\n };\n};\n\nmodule.exports = {};\nmodule.exports.support = typeof window !== 'undefined' && window && window.File && window.FileReader && window.Blob;\nmodule.exports.Sender = Sender;\nmodule.exports.Receiver = Receiver;\n","// getScreenMedia helper by @HenrikJoreteg\nvar getUserMedia = require('getusermedia');\n\n// cache for constraints and callback\nvar cache = {};\n\nmodule.exports = function (constraints, cb) {\n var hasConstraints = arguments.length === 2;\n var callback = hasConstraints ? cb : constraints;\n var error;\n\n if (typeof window === 'undefined' || window.location.protocol === 'http:') {\n error = new Error('NavigatorUserMediaError');\n error.name = 'HTTPS_REQUIRED';\n return callback(error);\n }\n\n if (window.navigator.userAgent.match('Chrome')) {\n var chromever = parseInt(window.navigator.userAgent.match(/Chrome\\/(.*) /)[1], 10);\n var maxver = 33;\n var isCef = !window.chrome.webstore;\n // \"known\" crash in chrome 34 and 35 on linux\n if (window.navigator.userAgent.match('Linux')) maxver = 35;\n\n // check that the extension is installed by looking for a\n // sessionStorage variable that contains the extension id\n // this has to be set after installation unless the contest\n // script does that\n if (sessionStorage.getScreenMediaJSExtensionId) {\n chrome.runtime.sendMessage(sessionStorage.getScreenMediaJSExtensionId,\n {type:'getScreen', id: 1}, null,\n function (data) {\n if (!data || data.sourceId === '') { // user canceled\n var error = new Error('NavigatorUserMediaError');\n error.name = 'PERMISSION_DENIED';\n callback(error);\n } else {\n constraints = (hasConstraints && constraints) || {audio: false, video: {\n mandatory: {\n chromeMediaSource: 'desktop',\n maxWidth: window.screen.width,\n maxHeight: window.screen.height,\n maxFrameRate: 3\n },\n optional: [\n {googLeakyBucket: true},\n {googTemporalLayeredScreencast: true}\n ]\n }};\n constraints.video.mandatory.chromeMediaSourceId = data.sourceId;\n getUserMedia(constraints, callback);\n }\n }\n );\n } else if (window.cefGetScreenMedia) {\n //window.cefGetScreenMedia is experimental - may be removed without notice\n window.cefGetScreenMedia(function(sourceId) {\n if (!sourceId) {\n var error = new Error('cefGetScreenMediaError');\n error.name = 'CEF_GETSCREENMEDIA_CANCELED';\n callback(error);\n } else {\n constraints = (hasConstraints && constraints) || {audio: false, video: {\n mandatory: {\n chromeMediaSource: 'desktop',\n maxWidth: window.screen.width,\n maxHeight: window.screen.height,\n maxFrameRate: 3\n },\n optional: [\n {googLeakyBucket: true},\n {googTemporalLayeredScreencast: true}\n ]\n }};\n constraints.video.mandatory.chromeMediaSourceId = sourceId;\n getUserMedia(constraints, callback);\n }\n });\n } else if (isCef || (chromever >= 26 && chromever <= maxver)) {\n // chrome 26 - chrome 33 way to do it -- requires bad chrome://flags\n // note: this is basically in maintenance mode and will go away soon\n constraints = (hasConstraints && constraints) || {\n video: {\n mandatory: {\n googLeakyBucket: true,\n maxWidth: window.screen.width,\n maxHeight: window.screen.height,\n maxFrameRate: 3,\n chromeMediaSource: 'screen'\n }\n }\n };\n getUserMedia(constraints, callback);\n } else {\n // chrome 34+ way requiring an extension\n var pending = window.setTimeout(function () {\n error = new Error('NavigatorUserMediaError');\n error.name = 'EXTENSION_UNAVAILABLE';\n return callback(error);\n }, 1000);\n cache[pending] = [callback, hasConstraints ? constraints : null];\n window.postMessage({ type: 'getScreen', id: pending }, '*');\n }\n } else if (window.navigator.userAgent.match('Firefox')) {\n var ffver = parseInt(window.navigator.userAgent.match(/Firefox\\/(.*)/)[1], 10);\n if (ffver >= 33) {\n constraints = (hasConstraints && constraints) || {\n video: {\n mozMediaSource: 'window',\n mediaSource: 'window'\n }\n }\n getUserMedia(constraints, function (err, stream) {\n callback(err, stream);\n // workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1045810\n if (!err) {\n var lastTime = stream.currentTime;\n var polly = window.setInterval(function () {\n if (!stream) window.clearInterval(polly);\n if (stream.currentTime == lastTime) {\n window.clearInterval(polly);\n if (stream.onended) {\n stream.onended();\n }\n }\n lastTime = stream.currentTime;\n }, 500);\n }\n });\n } else {\n error = new Error('NavigatorUserMediaError');\n error.name = 'EXTENSION_UNAVAILABLE'; // does not make much sense but...\n }\n }\n};\n\nwindow.addEventListener('message', function (event) {\n if (event.origin != window.location.origin) {\n return;\n }\n if (event.data.type == 'gotScreen' && cache[event.data.id]) {\n var data = cache[event.data.id];\n var constraints = data[1];\n var callback = data[0];\n delete cache[event.data.id];\n\n if (event.data.sourceId === '') { // user canceled\n var error = new Error('NavigatorUserMediaError');\n error.name = 'PERMISSION_DENIED';\n callback(error);\n } else {\n constraints = constraints || {audio: false, video: {\n mandatory: {\n chromeMediaSource: 'desktop',\n maxWidth: window.screen.width,\n maxHeight: window.screen.height,\n maxFrameRate: 3\n },\n optional: [\n {googLeakyBucket: true},\n {googTemporalLayeredScreencast: true}\n ]\n }};\n constraints.video.mandatory.chromeMediaSourceId = event.data.sourceId;\n getUserMedia(constraints, callback);\n }\n } else if (event.data.type == 'getScreenPending') {\n window.clearTimeout(event.data.id);\n }\n});\n","// getUserMedia helper by @HenrikJoreteg\nvar adapter = require('webrtc-adapter-test');\n\nmodule.exports = function (constraints, cb) {\n var options, error;\n var haveOpts = arguments.length === 2;\n var defaultOpts = {video: true, audio: true};\n\n var denied = 'PermissionDeniedError';\n var altDenied = 'PERMISSION_DENIED';\n var notSatisfied = 'ConstraintNotSatisfiedError';\n\n // make constraints optional\n if (!haveOpts) {\n cb = constraints;\n constraints = defaultOpts;\n }\n\n // treat lack of browser support like an error\n if (!navigator.getUserMedia) {\n // throw proper error per spec\n error = new Error('MediaStreamError');\n error.name = 'NotSupportedError';\n\n // keep all callbacks async\n return window.setTimeout(function () {\n cb(error);\n }, 0);\n }\n\n // normalize error handling when no media types are requested\n if (!constraints.audio && !constraints.video) {\n error = new Error('MediaStreamError');\n error.name = 'NoMediaRequestedError';\n\n // keep all callbacks async\n return window.setTimeout(function () {\n cb(error);\n }, 0);\n }\n\n // testing support\n if (localStorage && localStorage.useFirefoxFakeDevice === \"true\") {\n constraints.fake = true;\n }\n\n navigator.getUserMedia(constraints, function (stream) {\n cb(null, stream);\n }, function (err) {\n var error;\n // coerce into an error object since FF gives us a string\n // there are only two valid names according to the spec\n // we coerce all non-denied to \"constraint not satisfied\".\n if (typeof err === 'string') {\n error = new Error('MediaStreamError');\n if (err === denied || err === altDenied) {\n error.name = denied;\n } else {\n error.name = notSatisfied;\n }\n } else {\n // if we get an error object make sure '.name' property is set\n // according to spec: http://dev.w3.org/2011/webrtc/editor/getusermedia.html#navigatorusermediaerror-and-navigatorusermediaerrorcallback\n error = err;\n if (!error.name) {\n // this is likely chrome which\n // sets a property called \"ERROR_DENIED\" on the error object\n // if so we make sure to set a name\n if (error[denied]) {\n err.name = denied;\n } else {\n err.name = notSatisfied;\n }\n }\n }\n\n cb(error);\n });\n};\n","var WildEmitter = require('wildemitter');\n\nfunction getMaxVolume (analyser, fftBins) {\n var maxVolume = -Infinity;\n analyser.getFloatFrequencyData(fftBins);\n\n for(var i=4, ii=fftBins.length; i < ii; i++) {\n if (fftBins[i] > maxVolume && fftBins[i] < 0) {\n maxVolume = fftBins[i];\n }\n };\n\n return maxVolume;\n}\n\n\nvar audioContextType = window.AudioContext || window.webkitAudioContext;\n// use a single audio context due to hardware limits\nvar audioContext = null;\nmodule.exports = function(stream, options) {\n var harker = new WildEmitter();\n\n\n // make it not break in non-supported browsers\n if (!audioContextType) return harker;\n\n //Config\n var options = options || {},\n smoothing = (options.smoothing || 0.1),\n interval = (options.interval || 50),\n threshold = options.threshold,\n play = options.play,\n history = options.history || 10,\n running = true;\n\n //Setup Audio Context\n if (!audioContext) {\n audioContext = new audioContextType();\n }\n var sourceNode, fftBins, analyser;\n\n analyser = audioContext.createAnalyser();\n analyser.fftSize = 512;\n analyser.smoothingTimeConstant = smoothing;\n fftBins = new Float32Array(analyser.fftSize);\n\n if (stream.jquery) stream = stream[0];\n if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) {\n //Audio Tag\n sourceNode = audioContext.createMediaElementSource(stream);\n if (typeof play === 'undefined') play = true;\n threshold = threshold || -50;\n } else {\n //WebRTC Stream\n sourceNode = audioContext.createMediaStreamSource(stream);\n threshold = threshold || -50;\n }\n\n sourceNode.connect(analyser);\n if (play) analyser.connect(audioContext.destination);\n\n harker.speaking = false;\n\n harker.setThreshold = function(t) {\n threshold = t;\n };\n\n harker.setInterval = function(i) {\n interval = i;\n };\n \n harker.stop = function() {\n running = false;\n harker.emit('volume_change', -100, threshold);\n if (harker.speaking) {\n harker.speaking = false;\n harker.emit('stopped_speaking');\n }\n };\n harker.speakingHistory = [];\n for (var i = 0; i < history; i++) {\n harker.speakingHistory.push(0);\n }\n\n // Poll the analyser node to determine if speaking\n // and emit events if changed\n var looper = function() {\n setTimeout(function() {\n \n //check if stop has been called\n if(!running) {\n return;\n }\n \n var currentVolume = getMaxVolume(analyser, fftBins);\n\n harker.emit('volume_change', currentVolume, threshold);\n\n var history = 0;\n if (currentVolume > threshold && !harker.speaking) {\n // trigger quickly, short history\n for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) {\n history += harker.speakingHistory[i];\n }\n if (history >= 2) {\n harker.speaking = true;\n harker.emit('speaking');\n }\n } else if (currentVolume < threshold && harker.speaking) {\n for (var i = 0; i < harker.speakingHistory.length; i++) {\n history += harker.speakingHistory[i];\n }\n if (history == 0) {\n harker.speaking = false;\n harker.emit('stopped_speaking');\n }\n }\n harker.speakingHistory.shift();\n harker.speakingHistory.push(0 + (currentVolume > threshold));\n\n looper();\n }, interval);\n };\n looper();\n\n\n return harker;\n}\n","var util = require('util');\nvar hark = require('hark');\nvar webrtc = require('webrtcsupport');\nvar getUserMedia = require('getusermedia');\nvar getScreenMedia = require('getscreenmedia');\nvar WildEmitter = require('wildemitter');\nvar GainController = require('mediastream-gain');\nvar mockconsole = require('mockconsole');\n\n\nfunction LocalMedia(opts) {\n WildEmitter.call(this);\n\n var config = this.config = {\n autoAdjustMic: false,\n detectSpeakingEvents: true,\n audioFallback: false,\n media: {\n audio: true,\n video: true\n },\n logger: mockconsole\n };\n\n var item;\n for (item in opts) {\n this.config[item] = opts[item];\n }\n\n this.logger = config.logger;\n this._log = this.logger.log.bind(this.logger, 'LocalMedia:');\n this._logerror = this.logger.error.bind(this.logger, 'LocalMedia:');\n\n this.screenSharingSupport = webrtc.screenSharing;\n\n this.localStreams = [];\n this.localScreens = [];\n\n if (!webrtc.support) {\n this._logerror('Your browser does not support local media capture.');\n }\n}\n\nutil.inherits(LocalMedia, WildEmitter);\n\n\nLocalMedia.prototype.start = function (mediaConstraints, cb) {\n var self = this;\n var constraints = mediaConstraints || this.config.media;\n\n getUserMedia(constraints, function (err, stream) {\n\n if (!err) {\n if (constraints.audio && self.config.detectSpeakingEvents) {\n self.setupAudioMonitor(stream, self.config.harkOptions);\n }\n self.localStreams.push(stream);\n\n if (self.config.autoAdjustMic) {\n self.gainController = new GainController(stream);\n // start out somewhat muted if we can track audio\n self.setMicIfEnabled(0.5);\n }\n\n // TODO: might need to migrate to the video tracks onended\n // FIXME: firefox does not seem to trigger this...\n stream.onended = function () {\n /*\n var idx = self.localStreams.indexOf(stream);\n if (idx > -1) {\n self.localScreens.splice(idx, 1);\n }\n self.emit('localStreamStopped', stream);\n */\n };\n\n self.emit('localStream', stream);\n } else {\n // Fallback for users without a camera\n if (self.config.audioFallback && err.name === 'DevicesNotFoundError' && constraints.video !== false) {\n constraints.video = false;\n self.start(constraints, cb);\n return;\n }\n }\n if (cb) {\n return cb(err, stream);\n }\n });\n};\n\nLocalMedia.prototype.stop = function (stream) {\n var self = this;\n // FIXME: duplicates cleanup code until fixed in FF\n if (stream) {\n stream.getTracks().forEach(function (track) { track.stop(); });\n var idx = self.localStreams.indexOf(stream);\n if (idx > -1) {\n self.emit('localStreamStopped', stream);\n self.localStreams = self.localStreams.splice(idx, 1);\n } else {\n idx = self.localScreens.indexOf(stream);\n if (idx > -1) {\n self.emit('localScreenStopped', stream);\n self.localScreens = self.localScreens.splice(idx, 1);\n }\n }\n } else {\n this.stopStreams();\n this.stopScreenShare();\n }\n};\n\nLocalMedia.prototype.stopStreams = function () {\n var self = this;\n if (this.audioMonitor) {\n this.audioMonitor.stop();\n delete this.audioMonitor;\n }\n this.localStreams.forEach(function (stream) {\n stream.getTracks().forEach(function (track) { track.stop(); });\n self.emit('localStreamStopped', stream);\n });\n this.localStreams = [];\n};\n\nLocalMedia.prototype.startScreenShare = function (cb) {\n var self = this;\n getScreenMedia(function (err, stream) {\n if (!err) {\n self.localScreens.push(stream);\n\n // TODO: might need to migrate to the video tracks onended\n // Firefox does not support .onended but it does not support\n // screensharing either\n stream.onended = function () {\n var idx = self.localScreens.indexOf(stream);\n if (idx > -1) {\n self.localScreens.splice(idx, 1);\n }\n self.emit('localScreenStopped', stream);\n };\n self.emit('localScreen', stream);\n }\n\n // enable the callback\n if (cb) {\n return cb(err, stream);\n }\n });\n};\n\nLocalMedia.prototype.stopScreenShare = function (stream) {\n var self = this;\n if (stream) {\n stream.getTracks().forEach(function (track) { track.stop(); });\n this.emit('localScreenStopped', stream);\n } else {\n this.localScreens.forEach(function (stream) {\n stream.getTracks().forEach(function (track) { track.stop(); });\n self.emit('localScreenStopped', stream);\n });\n this.localScreens = [];\n }\n};\n\n// Audio controls\nLocalMedia.prototype.mute = function () {\n this._audioEnabled(false);\n this.hardMuted = true;\n this.emit('audioOff');\n};\n\nLocalMedia.prototype.unmute = function () {\n this._audioEnabled(true);\n this.hardMuted = false;\n this.emit('audioOn');\n};\n\nLocalMedia.prototype.setupAudioMonitor = function (stream, harkOptions) {\n this._log('Setup audio');\n var audio = this.audioMonitor = hark(stream, harkOptions);\n var self = this;\n var timeout;\n\n audio.on('speaking', function () {\n self.emit('speaking');\n if (self.hardMuted) {\n return;\n }\n self.setMicIfEnabled(1);\n });\n\n audio.on('stopped_speaking', function () {\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(function () {\n self.emit('stoppedSpeaking');\n if (self.hardMuted) {\n return;\n }\n self.setMicIfEnabled(0.5);\n }, 1000);\n });\n audio.on('volume_change', function (volume, treshold) {\n self.emit('volumeChange', volume, treshold);\n });\n};\n\n// We do this as a seperate method in order to\n// still leave the \"setMicVolume\" as a working\n// method.\nLocalMedia.prototype.setMicIfEnabled = function (volume) {\n if (!this.config.autoAdjustMic) {\n return;\n }\n this.gainController.setGain(volume);\n};\n\n// Video controls\nLocalMedia.prototype.pauseVideo = function () {\n this._videoEnabled(false);\n this.emit('videoOff');\n};\nLocalMedia.prototype.resumeVideo = function () {\n this._videoEnabled(true);\n this.emit('videoOn');\n};\n\n// Combined controls\nLocalMedia.prototype.pause = function () {\n this.mute();\n this.pauseVideo();\n};\nLocalMedia.prototype.resume = function () {\n this.unmute();\n this.resumeVideo();\n};\n\n// Internal methods for enabling/disabling audio/video\nLocalMedia.prototype._audioEnabled = function (bool) {\n // work around for chrome 27 bug where disabling tracks\n // doesn't seem to work (works in canary, remove when working)\n this.setMicIfEnabled(bool ? 1 : 0);\n this.localStreams.forEach(function (stream) {\n stream.getAudioTracks().forEach(function (track) {\n track.enabled = !!bool;\n });\n });\n};\nLocalMedia.prototype._videoEnabled = function (bool) {\n this.localStreams.forEach(function (stream) {\n stream.getVideoTracks().forEach(function (track) {\n track.enabled = !!bool;\n });\n });\n};\n\n// check if all audio streams are enabled\nLocalMedia.prototype.isAudioEnabled = function () {\n var enabled = true;\n this.localStreams.forEach(function (stream) {\n stream.getAudioTracks().forEach(function (track) {\n enabled = enabled && track.enabled;\n });\n });\n return enabled;\n};\n\n// check if all video streams are enabled\nLocalMedia.prototype.isVideoEnabled = function () {\n var enabled = true;\n this.localStreams.forEach(function (stream) {\n stream.getVideoTracks().forEach(function (track) {\n enabled = enabled && track.enabled;\n });\n });\n return enabled;\n};\n\n// Backwards Compat\nLocalMedia.prototype.startLocalMedia = LocalMedia.prototype.start;\nLocalMedia.prototype.stopLocalMedia = LocalMedia.prototype.stop;\n\n// fallback for old .localStream behaviour\nObject.defineProperty(LocalMedia.prototype, 'localStream', {\n get: function () {\n return this.localStreams.length > 0 ? this.localStreams[0] : null;\n }\n});\n// fallback for old .localScreen behaviour\nObject.defineProperty(LocalMedia.prototype, 'localScreen', {\n get: function () {\n return this.localScreens.length > 0 ? this.localScreens[0] : null;\n }\n});\n\nmodule.exports = LocalMedia;\n","/**\n * lodash 3.0.0 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/**\n * A specialized version of `_.forEach` for arrays without support for callback\n * shorthands or `this` binding.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n var index = -1,\n length = array.length;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n}\n\nmodule.exports = arrayEach;\n","/**\n * lodash 3.0.0 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/**\n * A specialized version of `_.map` for arrays without support for callback\n * shorthands or `this` binding.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nmodule.exports = arrayMap;\n","/**\n * lodash 3.3.1 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar baseIsEqual = require('lodash._baseisequal'),\n bindCallback = require('lodash._bindcallback'),\n isArray = require('lodash.isarray'),\n pairs = require('lodash.pairs');\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/,\n rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\n\\\\]|\\\\.)*?)\\2)\\]/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `value` to a string if it's not one. An empty string is returned\n * for `null` or `undefined` values.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n return value == null ? '' : (value + '');\n}\n\n/**\n * The base implementation of `_.callback` which supports specifying the\n * number of arguments to provide to `func`.\n *\n * @private\n * @param {*} [func=_.identity] The value to convert to a callback.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {number} [argCount] The number of arguments to provide to `func`.\n * @returns {Function} Returns the callback.\n */\nfunction baseCallback(func, thisArg, argCount) {\n var type = typeof func;\n if (type == 'function') {\n return thisArg === undefined\n ? func\n : bindCallback(func, thisArg, argCount);\n }\n if (func == null) {\n return identity;\n }\n if (type == 'object') {\n return baseMatches(func);\n }\n return thisArg === undefined\n ? property(func)\n : baseMatchesProperty(func, thisArg);\n}\n\n/**\n * The base implementation of `get` without support for string paths\n * and default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} path The path of the property to get.\n * @param {string} [pathKey] The key representation of path.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path, pathKey) {\n if (object == null) {\n return;\n }\n if (pathKey !== undefined && pathKey in toObject(object)) {\n path = [pathKey];\n }\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[path[index++]];\n }\n return (index && index == length) ? object : undefined;\n}\n\n/**\n * The base implementation of `_.isMatch` without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Array} matchData The propery names, values, and compare flags to match.\n * @param {Function} [customizer] The function to customize comparing objects.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n */\nfunction baseIsMatch(object, matchData, customizer) {\n var index = matchData.length,\n length = index,\n noCustomizer = !customizer;\n\n if (object == null) {\n return !length;\n }\n object = toObject(object);\n while (index--) {\n var data = matchData[index];\n if ((noCustomizer && data[2])\n ? data[1] !== object[data[0]]\n : !(data[0] in object)\n ) {\n return false;\n }\n }\n while (++index < length) {\n data = matchData[index];\n var key = data[0],\n objValue = object[key],\n srcValue = data[1];\n\n if (noCustomizer && data[2]) {\n if (objValue === undefined && !(key in object)) {\n return false;\n }\n } else {\n var result = customizer ? customizer(objValue, srcValue, key) : undefined;\n if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {\n return false;\n }\n }\n }\n return true;\n}\n\n/**\n * The base implementation of `_.matches` which does not clone `source`.\n *\n * @private\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new function.\n */\nfunction baseMatches(source) {\n var matchData = getMatchData(source);\n if (matchData.length == 1 && matchData[0][2]) {\n var key = matchData[0][0],\n value = matchData[0][1];\n\n return function(object) {\n if (object == null) {\n return false;\n }\n return object[key] === value && (value !== undefined || (key in toObject(object)));\n };\n }\n return function(object) {\n return baseIsMatch(object, matchData);\n };\n}\n\n/**\n * The base implementation of `_.matchesProperty` which does not clone `srcValue`.\n *\n * @private\n * @param {string} path The path of the property to get.\n * @param {*} srcValue The value to compare.\n * @returns {Function} Returns the new function.\n */\nfunction baseMatchesProperty(path, srcValue) {\n var isArr = isArray(path),\n isCommon = isKey(path) && isStrictComparable(srcValue),\n pathKey = (path + '');\n\n path = toPath(path);\n return function(object) {\n if (object == null) {\n return false;\n }\n var key = pathKey;\n object = toObject(object);\n if ((isArr || !isCommon) && !(key in object)) {\n object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n if (object == null) {\n return false;\n }\n key = last(path);\n object = toObject(object);\n }\n return object[key] === srcValue\n ? (srcValue !== undefined || (key in object))\n : baseIsEqual(srcValue, object[key], undefined, true);\n };\n}\n\n/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\n/**\n * A specialized version of `baseProperty` which supports deep paths.\n *\n * @private\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction basePropertyDeep(path) {\n var pathKey = (path + '');\n path = toPath(path);\n return function(object) {\n return baseGet(object, path, pathKey);\n };\n}\n\n/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n start = start == null ? 0 : (+start || 0);\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = (end === undefined || end > length) ? length : (+end || 0);\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n}\n\n/**\n * Gets the propery names, values, and compare flags of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the match data of `object`.\n */\nfunction getMatchData(object) {\n var result = pairs(object),\n length = result.length;\n\n while (length--) {\n result[length][2] = isStrictComparable(result[length][1]);\n }\n return result;\n}\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n var type = typeof value;\n if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {\n return true;\n }\n if (isArray(value)) {\n return false;\n }\n var result = !reIsDeepProp.test(value);\n return result || (object != null && value in toObject(object));\n}\n\n/**\n * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` if suitable for strict\n * equality comparisons, else `false`.\n */\nfunction isStrictComparable(value) {\n return value === value && !isObject(value);\n}\n\n/**\n * Converts `value` to an object if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Object} Returns the object.\n */\nfunction toObject(value) {\n return isObject(value) ? value : Object(value);\n}\n\n/**\n * Converts `value` to property path array if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Array} Returns the property path array.\n */\nfunction toPath(value) {\n if (isArray(value)) {\n return value;\n }\n var result = [];\n baseToString(value).replace(rePropName, function(match, number, quote, string) {\n result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n}\n\n/**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\nfunction last(array) {\n var length = array ? array.length : 0;\n return length ? array[length - 1] : undefined;\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * This method returns the first argument provided to it.\n *\n * @static\n * @memberOf _\n * @category Utility\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'user': 'fred' };\n *\n * _.identity(object) === object;\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\n/**\n * Creates a function that returns the property value at `path` on a\n * given object.\n *\n * @static\n * @memberOf _\n * @category Utility\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': { 'c': 2 } } },\n * { 'a': { 'b': { 'c': 1 } } }\n * ];\n *\n * _.map(objects, _.property('a.b.c'));\n * // => [2, 1]\n *\n * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');\n * // => [1, 2]\n */\nfunction property(path) {\n return isKey(path) ? baseProperty(path) : basePropertyDeep(path);\n}\n\nmodule.exports = baseCallback;\n","/**\n * lodash 3.0.4 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar keys = require('lodash.keys');\n\n/**\n * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * The base implementation of `_.forEach` without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object|string} Returns `collection`.\n */\nvar baseEach = createBaseEach(baseForOwn);\n\n/**\n * The base implementation of `baseForIn` and `baseForOwn` which iterates\n * over `object` properties returned by `keysFunc` invoking `iteratee` for\n * each property. Iteratee functions may exit iteration early by explicitly\n * returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\nvar baseFor = createBaseFor();\n\n/**\n * The base implementation of `_.forOwn` without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\nfunction baseForOwn(object, iteratee) {\n return baseFor(object, iteratee, keys);\n}\n\n/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\n/**\n * Creates a `baseEach` or `baseEachRight` function.\n *\n * @private\n * @param {Function} eachFunc The function to iterate over a collection.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseEach(eachFunc, fromRight) {\n return function(collection, iteratee) {\n var length = collection ? getLength(collection) : 0;\n if (!isLength(length)) {\n return eachFunc(collection, iteratee);\n }\n var index = fromRight ? length : -1,\n iterable = toObject(collection);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (iteratee(iterable[index], index, iterable) === false) {\n break;\n }\n }\n return collection;\n };\n}\n\n/**\n * Creates a base function for `_.forIn` or `_.forInRight`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var iterable = toObject(object),\n props = keysFunc(object),\n length = props.length,\n index = fromRight ? length : -1;\n\n while ((fromRight ? index-- : ++index < length)) {\n var key = props[index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n}\n\n/**\n * Gets the \"length\" property value of `object`.\n *\n * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)\n * that affects Safari on at least iOS 8.1-8.3 ARM64.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {*} Returns the \"length\" value.\n */\nvar getLength = baseProperty('length');\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n */\nfunction isLength(value) {\n return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Converts `value` to an object if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Object} Returns the object.\n */\nfunction toObject(value) {\n return isObject(value) ? value : Object(value);\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\nmodule.exports = baseEach;\n","/**\n * lodash 3.7.2 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/**\n * The base implementation of `get` without support for string paths\n * and default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} path The path of the property to get.\n * @param {string} [pathKey] The key representation of path.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path, pathKey) {\n if (object == null) {\n return;\n }\n if (pathKey !== undefined && pathKey in toObject(object)) {\n path = [pathKey];\n }\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[path[index++]];\n }\n return (index && index == length) ? object : undefined;\n}\n\n/**\n * Converts `value` to an object if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Object} Returns the object.\n */\nfunction toObject(value) {\n return isObject(value) ? value : Object(value);\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\nmodule.exports = baseGet;\n","/**\n * lodash 3.0.7 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar isArray = require('lodash.isarray'),\n isTypedArray = require('lodash.istypedarray'),\n keys = require('lodash.keys');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n stringTag = '[object String]';\n\n/**\n * Checks if `value` is object-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * A specialized version of `_.some` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * The base implementation of `_.isEqual` without support for `this` binding\n * `customizer` functions.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {Function} [customizer] The function to customize comparing values.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA] Tracks traversed `value` objects.\n * @param {Array} [stackB] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);\n}\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} [customizer] The function to customize comparing objects.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA=[]] Tracks traversed `value` objects.\n * @param {Array} [stackB=[]] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = arrayTag,\n othTag = arrayTag;\n\n if (!objIsArr) {\n objTag = objToString.call(object);\n if (objTag == argsTag) {\n objTag = objectTag;\n } else if (objTag != objectTag) {\n objIsArr = isTypedArray(object);\n }\n }\n if (!othIsArr) {\n othTag = objToString.call(other);\n if (othTag == argsTag) {\n othTag = objectTag;\n } else if (othTag != objectTag) {\n othIsArr = isTypedArray(other);\n }\n }\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && !(objIsArr || objIsObj)) {\n return equalByTag(object, other, objTag);\n }\n if (!isLoose) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);\n }\n }\n if (!isSameTag) {\n return false;\n }\n // Assume cyclic values are equal.\n // For more information on detecting circular references see https://es5.github.io/#JO.\n stackA || (stackA = []);\n stackB || (stackB = []);\n\n var length = stackA.length;\n while (length--) {\n if (stackA[length] == object) {\n return stackB[length] == other;\n }\n }\n // Add `object` and `other` to the stack of traversed objects.\n stackA.push(object);\n stackB.push(other);\n\n var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);\n\n stackA.pop();\n stackB.pop();\n\n return result;\n}\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} [customizer] The function to customize comparing arrays.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA] Tracks traversed `value` objects.\n * @param {Array} [stackB] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {\n var index = -1,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isLoose && othLength > arrLength)) {\n return false;\n }\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index],\n result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;\n\n if (result !== undefined) {\n if (result) {\n continue;\n }\n return false;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (isLoose) {\n if (!arraySome(other, function(othValue) {\n return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);\n })) {\n return false;\n }\n } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} value The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag) {\n switch (tag) {\n case boolTag:\n case dateTag:\n // Coerce dates and booleans to numbers, dates to milliseconds and booleans\n // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.\n return +object == +other;\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case numberTag:\n // Treat `NaN` vs. `NaN` as equal.\n return (object != +object)\n ? other != +other\n : object == +other;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings primitives and string\n // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.\n return object == (other + '');\n }\n return false;\n}\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} [customizer] The function to customize comparing values.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA] Tracks traversed `value` objects.\n * @param {Array} [stackB] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n var objProps = keys(object),\n objLength = objProps.length,\n othProps = keys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isLoose) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n var skipCtor = isLoose;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key],\n result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;\n\n // Recursively compare objects (susceptible to call stack limits).\n if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {\n return false;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (!skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\nmodule.exports = baseIsEqual;\n","/**\n * lodash 3.0.1 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/**\n * A specialized version of `baseCallback` which only supports `this` binding\n * and specifying the number of arguments to provide to `func`.\n *\n * @private\n * @param {Function} func The function to bind.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {number} [argCount] The number of arguments to provide to `func`.\n * @returns {Function} Returns the callback.\n */\nfunction bindCallback(func, thisArg, argCount) {\n if (typeof func != 'function') {\n return identity;\n }\n if (thisArg === undefined) {\n return func;\n }\n switch (argCount) {\n case 1: return function(value) {\n return func.call(thisArg, value);\n };\n case 3: return function(value, index, collection) {\n return func.call(thisArg, value, index, collection);\n };\n case 4: return function(accumulator, value, index, collection) {\n return func.call(thisArg, accumulator, value, index, collection);\n };\n case 5: return function(value, other, key, object, source) {\n return func.call(thisArg, value, other, key, object, source);\n };\n }\n return function() {\n return func.apply(thisArg, arguments);\n };\n}\n\n/**\n * This method returns the first argument provided to it.\n *\n * @static\n * @memberOf _\n * @category Utility\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'user': 'fred' };\n *\n * _.identity(object) === object;\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nmodule.exports = bindCallback;\n","/**\n * lodash 3.9.1 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/** `Object#toString` result references. */\nvar funcTag = '[object Function]';\n\n/** Used to detect host constructors (Safari > 5). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/**\n * Checks if `value` is object-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar fnToString = Function.prototype.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n fnToString.call(hasOwnProperty).replace(/[\\\\^$.*+?()[\\]{}|]/g, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = object == null ? undefined : object[key];\n return isNative(value) ? value : undefined;\n}\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in older versions of Chrome and Safari which return 'function' for regexes\n // and Safari 8 equivalents which return 'object' for typed array constructors.\n return isObject(value) && objToString.call(value) == funcTag;\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is a native function.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function, else `false`.\n * @example\n *\n * _.isNative(Array.prototype.push);\n * // => true\n *\n * _.isNative(_);\n * // => false\n */\nfunction isNative(value) {\n if (value == null) {\n return false;\n }\n if (isFunction(value)) {\n return reIsNative.test(fnToString.call(value));\n }\n return isObjectLike(value) && reIsHostCtor.test(value);\n}\n\nmodule.exports = getNative;\n","/**\n * lodash 3.8.1 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar isArray = require('lodash.isarray');\n\n/** Used to match property names within property paths. */\nvar rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\n\\\\]|\\\\.)*?)\\2)\\]/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `value` to a string if it's not one. An empty string is returned\n * for `null` or `undefined` values.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n return value == null ? '' : (value + '');\n}\n\n/**\n * Converts `value` to property path array if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Array} Returns the property path array.\n */\nfunction toPath(value) {\n if (isArray(value)) {\n return value;\n }\n var result = [];\n baseToString(value).replace(rePropName, function(match, number, quote, string) {\n result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n}\n\nmodule.exports = toPath;\n","/**\n * lodash 3.0.3 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar arrayEach = require('lodash._arrayeach'),\n baseEach = require('lodash._baseeach'),\n bindCallback = require('lodash._bindcallback'),\n isArray = require('lodash.isarray');\n\n/**\n * Creates a function for `_.forEach` or `_.forEachRight`.\n *\n * @private\n * @param {Function} arrayFunc The function to iterate over an array.\n * @param {Function} eachFunc The function to iterate over a collection.\n * @returns {Function} Returns the new each function.\n */\nfunction createForEach(arrayFunc, eachFunc) {\n return function(collection, iteratee, thisArg) {\n return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))\n ? arrayFunc(collection, iteratee)\n : eachFunc(collection, bindCallback(iteratee, thisArg, 3));\n };\n}\n\n/**\n * Iterates over elements of `collection` invoking `iteratee` for each element.\n * The `iteratee` is bound to `thisArg` and invoked with three arguments:\n * (value, index|key, collection). Iteratee functions may exit iteration early\n * by explicitly returning `false`.\n *\n * **Note:** As with other \"Collections\" methods, objects with a \"length\" property\n * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`\n * may be used for object iteration.\n *\n * @static\n * @memberOf _\n * @alias each\n * @category Collection\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [thisArg] The `this` binding of `iteratee`.\n * @returns {Array|Object|string} Returns `collection`.\n * @example\n *\n * _([1, 2]).forEach(function(n) {\n * console.log(n);\n * }).value();\n * // => logs each value from left to right and returns the array\n *\n * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {\n * console.log(n, key);\n * });\n * // => logs each value-key pair and returns the object (iteration order is not guaranteed)\n */\nvar forEach = createForEach(arrayEach, baseEach);\n\nmodule.exports = forEach;\n","/**\n * lodash 3.0.4 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/**\n * Checks if `value` is object-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Native method references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\n/**\n * Gets the \"length\" property value of `object`.\n *\n * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)\n * that affects Safari on at least iOS 8.1-8.3 ARM64.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {*} Returns the \"length\" value.\n */\nvar getLength = baseProperty('length');\n\n/**\n * Checks if `value` is array-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n */\nfunction isArrayLike(value) {\n return value != null && isLength(getLength(value));\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n */\nfunction isLength(value) {\n return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is classified as an `arguments` object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nfunction isArguments(value) {\n return isObjectLike(value) && isArrayLike(value) &&\n hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');\n}\n\nmodule.exports = isArguments;\n","/**\n * lodash 3.0.4 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/** `Object#toString` result references. */\nvar arrayTag = '[object Array]',\n funcTag = '[object Function]';\n\n/** Used to detect host constructors (Safari > 5). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/**\n * Checks if `value` is object-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar fnToString = Function.prototype.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n fnToString.call(hasOwnProperty).replace(/[\\\\^$.*+?()[\\]{}|]/g, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeIsArray = getNative(Array, 'isArray');\n\n/**\n * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = object == null ? undefined : object[key];\n return isNative(value) ? value : undefined;\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n */\nfunction isLength(value) {\n return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(function() { return arguments; }());\n * // => false\n */\nvar isArray = nativeIsArray || function(value) {\n return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;\n};\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in older versions of Chrome and Safari which return 'function' for regexes\n // and Safari 8 equivalents which return 'object' for typed array constructors.\n return isObject(value) && objToString.call(value) == funcTag;\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is a native function.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function, else `false`.\n * @example\n *\n * _.isNative(Array.prototype.push);\n * // => true\n *\n * _.isNative(_);\n * // => false\n */\nfunction isNative(value) {\n if (value == null) {\n return false;\n }\n if (isFunction(value)) {\n return reIsNative.test(fnToString.call(value));\n }\n return isObjectLike(value) && reIsHostCtor.test(value);\n}\n\nmodule.exports = isArray;\n","/**\n * lodash 3.0.2 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dateTag] = typedArrayTags[errorTag] =\ntypedArrayTags[funcTag] = typedArrayTags[mapTag] =\ntypedArrayTags[numberTag] = typedArrayTags[objectTag] =\ntypedArrayTags[regexpTag] = typedArrayTags[setTag] =\ntypedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;\n\n/**\n * Checks if `value` is object-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n */\nfunction isLength(value) {\n return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nfunction isTypedArray(value) {\n return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];\n}\n\nmodule.exports = isTypedArray;\n","/**\n * lodash 3.1.2 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar getNative = require('lodash._getnative'),\n isArguments = require('lodash.isarguments'),\n isArray = require('lodash.isarray');\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^\\d+$/;\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = getNative(Object, 'keys');\n\n/**\n * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\n/**\n * Gets the \"length\" property value of `object`.\n *\n * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)\n * that affects Safari on at least iOS 8.1-8.3 ARM64.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {*} Returns the \"length\" value.\n */\nvar getLength = baseProperty('length');\n\n/**\n * Checks if `value` is array-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n */\nfunction isArrayLike(value) {\n return value != null && isLength(getLength(value));\n}\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;\n length = length == null ? MAX_SAFE_INTEGER : length;\n return value > -1 && value % 1 == 0 && value < length;\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n */\nfunction isLength(value) {\n return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * A fallback implementation of `Object.keys` which creates an array of the\n * own enumerable property names of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction shimKeys(object) {\n var props = keysIn(object),\n propsLength = props.length,\n length = propsLength && object.length;\n\n var allowIndexes = !!length && isLength(length) &&\n (isArray(object) || isArguments(object));\n\n var index = -1,\n result = [];\n\n while (++index < propsLength) {\n var key = props[index];\n if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {\n result.push(key);\n }\n }\n return result;\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nvar keys = !nativeKeys ? shimKeys : function(object) {\n var Ctor = object == null ? undefined : object.constructor;\n if ((typeof Ctor == 'function' && Ctor.prototype === object) ||\n (typeof object != 'function' && isArrayLike(object))) {\n return shimKeys(object);\n }\n return isObject(object) ? nativeKeys(object) : [];\n};\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n if (object == null) {\n return [];\n }\n if (!isObject(object)) {\n object = Object(object);\n }\n var length = object.length;\n length = (length && isLength(length) &&\n (isArray(object) || isArguments(object)) && length) || 0;\n\n var Ctor = object.constructor,\n index = -1,\n isProto = typeof Ctor == 'function' && Ctor.prototype === object,\n result = Array(length),\n skipIndexes = length > 0;\n\n while (++index < length) {\n result[index] = (index + '');\n }\n for (var key in object) {\n if (!(skipIndexes && isIndex(key, length)) &&\n !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = keys;\n","/**\n * lodash 3.1.4 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar arrayMap = require('lodash._arraymap'),\n baseCallback = require('lodash._basecallback'),\n baseEach = require('lodash._baseeach'),\n isArray = require('lodash.isarray');\n\n/**\n * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * The base implementation of `_.map` without support for callback shorthands\n * and `this` binding.\n *\n * @private\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction baseMap(collection, iteratee) {\n var index = -1,\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value, key, collection) {\n result[++index] = iteratee(value, key, collection);\n });\n return result;\n}\n\n/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\n/**\n * Gets the \"length\" property value of `object`.\n *\n * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)\n * that affects Safari on at least iOS 8.1-8.3 ARM64.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {*} Returns the \"length\" value.\n */\nvar getLength = baseProperty('length');\n\n/**\n * Checks if `value` is array-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n */\nfunction isArrayLike(value) {\n return value != null && isLength(getLength(value));\n}\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n */\nfunction isLength(value) {\n return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\n/**\n * Creates an array of values by running each element in `collection` through\n * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three\n * arguments: (value, index|key, collection).\n *\n * If a property name is provided for `iteratee` the created `_.property`\n * style callback returns the property value of the given element.\n *\n * If a value is also provided for `thisArg` the created `_.matchesProperty`\n * style callback returns `true` for elements that have a matching property\n * value, else `false`.\n *\n * If an object is provided for `iteratee` the created `_.matches` style\n * callback returns `true` for elements that have the properties of the given\n * object, else `false`.\n *\n * Many lodash methods are guarded to work as iteratees for methods like\n * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.\n *\n * The guarded methods are:\n * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,\n * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,\n * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,\n * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,\n * `sum`, `uniq`, and `words`\n *\n * @static\n * @memberOf _\n * @alias collect\n * @category Collection\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n * per iteration.\n * @param {*} [thisArg] The `this` binding of `iteratee`.\n * @returns {Array} Returns the new mapped array.\n * @example\n *\n * function timesThree(n) {\n * return n * 3;\n * }\n *\n * _.map([1, 2], timesThree);\n * // => [3, 6]\n *\n * _.map({ 'a': 1, 'b': 2 }, timesThree);\n * // => [3, 6] (iteration order is not guaranteed)\n *\n * var users = [\n * { 'user': 'barney' },\n * { 'user': 'fred' }\n * ];\n *\n * // using the `_.property` callback shorthand\n * _.map(users, 'user');\n * // => ['barney', 'fred']\n */\nfunction map(collection, iteratee, thisArg) {\n var func = isArray(collection) ? arrayMap : baseMap;\n iteratee = baseCallback(iteratee, thisArg, 3);\n return func(collection, iteratee);\n}\n\nmodule.exports = map;\n","/**\n * lodash 3.0.1 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar keys = require('lodash.keys');\n\n/**\n * Converts `value` to an object if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Object} Returns the object.\n */\nfunction toObject(value) {\n return isObject(value) ? value : Object(value);\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Creates a two dimensional array of the key-value pairs for `object`,\n * e.g. `[[key1, value1], [key2, value2]]`.\n *\n * @static\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the new array of key-value pairs.\n * @example\n *\n * _.pairs({ 'barney': 36, 'fred': 40 });\n * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)\n */\nfunction pairs(object) {\n object = toObject(object);\n\n var index = -1,\n props = keys(object),\n length = props.length,\n result = Array(length);\n\n while (++index < length) {\n var key = props[index];\n result[index] = [key, object[key]];\n }\n return result;\n}\n\nmodule.exports = pairs;\n","/**\n * lodash 3.1.2 (Custom Build) <https://lodash.com/>\n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT license <https://lodash.com/license>\n */\nvar baseGet = require('lodash._baseget'),\n toPath = require('lodash._topath'),\n isArray = require('lodash.isarray'),\n map = require('lodash.map');\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/;\n\n/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n}\n\n/**\n * A specialized version of `baseProperty` which supports deep paths.\n *\n * @private\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction basePropertyDeep(path) {\n var pathKey = (path + '');\n path = toPath(path);\n return function(object) {\n return baseGet(object, path, pathKey);\n };\n}\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n var type = typeof value;\n if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {\n return true;\n }\n if (isArray(value)) {\n return false;\n }\n var result = !reIsDeepProp.test(value);\n return result || (object != null && value in toObject(object));\n}\n\n/**\n * Converts `value` to an object if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Object} Returns the object.\n */\nfunction toObject(value) {\n return isObject(value) ? value : Object(value);\n}\n\n/**\n * Gets the property value of `path` from all elements in `collection`.\n *\n * @static\n * @memberOf _\n * @category Collection\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Array|string} path The path of the property to pluck.\n * @returns {Array} Returns the property values.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 40 }\n * ];\n *\n * _.pluck(users, 'user');\n * // => ['barney', 'fred']\n *\n * var userIndex = _.indexBy(users, 'user');\n * _.pluck(userIndex, 'age');\n * // => [36, 40] (iteration order is not guaranteed)\n */\nfunction pluck(collection, path) {\n return map(collection, property(path));\n}\n\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n // Avoid a V8 JIT bug in Chrome 19-20.\n // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Creates a function which returns the property value at `path` on a\n * given object.\n *\n * @static\n * @memberOf _\n * @category Utility\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': { 'c': 2 } } },\n * { 'a': { 'b': { 'c': 1 } } }\n * ];\n *\n * _.map(objects, _.property('a.b.c'));\n * // => [2, 1]\n *\n * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');\n * // => [1, 2]\n */\nfunction property(path) {\n return isKey(path) ? baseProperty(path) : basePropertyDeep(path);\n}\n\nmodule.exports = pluck;\n","var support = require('webrtcsupport');\n\n\nfunction GainController(stream) {\n this.support = support.webAudio && support.mediaStream;\n\n // set our starting value\n this.gain = 1;\n\n if (this.support) {\n var context = this.context = new support.AudioContext();\n this.microphone = context.createMediaStreamSource(stream);\n this.gainFilter = context.createGain();\n this.destination = context.createMediaStreamDestination();\n this.outputStream = this.destination.stream;\n this.microphone.connect(this.gainFilter);\n this.gainFilter.connect(this.destination);\n stream.addTrack(this.outputStream.getAudioTracks()[0]);\n stream.removeTrack(stream.getAudioTracks()[0]);\n }\n this.stream = stream;\n}\n\n// setting\nGainController.prototype.setGain = function (val) {\n // check for support\n if (!this.support) return;\n this.gainFilter.gain.value = val;\n this.gain = val;\n};\n\nGainController.prototype.getGain = function () {\n return this.gain;\n};\n\nGainController.prototype.off = function () {\n return this.setGain(0);\n};\n\nGainController.prototype.on = function () {\n this.setGain(1);\n};\n\n\nmodule.exports = GainController;\n","var methods = \"assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn\".split(\",\");\nvar l = methods.length;\nvar fn = function () {};\nvar mockconsole = {};\n\nwhile (l--) {\n mockconsole[methods[l]] = fn;\n}\n\nmodule.exports = mockconsole;\n","var util = require('util');\nvar each = require('lodash.foreach');\nvar pluck = require('lodash.pluck');\nvar SJJ = require('sdp-jingle-json');\nvar WildEmitter = require('wildemitter');\nvar peerconn = require('traceablepeerconnection');\nvar adapter = require('webrtc-adapter-test');\n\nfunction PeerConnection(config, constraints) {\n var self = this;\n var item;\n WildEmitter.call(this);\n\n config = config || {};\n config.iceServers = config.iceServers || [];\n\n // make sure this only gets enabled in Google Chrome\n // EXPERIMENTAL FLAG, might get removed without notice\n this.enableChromeNativeSimulcast = false;\n if (constraints && constraints.optional &&\n adapter.webrtcDetectedBrowser === 'chrome' &&\n navigator.appVersion.match(/Chromium\\//) === null) {\n constraints.optional.forEach(function (constraint) {\n if (constraint.enableChromeNativeSimulcast) {\n self.enableChromeNativeSimulcast = true;\n }\n });\n }\n\n // EXPERIMENTAL FLAG, might get removed without notice\n this.enableMultiStreamHacks = false;\n if (constraints && constraints.optional &&\n adapter.webrtcDetectedBrowser === 'chrome') {\n constraints.optional.forEach(function (constraint) {\n if (constraint.enableMultiStreamHacks) {\n self.enableMultiStreamHacks = true;\n }\n });\n }\n // EXPERIMENTAL FLAG, might get removed without notice\n this.restrictBandwidth = 0;\n if (constraints && constraints.optional) {\n constraints.optional.forEach(function (constraint) {\n if (constraint.andyetRestrictBandwidth) {\n self.restrictBandwidth = constraint.andyetRestrictBandwidth;\n }\n });\n }\n\n // EXPERIMENTAL FLAG, might get removed without notice\n // bundle up ice candidates, only works for jingle mode\n // number > 0 is the delay to wait for additional candidates\n // ~20ms seems good\n this.batchIceCandidates = 0;\n if (constraints && constraints.optional) {\n constraints.optional.forEach(function (constraint) {\n if (constraint.andyetBatchIce) {\n self.batchIceCandidates = constraint.andyetBatchIce;\n }\n });\n }\n this.batchedIceCandidates = [];\n\n // EXPERIMENTAL FLAG, might get removed without notice\n // this attemps to strip out candidates with an already known foundation\n // and type -- i.e. those which are gathered via the same TURN server\n // but different transports (TURN udp, tcp and tls respectively)\n if (constraints && constraints.optional && adapter.webrtcDetectedBrowser === 'chrome') {\n constraints.optional.forEach(function (constraint) {\n if (constraint.andyetFasterICE) {\n self.eliminateDuplicateCandidates = constraint.andyetFasterICE;\n }\n });\n }\n // EXPERIMENTAL FLAG, might get removed without notice\n // when using a server such as the jitsi videobridge we don't need to signal\n // our candidates\n if (constraints && constraints.optional) {\n constraints.optional.forEach(function (constraint) {\n if (constraint.andyetDontSignalCandidates) {\n self.dontSignalCandidates = constraint.andyetDontSignalCandidates;\n }\n });\n }\n\n\n // EXPERIMENTAL FLAG, might get removed without notice\n this.assumeSetLocalSuccess = false;\n if (constraints && constraints.optional) {\n constraints.optional.forEach(function (constraint) {\n if (constraint.andyetAssumeSetLocalSuccess) {\n self.assumeSetLocalSuccess = constraint.andyetAssumeSetLocalSuccess;\n }\n });\n }\n\n // EXPERIMENTAL FLAG, might get removed without notice\n // working around https://bugzilla.mozilla.org/show_bug.cgi?id=1087551\n // pass in a timeout for this\n if (adapter.webrtcDetectedBrowser === 'firefox') {\n if (constraints && constraints.optional) {\n this.wtFirefox = 0;\n constraints.optional.forEach(function (constraint) {\n if (constraint.andyetFirefoxMakesMeSad) {\n self.wtFirefox = constraint.andyetFirefoxMakesMeSad;\n if (self.wtFirefox > 0) {\n self.firefoxcandidatebuffer = [];\n }\n }\n });\n }\n }\n\n\n this.pc = new peerconn(config, constraints);\n\n this.getLocalStreams = this.pc.getLocalStreams.bind(this.pc);\n this.getRemoteStreams = this.pc.getRemoteStreams.bind(this.pc);\n this.addStream = this.pc.addStream.bind(this.pc);\n this.removeStream = this.pc.removeStream.bind(this.pc);\n\n // proxy events\n this.pc.on('*', function () {\n self.emit.apply(self, arguments);\n });\n\n // proxy some events directly\n this.pc.onremovestream = this.emit.bind(this, 'removeStream');\n this.pc.onaddstream = this.emit.bind(this, 'addStream');\n this.pc.onnegotiationneeded = this.emit.bind(this, 'negotiationNeeded');\n this.pc.oniceconnectionstatechange = this.emit.bind(this, 'iceConnectionStateChange');\n this.pc.onsignalingstatechange = this.emit.bind(this, 'signalingStateChange');\n\n // handle ice candidate and data channel events\n this.pc.onicecandidate = this._onIce.bind(this);\n this.pc.ondatachannel = this._onDataChannel.bind(this);\n\n this.localDescription = {\n contents: []\n };\n this.remoteDescription = {\n contents: []\n };\n\n this.config = {\n debug: false,\n ice: {},\n sid: '',\n isInitiator: true,\n sdpSessionID: Date.now(),\n useJingle: false\n };\n\n // apply our config\n for (item in config) {\n this.config[item] = config[item];\n }\n\n if (this.config.debug) {\n this.on('*', function () {\n var logger = config.logger || console;\n logger.log('PeerConnection event:', arguments);\n });\n }\n this.hadLocalStunCandidate = false;\n this.hadRemoteStunCandidate = false;\n this.hadLocalRelayCandidate = false;\n this.hadRemoteRelayCandidate = false;\n\n this.hadLocalIPv6Candidate = false;\n this.hadRemoteIPv6Candidate = false;\n\n // keeping references for all our data channels\n // so they dont get garbage collected\n // can be removed once the following bugs have been fixed\n // https://crbug.com/405545\n // https://bugzilla.mozilla.org/show_bug.cgi?id=964092\n // to be filed for opera\n this._remoteDataChannels = [];\n this._localDataChannels = [];\n\n this._candidateBuffer = [];\n}\n\nutil.inherits(PeerConnection, WildEmitter);\n\nObject.defineProperty(PeerConnection.prototype, 'signalingState', {\n get: function () {\n return this.pc.signalingState;\n }\n});\nObject.defineProperty(PeerConnection.prototype, 'iceConnectionState', {\n get: function () {\n return this.pc.iceConnectionState;\n }\n});\n\nPeerConnection.prototype._role = function () {\n return this.isInitiator ? 'initiator' : 'responder';\n};\n\n// Add a stream to the peer connection object\nPeerConnection.prototype.addStream = function (stream) {\n this.localStream = stream;\n this.pc.addStream(stream);\n};\n\n// helper function to check if a remote candidate is a stun/relay\n// candidate or an ipv6 candidate\nPeerConnection.prototype._checkLocalCandidate = function (candidate) {\n var cand = SJJ.toCandidateJSON(candidate);\n if (cand.type == 'srflx') {\n this.hadLocalStunCandidate = true;\n } else if (cand.type == 'relay') {\n this.hadLocalRelayCandidate = true;\n }\n if (cand.ip.indexOf(':') != -1) {\n this.hadLocalIPv6Candidate = true;\n }\n};\n\n// helper function to check if a remote candidate is a stun/relay\n// candidate or an ipv6 candidate\nPeerConnection.prototype._checkRemoteCandidate = function (candidate) {\n var cand = SJJ.toCandidateJSON(candidate);\n if (cand.type == 'srflx') {\n this.hadRemoteStunCandidate = true;\n } else if (cand.type == 'relay') {\n this.hadRemoteRelayCandidate = true;\n }\n if (cand.ip.indexOf(':') != -1) {\n this.hadRemoteIPv6Candidate = true;\n }\n};\n\n\n// Init and add ice candidate object with correct constructor\nPeerConnection.prototype.processIce = function (update, cb) {\n cb = cb || function () {};\n var self = this;\n\n // ignore any added ice candidates to avoid errors. why does the\n // spec not do this?\n if (this.pc.signalingState === 'closed') return cb();\n\n if (update.contents || (update.jingle && update.jingle.contents)) {\n var contentNames = pluck(this.remoteDescription.contents, 'name');\n var contents = update.contents || update.jingle.contents;\n\n contents.forEach(function (content) {\n var transport = content.transport || {};\n var candidates = transport.candidates || [];\n var mline = contentNames.indexOf(content.name);\n var mid = content.name;\n\n candidates.forEach(\n function (candidate) {\n var iceCandidate = SJJ.toCandidateSDP(candidate) + '\\r\\n';\n self.pc.addIceCandidate(\n new RTCIceCandidate({\n candidate: iceCandidate,\n sdpMLineIndex: mline,\n sdpMid: mid\n }), function () {\n // well, this success callback is pretty meaningless\n },\n function (err) {\n self.emit('error', err);\n }\n );\n self._checkRemoteCandidate(iceCandidate);\n });\n });\n } else {\n // working around https://code.google.com/p/webrtc/issues/detail?id=3669\n if (update.candidate && update.candidate.candidate.indexOf('a=') !== 0) {\n update.candidate.candidate = 'a=' + update.candidate.candidate;\n }\n\n if (this.wtFirefox && this.firefoxcandidatebuffer !== null) {\n // we cant add this yet due to https://bugzilla.mozilla.org/show_bug.cgi?id=1087551\n if (this.pc.localDescription && this.pc.localDescription.type === 'offer') {\n this.firefoxcandidatebuffer.push(update.candidate);\n return cb();\n }\n }\n\n self.pc.addIceCandidate(\n new RTCIceCandidate(update.candidate),\n function () { },\n function (err) {\n self.emit('error', err);\n }\n );\n self._checkRemoteCandidate(update.candidate.candidate);\n }\n cb();\n};\n\n// Generate and emit an offer with the given constraints\nPeerConnection.prototype.offer = function (constraints, cb) {\n var self = this;\n var hasConstraints = arguments.length === 2;\n var mediaConstraints = hasConstraints && constraints ? constraints : {\n mandatory: {\n OfferToReceiveAudio: true,\n OfferToReceiveVideo: true\n }\n };\n cb = hasConstraints ? cb : constraints;\n cb = cb || function () {};\n\n if (this.pc.signalingState === 'closed') return cb('Already closed');\n\n // Actually generate the offer\n this.pc.createOffer(\n function (offer) {\n // does not work for jingle, but jingle.js doesn't need\n // this hack...\n var expandedOffer = {\n type: 'offer',\n sdp: offer.sdp\n };\n if (self.assumeSetLocalSuccess) {\n self.emit('offer', expandedOffer);\n cb(null, expandedOffer);\n }\n self._candidateBuffer = [];\n self.pc.setLocalDescription(offer,\n function () {\n var jingle;\n if (self.config.useJingle) {\n jingle = SJJ.toSessionJSON(offer.sdp, {\n role: self._role(),\n direction: 'outgoing'\n });\n jingle.sid = self.config.sid;\n self.localDescription = jingle;\n\n // Save ICE credentials\n each(jingle.contents, function (content) {\n var transport = content.transport || {};\n if (transport.ufrag) {\n self.config.ice[content.name] = {\n ufrag: transport.ufrag,\n pwd: transport.pwd\n };\n }\n });\n\n expandedOffer.jingle = jingle;\n }\n expandedOffer.sdp.split('\\r\\n').forEach(function (line) {\n if (line.indexOf('a=candidate:') === 0) {\n self._checkLocalCandidate(line);\n }\n });\n\n if (!self.assumeSetLocalSuccess) {\n self.emit('offer', expandedOffer);\n cb(null, expandedOffer);\n }\n },\n function (err) {\n self.emit('error', err);\n cb(err);\n }\n );\n },\n function (err) {\n self.emit('error', err);\n cb(err);\n },\n mediaConstraints\n );\n};\n\n\n// Process an incoming offer so that ICE may proceed before deciding\n// to answer the request.\nPeerConnection.prototype.handleOffer = function (offer, cb) {\n cb = cb || function () {};\n var self = this;\n offer.type = 'offer';\n if (offer.jingle) {\n if (this.enableChromeNativeSimulcast) {\n offer.jingle.contents.forEach(function (content) {\n if (content.name === 'video') {\n content.description.googConferenceFlag = true;\n }\n });\n }\n if (this.enableMultiStreamHacks) {\n // add a mixed video stream as first stream\n offer.jingle.contents.forEach(function (content) {\n if (content.name === 'video') {\n var sources = content.description.sources || [];\n if (sources.length === 0 || sources[0].ssrc !== \"3735928559\") {\n sources.unshift({\n ssrc: \"3735928559\", // 0xdeadbeef\n parameters: [\n {\n key: \"cname\",\n value: \"deadbeef\"\n },\n {\n key: \"msid\",\n value: \"mixyourfecintothis please\"\n }\n ]\n });\n content.description.sources = sources;\n }\n }\n });\n }\n if (self.restrictBandwidth > 0) {\n if (offer.jingle.contents.length >= 2 && offer.jingle.contents[1].name === 'video') {\n var content = offer.jingle.contents[1];\n var hasBw = content.description && content.description.bandwidth;\n if (!hasBw) {\n offer.jingle.contents[1].description.bandwidth = { type: 'AS', bandwidth: self.restrictBandwidth.toString() };\n offer.sdp = SJJ.toSessionSDP(offer.jingle, {\n sid: self.config.sdpSessionID,\n role: self._role(),\n direction: 'outgoing'\n });\n }\n }\n }\n offer.sdp = SJJ.toSessionSDP(offer.jingle, {\n sid: self.config.sdpSessionID,\n role: self._role(),\n direction: 'incoming'\n });\n self.remoteDescription = offer.jingle;\n }\n offer.sdp.split('\\r\\n').forEach(function (line) {\n if (line.indexOf('a=candidate:') === 0) {\n self._checkRemoteCandidate(line);\n }\n });\n self.pc.setRemoteDescription(new RTCSessionDescription(offer),\n function () {\n cb();\n },\n cb\n );\n};\n\n// Answer an offer with audio only\nPeerConnection.prototype.answerAudioOnly = function (cb) {\n var mediaConstraints = {\n mandatory: {\n OfferToReceiveAudio: true,\n OfferToReceiveVideo: false\n }\n };\n this._answer(mediaConstraints, cb);\n};\n\n// Answer an offer without offering to recieve\nPeerConnection.prototype.answerBroadcastOnly = function (cb) {\n var mediaConstraints = {\n mandatory: {\n OfferToReceiveAudio: false,\n OfferToReceiveVideo: false\n }\n };\n this._answer(mediaConstraints, cb);\n};\n\n// Answer an offer with given constraints default is audio/video\nPeerConnection.prototype.answer = function (constraints, cb) {\n var hasConstraints = arguments.length === 2;\n var callback = hasConstraints ? cb : constraints;\n var mediaConstraints = hasConstraints && constraints ? constraints : {\n mandatory: {\n OfferToReceiveAudio: true,\n OfferToReceiveVideo: true\n }\n };\n\n this._answer(mediaConstraints, callback);\n};\n\n// Process an answer\nPeerConnection.prototype.handleAnswer = function (answer, cb) {\n cb = cb || function () {};\n var self = this;\n if (answer.jingle) {\n answer.sdp = SJJ.toSessionSDP(answer.jingle, {\n sid: self.config.sdpSessionID,\n role: self._role(),\n direction: 'incoming'\n });\n self.remoteDescription = answer.jingle;\n }\n answer.sdp.split('\\r\\n').forEach(function (line) {\n if (line.indexOf('a=candidate:') === 0) {\n self._checkRemoteCandidate(line);\n }\n });\n self.pc.setRemoteDescription(\n new RTCSessionDescription(answer),\n function () {\n if (self.wtFirefox) {\n window.setTimeout(function () {\n self.firefoxcandidatebuffer.forEach(function (candidate) {\n // add candidates later\n self.pc.addIceCandidate(\n new RTCIceCandidate(candidate),\n function () { },\n function (err) {\n self.emit('error', err);\n }\n );\n self._checkRemoteCandidate(candidate.candidate);\n });\n self.firefoxcandidatebuffer = null;\n }, self.wtFirefox);\n }\n cb(null);\n },\n cb\n );\n};\n\n// Close the peer connection\nPeerConnection.prototype.close = function () {\n this.pc.close();\n\n this._localDataChannels = [];\n this._remoteDataChannels = [];\n\n this.emit('close');\n};\n\n// Internal code sharing for various types of answer methods\nPeerConnection.prototype._answer = function (constraints, cb) {\n cb = cb || function () {};\n var self = this;\n if (!this.pc.remoteDescription) {\n // the old API is used, call handleOffer\n throw new Error('remoteDescription not set');\n }\n\n if (this.pc.signalingState === 'closed') return cb('Already closed');\n\n self.pc.createAnswer(\n function (answer) {\n var sim = [];\n if (self.enableChromeNativeSimulcast) {\n // native simulcast part 1: add another SSRC\n answer.jingle = SJJ.toSessionJSON(answer.sdp, {\n role: self._role(),\n direction: 'outgoing'\n });\n if (answer.jingle.contents.length >= 2 && answer.jingle.contents[1].name === 'video') {\n var groups = answer.jingle.contents[1].description.sourceGroups || [];\n var hasSim = false;\n groups.forEach(function (group) {\n if (group.semantics == 'SIM') hasSim = true;\n });\n if (!hasSim &&\n answer.jingle.contents[1].description.sources.length) {\n var newssrc = JSON.parse(JSON.stringify(answer.jingle.contents[1].description.sources[0]));\n newssrc.ssrc = '' + Math.floor(Math.random() * 0xffffffff); // FIXME: look for conflicts\n answer.jingle.contents[1].description.sources.push(newssrc);\n\n sim.push(answer.jingle.contents[1].description.sources[0].ssrc);\n sim.push(newssrc.ssrc);\n groups.push({\n semantics: 'SIM',\n sources: sim\n });\n\n // also create an RTX one for the SIM one\n var rtxssrc = JSON.parse(JSON.stringify(newssrc));\n rtxssrc.ssrc = '' + Math.floor(Math.random() * 0xffffffff); // FIXME: look for conflicts\n answer.jingle.contents[1].description.sources.push(rtxssrc);\n groups.push({\n semantics: 'FID',\n sources: [newssrc.ssrc, rtxssrc.ssrc]\n });\n\n answer.jingle.contents[1].description.sourceGroups = groups;\n answer.sdp = SJJ.toSessionSDP(answer.jingle, {\n sid: self.config.sdpSessionID,\n role: self._role(),\n direction: 'outgoing'\n });\n }\n }\n }\n var expandedAnswer = {\n type: 'answer',\n sdp: answer.sdp\n };\n if (self.assumeSetLocalSuccess) {\n // not safe to do when doing simulcast mangling\n self.emit('answer', expandedAnswer);\n cb(null, expandedAnswer);\n }\n self._candidateBuffer = [];\n self.pc.setLocalDescription(answer,\n function () {\n if (self.config.useJingle) {\n var jingle = SJJ.toSessionJSON(answer.sdp, {\n role: self._role(),\n direction: 'outgoing'\n });\n jingle.sid = self.config.sid;\n self.localDescription = jingle;\n expandedAnswer.jingle = jingle;\n }\n if (self.enableChromeNativeSimulcast) {\n // native simulcast part 2:\n // signal multiple tracks to the receiver\n // for anything in the SIM group\n if (!expandedAnswer.jingle) {\n expandedAnswer.jingle = SJJ.toSessionJSON(answer.sdp, {\n role: self._role(),\n direction: 'outgoing'\n });\n }\n expandedAnswer.jingle.contents[1].description.sources.forEach(function (source, idx) {\n // the floor idx/2 is a hack that relies on a particular order\n // of groups, alternating between sim and rtx\n source.parameters = source.parameters.map(function (parameter) {\n if (parameter.key === 'msid') {\n parameter.value += '-' + Math.floor(idx / 2);\n }\n return parameter;\n });\n });\n expandedAnswer.sdp = SJJ.toSessionSDP(expandedAnswer.jingle, {\n sid: self.sdpSessionID,\n role: self._role(),\n direction: 'outgoing'\n });\n }\n expandedAnswer.sdp.split('\\r\\n').forEach(function (line) {\n if (line.indexOf('a=candidate:') === 0) {\n self._checkLocalCandidate(line);\n }\n });\n if (!self.assumeSetLocalSuccess) {\n self.emit('answer', expandedAnswer);\n cb(null, expandedAnswer);\n }\n },\n function (err) {\n self.emit('error', err);\n cb(err);\n }\n );\n },\n function (err) {\n self.emit('error', err);\n cb(err);\n },\n constraints\n );\n};\n\n// Internal method for emitting ice candidates on our peer object\nPeerConnection.prototype._onIce = function (event) {\n var self = this;\n if (event.candidate) {\n if (this.dontSignalCandidates) return;\n var ice = event.candidate;\n\n var expandedCandidate = {\n candidate: {\n candidate: ice.candidate,\n sdpMid: ice.sdpMid,\n sdpMLineIndex: ice.sdpMLineIndex\n }\n };\n this._checkLocalCandidate(ice.candidate);\n\n var cand = SJJ.toCandidateJSON(ice.candidate);\n\n var already;\n var idx;\n if (this.eliminateDuplicateCandidates && cand.type === 'relay') {\n // drop candidates with same foundation, component\n // take local type pref into account so we don't ignore udp\n // ones when we know about a TCP one. unlikely but...\n already = this._candidateBuffer.filter(\n function (c) {\n return c.type === 'relay';\n }).map(function (c) {\n return c.foundation + ':' + c.component;\n }\n );\n idx = already.indexOf(cand.foundation + ':' + cand.component);\n // remember: local type pref of udp is 0, tcp 1, tls 2\n if (idx > -1 && ((cand.priority >> 24) >= (already[idx].priority >> 24))) {\n // drop it, same foundation with higher (worse) type pref\n return;\n }\n }\n if (this.config.bundlePolicy === 'max-bundle') {\n // drop candidates which are duplicate for audio/video/data\n // duplicate means same host/port but different sdpMid\n already = this._candidateBuffer.filter(\n function (c) {\n return cand.type === c.type;\n }).map(function (cand) {\n return cand.address + ':' + cand.port;\n }\n );\n idx = already.indexOf(cand.address + ':' + cand.port);\n if (idx > -1) return;\n }\n // also drop rtcp candidates since we know the peer supports RTCP-MUX\n // this is a workaround until browsers implement this natively\n if (this.config.rtcpMuxPolicy === 'require' && cand.component === '2') {\n return;\n }\n this._candidateBuffer.push(cand);\n\n if (self.config.useJingle) {\n if (!ice.sdpMid) { // firefox doesn't set this\n if (self.pc.remoteDescription && self.pc.remoteDescription.type === 'offer') {\n // preserve name from remote\n ice.sdpMid = self.remoteDescription.contents[ice.sdpMLineIndex].name;\n } else {\n ice.sdpMid = self.localDescription.contents[ice.sdpMLineIndex].name;\n }\n }\n if (!self.config.ice[ice.sdpMid]) {\n var jingle = SJJ.toSessionJSON(self.pc.localDescription.sdp, {\n role: self._role(),\n direction: 'outgoing'\n });\n each(jingle.contents, function (content) {\n var transport = content.transport || {};\n if (transport.ufrag) {\n self.config.ice[content.name] = {\n ufrag: transport.ufrag,\n pwd: transport.pwd\n };\n }\n });\n }\n expandedCandidate.jingle = {\n contents: [{\n name: ice.sdpMid,\n creator: self._role(),\n transport: {\n transType: 'iceUdp',\n ufrag: self.config.ice[ice.sdpMid].ufrag,\n pwd: self.config.ice[ice.sdpMid].pwd,\n candidates: [\n cand\n ]\n }\n }]\n };\n if (self.batchIceCandidates > 0) {\n if (self.batchedIceCandidates.length === 0) {\n window.setTimeout(function () {\n var contents = {};\n self.batchedIceCandidates.forEach(function (content) {\n content = content.contents[0];\n if (!contents[content.name]) contents[content.name] = content;\n contents[content.name].transport.candidates.push(content.transport.candidates[0]);\n });\n var newCand = {\n jingle: {\n contents: []\n }\n };\n Object.keys(contents).forEach(function (name) {\n newCand.jingle.contents.push(contents[name]);\n });\n self.batchedIceCandidates = [];\n self.emit('ice', newCand);\n }, self.batchIceCandidates);\n }\n self.batchedIceCandidates.push(expandedCandidate.jingle);\n return;\n }\n\n }\n this.emit('ice', expandedCandidate);\n } else {\n this.emit('endOfCandidates');\n }\n};\n\n// Internal method for processing a new data channel being added by the\n// other peer.\nPeerConnection.prototype._onDataChannel = function (event) {\n // make sure we keep a reference so this doesn't get garbage collected\n var channel = event.channel;\n this._remoteDataChannels.push(channel);\n\n this.emit('addChannel', channel);\n};\n\n// Create a data channel spec reference:\n// http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCDataChannelInit\nPeerConnection.prototype.createDataChannel = function (name, opts) {\n var channel = this.pc.createDataChannel(name, opts);\n\n // make sure we keep a reference so this doesn't get garbage collected\n this._localDataChannels.push(channel);\n\n return channel;\n};\n\n// a wrapper around getStats which hides the differences (where possible)\n// TODO: remove in favor of adapter.js shim\nPeerConnection.prototype.getStats = function (cb) {\n if (adapter.webrtcDetectedBrowser === 'firefox') {\n this.pc.getStats(\n function (res) {\n var items = [];\n for (var result in res) {\n if (typeof res[result] === 'object') {\n items.push(res[result]);\n }\n }\n cb(null, items);\n },\n cb\n );\n } else {\n this.pc.getStats(function (res) {\n var items = [];\n res.result().forEach(function (result) {\n var item = {};\n result.names().forEach(function (name) {\n item[name] = result.stat(name);\n });\n item.id = result.id;\n item.type = result.type;\n item.timestamp = result.timestamp;\n items.push(item);\n });\n cb(null, items);\n });\n }\n};\n\nmodule.exports = PeerConnection;\n","var toSDP = require('./lib/tosdp');\nvar toJSON = require('./lib/tojson');\n\n\n// Converstion from JSON to SDP\n\nexports.toIncomingSDPOffer = function (session) {\n return toSDP.toSessionSDP(session, {\n role: 'responder',\n direction: 'incoming'\n });\n};\nexports.toOutgoingSDPOffer = function (session) {\n return toSDP.toSessionSDP(session, {\n role: 'initiator',\n direction: 'outgoing'\n });\n};\nexports.toIncomingSDPAnswer = function (session) {\n return toSDP.toSessionSDP(session, {\n role: 'initiator',\n direction: 'incoming'\n });\n};\nexports.toOutgoingSDPAnswer = function (session) {\n return toSDP.toSessionSDP(session, {\n role: 'responder',\n direction: 'outgoing'\n });\n};\nexports.toIncomingMediaSDPOffer = function (media) {\n return toSDP.toMediaSDP(media, {\n role: 'responder',\n direction: 'incoming'\n });\n};\nexports.toOutgoingMediaSDPOffer = function (media) {\n return toSDP.toMediaSDP(media, {\n role: 'initiator',\n direction: 'outgoing'\n });\n};\nexports.toIncomingMediaSDPAnswer = function (media) {\n return toSDP.toMediaSDP(media, {\n role: 'initiator',\n direction: 'incoming'\n });\n};\nexports.toOutgoingMediaSDPAnswer = function (media) {\n return toSDP.toMediaSDP(media, {\n role: 'responder',\n direction: 'outgoing'\n });\n};\nexports.toCandidateSDP = toSDP.toCandidateSDP;\nexports.toMediaSDP = toSDP.toMediaSDP;\nexports.toSessionSDP = toSDP.toSessionSDP;\n\n\n// Conversion from SDP to JSON\n\nexports.toIncomingJSONOffer = function (sdp, creators) {\n return toJSON.toSessionJSON(sdp, {\n role: 'responder',\n direction: 'incoming',\n creators: creators\n });\n};\nexports.toOutgoingJSONOffer = function (sdp, creators) {\n return toJSON.toSessionJSON(sdp, {\n role: 'initiator',\n direction: 'outgoing',\n creators: creators\n });\n};\nexports.toIncomingJSONAnswer = function (sdp, creators) {\n return toJSON.toSessionJSON(sdp, {\n role: 'initiator',\n direction: 'incoming',\n creators: creators\n });\n};\nexports.toOutgoingJSONAnswer = function (sdp, creators) {\n return toJSON.toSessionJSON(sdp, {\n role: 'responder',\n direction: 'outgoing',\n creators: creators\n });\n};\nexports.toIncomingMediaJSONOffer = function (sdp, creator) {\n return toJSON.toMediaJSON(sdp, {\n role: 'responder',\n direction: 'incoming',\n creator: creator\n });\n};\nexports.toOutgoingMediaJSONOffer = function (sdp, creator) {\n return toJSON.toMediaJSON(sdp, {\n role: 'initiator',\n direction: 'outgoing',\n creator: creator\n });\n};\nexports.toIncomingMediaJSONAnswer = function (sdp, creator) {\n return toJSON.toMediaJSON(sdp, {\n role: 'initiator',\n direction: 'incoming',\n creator: creator\n });\n};\nexports.toOutgoingMediaJSONAnswer = function (sdp, creator) {\n return toJSON.toMediaJSON(sdp, {\n role: 'responder',\n direction: 'outgoing',\n creator: creator\n });\n};\nexports.toCandidateJSON = toJSON.toCandidateJSON;\nexports.toMediaJSON = toJSON.toMediaJSON;\nexports.toSessionJSON = toJSON.toSessionJSON;\n","exports.lines = function (sdp) {\n return sdp.split('\\r\\n').filter(function (line) {\n return line.length > 0;\n });\n};\n\nexports.findLine = function (prefix, mediaLines, sessionLines) {\n var prefixLength = prefix.length;\n for (var i = 0; i < mediaLines.length; i++) {\n if (mediaLines[i].substr(0, prefixLength) === prefix) {\n return mediaLines[i];\n }\n }\n // Continue searching in parent session section\n if (!sessionLines) {\n return false;\n }\n\n for (var j = 0; j < sessionLines.length; j++) {\n if (sessionLines[j].substr(0, prefixLength) === prefix) {\n return sessionLines[j];\n }\n }\n\n return false;\n};\n\nexports.findLines = function (prefix, mediaLines, sessionLines) {\n var results = [];\n var prefixLength = prefix.length;\n for (var i = 0; i < mediaLines.length; i++) {\n if (mediaLines[i].substr(0, prefixLength) === prefix) {\n results.push(mediaLines[i]);\n }\n }\n if (results.length || !sessionLines) {\n return results;\n }\n for (var j = 0; j < sessionLines.length; j++) {\n if (sessionLines[j].substr(0, prefixLength) === prefix) {\n results.push(sessionLines[j]);\n }\n }\n return results;\n};\n\nexports.mline = function (line) {\n var parts = line.substr(2).split(' ');\n var parsed = {\n media: parts[0],\n port: parts[1],\n proto: parts[2],\n formats: []\n };\n for (var i = 3; i < parts.length; i++) {\n if (parts[i]) {\n parsed.formats.push(parts[i]);\n }\n }\n return parsed;\n};\n\nexports.rtpmap = function (line) {\n var parts = line.substr(9).split(' ');\n var parsed = {\n id: parts.shift()\n };\n\n parts = parts[0].split('/');\n\n parsed.name = parts[0];\n parsed.clockrate = parts[1];\n parsed.channels = parts.length == 3 ? parts[2] : '1';\n return parsed;\n};\n\nexports.sctpmap = function (line) {\n // based on -05 draft\n var parts = line.substr(10).split(' ');\n var parsed = {\n number: parts.shift(),\n protocol: parts.shift(),\n streams: parts.shift()\n };\n return parsed;\n};\n\n\nexports.fmtp = function (line) {\n var kv, key, value;\n var parts = line.substr(line.indexOf(' ') + 1).split(';');\n var parsed = [];\n for (var i = 0; i < parts.length; i++) {\n kv = parts[i].split('=');\n key = kv[0].trim();\n value = kv[1];\n if (key && value) {\n parsed.push({key: key, value: value});\n } else if (key) {\n parsed.push({key: '', value: key});\n }\n }\n return parsed;\n};\n\nexports.crypto = function (line) {\n var parts = line.substr(9).split(' ');\n var parsed = {\n tag: parts[0],\n cipherSuite: parts[1],\n keyParams: parts[2],\n sessionParams: parts.slice(3).join(' ')\n };\n return parsed;\n};\n\nexports.fingerprint = function (line) {\n var parts = line.substr(14).split(' ');\n return {\n hash: parts[0],\n value: parts[1]\n };\n};\n\nexports.extmap = function (line) {\n var parts = line.substr(9).split(' ');\n var parsed = {};\n\n var idpart = parts.shift();\n var sp = idpart.indexOf('/');\n if (sp >= 0) {\n parsed.id = idpart.substr(0, sp);\n parsed.senders = idpart.substr(sp + 1);\n } else {\n parsed.id = idpart;\n parsed.senders = 'sendrecv';\n }\n\n parsed.uri = parts.shift() || '';\n\n return parsed;\n};\n\nexports.rtcpfb = function (line) {\n var parts = line.substr(10).split(' ');\n var parsed = {};\n parsed.id = parts.shift();\n parsed.type = parts.shift();\n if (parsed.type === 'trr-int') {\n parsed.value = parts.shift();\n } else {\n parsed.subtype = parts.shift() || '';\n }\n parsed.parameters = parts;\n return parsed;\n};\n\nexports.candidate = function (line) {\n var parts;\n if (line.indexOf('a=candidate:') === 0) {\n parts = line.substring(12).split(' ');\n } else { // no a=candidate\n parts = line.substring(10).split(' ');\n }\n\n var candidate = {\n foundation: parts[0],\n component: parts[1],\n protocol: parts[2].toLowerCase(),\n priority: parts[3],\n ip: parts[4],\n port: parts[5],\n // skip parts[6] == 'typ'\n type: parts[7],\n generation: '0'\n };\n\n for (var i = 8; i < parts.length; i += 2) {\n if (parts[i] === 'raddr') {\n candidate.relAddr = parts[i + 1];\n } else if (parts[i] === 'rport') {\n candidate.relPort = parts[i + 1];\n } else if (parts[i] === 'generation') {\n candidate.generation = parts[i + 1];\n } else if (parts[i] === 'tcptype') {\n candidate.tcpType = parts[i + 1];\n }\n }\n\n candidate.network = '1';\n\n return candidate;\n};\n\nexports.sourceGroups = function (lines) {\n var parsed = [];\n for (var i = 0; i < lines.length; i++) {\n var parts = lines[i].substr(13).split(' ');\n parsed.push({\n semantics: parts.shift(),\n sources: parts\n });\n }\n return parsed;\n};\n\nexports.sources = function (lines) {\n // http://tools.ietf.org/html/rfc5576\n var parsed = [];\n var sources = {};\n for (var i = 0; i < lines.length; i++) {\n var parts = lines[i].substr(7).split(' ');\n var ssrc = parts.shift();\n\n if (!sources[ssrc]) {\n var source = {\n ssrc: ssrc,\n parameters: []\n };\n parsed.push(source);\n\n // Keep an index\n sources[ssrc] = source;\n }\n\n parts = parts.join(' ').split(':');\n var attribute = parts.shift();\n var value = parts.join(':') || null;\n\n sources[ssrc].parameters.push({\n key: attribute,\n value: value\n });\n }\n\n return parsed;\n};\n\nexports.groups = function (lines) {\n // http://tools.ietf.org/html/rfc5888\n var parsed = [];\n var parts;\n for (var i = 0; i < lines.length; i++) {\n parts = lines[i].substr(8).split(' ');\n parsed.push({\n semantics: parts.shift(),\n contents: parts\n });\n }\n return parsed;\n};\n\nexports.bandwidth = function (line) {\n var parts = line.substr(2).split(':');\n var parsed = {};\n parsed.type = parts.shift();\n parsed.bandwidth = parts.shift();\n return parsed;\n};\n\nexports.msid = function (line) {\n var data = line.substr(7);\n var parts = data.split(' ');\n return {\n msid: data,\n mslabel: parts[0],\n label: parts[1]\n };\n};\n","module.exports = {\n initiator: {\n incoming: {\n initiator: 'recvonly',\n responder: 'sendonly',\n both: 'sendrecv',\n none: 'inactive',\n recvonly: 'initiator',\n sendonly: 'responder',\n sendrecv: 'both',\n inactive: 'none'\n },\n outgoing: {\n initiator: 'sendonly',\n responder: 'recvonly',\n both: 'sendrecv',\n none: 'inactive',\n recvonly: 'responder',\n sendonly: 'initiator',\n sendrecv: 'both',\n inactive: 'none'\n }\n },\n responder: {\n incoming: {\n initiator: 'sendonly',\n responder: 'recvonly',\n both: 'sendrecv',\n none: 'inactive',\n recvonly: 'responder',\n sendonly: 'initiator',\n sendrecv: 'both',\n inactive: 'none'\n },\n outgoing: {\n initiator: 'recvonly',\n responder: 'sendonly',\n both: 'sendrecv',\n none: 'inactive',\n recvonly: 'initiator',\n sendonly: 'responder',\n sendrecv: 'both',\n inactive: 'none'\n }\n }\n};\n","var SENDERS = require('./senders');\nvar parsers = require('./parsers');\nvar idCounter = Math.random();\n\n\nexports._setIdCounter = function (counter) {\n idCounter = counter;\n};\n\nexports.toSessionJSON = function (sdp, opts) {\n var i;\n var creators = opts.creators || [];\n var role = opts.role || 'initiator';\n var direction = opts.direction || 'outgoing';\n\n\n // Divide the SDP into session and media sections.\n var media = sdp.split('\\r\\nm=');\n for (i = 1; i < media.length; i++) {\n media[i] = 'm=' + media[i];\n if (i !== media.length - 1) {\n media[i] += '\\r\\n';\n }\n }\n var session = media.shift() + '\\r\\n';\n var sessionLines = parsers.lines(session);\n var parsed = {};\n\n var contents = [];\n for (i = 0; i < media.length; i++) {\n contents.push(exports.toMediaJSON(media[i], session, {\n role: role,\n direction: direction,\n creator: creators[i] || 'initiator'\n }));\n }\n parsed.contents = contents;\n\n var groupLines = parsers.findLines('a=group:', sessionLines);\n if (groupLines.length) {\n parsed.groups = parsers.groups(groupLines);\n }\n\n return parsed;\n};\n\nexports.toMediaJSON = function (media, session, opts) {\n var creator = opts.creator || 'initiator';\n var role = opts.role || 'initiator';\n var direction = opts.direction || 'outgoing';\n\n var lines = parsers.lines(media);\n var sessionLines = parsers.lines(session);\n var mline = parsers.mline(lines[0]);\n\n var content = {\n creator: creator,\n name: mline.media,\n description: {\n descType: 'rtp',\n media: mline.media,\n payloads: [],\n encryption: [],\n feedback: [],\n headerExtensions: []\n },\n transport: {\n transType: 'iceUdp',\n candidates: [],\n fingerprints: []\n }\n };\n if (mline.media == 'application') {\n // FIXME: the description is most likely to be independent\n // of the SDP and should be processed by other parts of the library\n content.description = {\n descType: 'datachannel'\n };\n content.transport.sctp = [];\n }\n var desc = content.description;\n var trans = content.transport;\n\n // If we have a mid, use that for the content name instead.\n var mid = parsers.findLine('a=mid:', lines);\n if (mid) {\n content.name = mid.substr(6);\n }\n\n if (parsers.findLine('a=sendrecv', lines, sessionLines)) {\n content.senders = 'both';\n } else if (parsers.findLine('a=sendonly', lines, sessionLines)) {\n content.senders = SENDERS[role][direction].sendonly;\n } else if (parsers.findLine('a=recvonly', lines, sessionLines)) {\n content.senders = SENDERS[role][direction].recvonly;\n } else if (parsers.findLine('a=inactive', lines, sessionLines)) {\n content.senders = 'none';\n }\n\n if (desc.descType == 'rtp') {\n var bandwidth = parsers.findLine('b=', lines);\n if (bandwidth) {\n desc.bandwidth = parsers.bandwidth(bandwidth);\n }\n\n var ssrc = parsers.findLine('a=ssrc:', lines);\n if (ssrc) {\n desc.ssrc = ssrc.substr(7).split(' ')[0];\n }\n\n var rtpmapLines = parsers.findLines('a=rtpmap:', lines);\n rtpmapLines.forEach(function (line) {\n var payload = parsers.rtpmap(line);\n payload.parameters = [];\n payload.feedback = [];\n\n var fmtpLines = parsers.findLines('a=fmtp:' + payload.id, lines);\n // There should only be one fmtp line per payload\n fmtpLines.forEach(function (line) {\n payload.parameters = parsers.fmtp(line);\n });\n\n var fbLines = parsers.findLines('a=rtcp-fb:' + payload.id, lines);\n fbLines.forEach(function (line) {\n payload.feedback.push(parsers.rtcpfb(line));\n });\n\n desc.payloads.push(payload);\n });\n\n var cryptoLines = parsers.findLines('a=crypto:', lines, sessionLines);\n cryptoLines.forEach(function (line) {\n desc.encryption.push(parsers.crypto(line));\n });\n\n if (parsers.findLine('a=rtcp-mux', lines)) {\n desc.mux = true;\n }\n\n var fbLines = parsers.findLines('a=rtcp-fb:*', lines);\n fbLines.forEach(function (line) {\n desc.feedback.push(parsers.rtcpfb(line));\n });\n\n var extLines = parsers.findLines('a=extmap:', lines);\n extLines.forEach(function (line) {\n var ext = parsers.extmap(line);\n\n ext.senders = SENDERS[role][direction][ext.senders];\n\n desc.headerExtensions.push(ext);\n });\n\n var ssrcGroupLines = parsers.findLines('a=ssrc-group:', lines);\n desc.sourceGroups = parsers.sourceGroups(ssrcGroupLines || []);\n\n var ssrcLines = parsers.findLines('a=ssrc:', lines);\n var sources = desc.sources = parsers.sources(ssrcLines || []);\n\n var msidLine = parsers.findLine('a=msid:', lines);\n if (msidLine) {\n var msid = parsers.msid(msidLine);\n ['msid', 'mslabel', 'label'].forEach(function (key) {\n for (var i = 0; i < sources.length; i++) {\n var found = false;\n for (var j = 0; j < sources[i].parameters.length; j++) {\n if (sources[i].parameters[j].key === key) {\n found = true;\n }\n }\n if (!found) {\n sources[i].parameters.push({ key: key, value: msid[key] });\n }\n }\n });\n }\n\n if (parsers.findLine('a=x-google-flag:conference', lines, sessionLines)) {\n desc.googConferenceFlag = true;\n }\n }\n\n // transport specific attributes\n var fingerprintLines = parsers.findLines('a=fingerprint:', lines, sessionLines);\n var setup = parsers.findLine('a=setup:', lines, sessionLines);\n fingerprintLines.forEach(function (line) {\n var fp = parsers.fingerprint(line);\n if (setup) {\n fp.setup = setup.substr(8);\n }\n trans.fingerprints.push(fp);\n });\n\n var ufragLine = parsers.findLine('a=ice-ufrag:', lines, sessionLines);\n var pwdLine = parsers.findLine('a=ice-pwd:', lines, sessionLines);\n if (ufragLine && pwdLine) {\n trans.ufrag = ufragLine.substr(12);\n trans.pwd = pwdLine.substr(10);\n trans.candidates = [];\n\n var candidateLines = parsers.findLines('a=candidate:', lines, sessionLines);\n candidateLines.forEach(function (line) {\n trans.candidates.push(exports.toCandidateJSON(line));\n });\n }\n\n if (desc.descType == 'datachannel') {\n var sctpmapLines = parsers.findLines('a=sctpmap:', lines);\n sctpmapLines.forEach(function (line) {\n var sctp = parsers.sctpmap(line);\n trans.sctp.push(sctp);\n });\n }\n\n return content;\n};\n\nexports.toCandidateJSON = function (line) {\n var candidate = parsers.candidate(line.split('\\r\\n')[0]);\n candidate.id = (idCounter++).toString(36).substr(0, 12);\n return candidate;\n};\n","var SENDERS = require('./senders');\n\n\nexports.toSessionSDP = function (session, opts) {\n var role = opts.role || 'initiator';\n var direction = opts.direction || 'outgoing';\n var sid = opts.sid || session.sid || Date.now();\n var time = opts.time || Date.now();\n\n var sdp = [\n 'v=0',\n 'o=- ' + sid + ' ' + time + ' IN IP4 0.0.0.0',\n 's=-',\n 't=0 0',\n 'a=msid-semantic: WMS *'\n ];\n\n var groups = session.groups || [];\n groups.forEach(function (group) {\n sdp.push('a=group:' + group.semantics + ' ' + group.contents.join(' '));\n });\n\n var contents = session.contents || [];\n contents.forEach(function (content) {\n sdp.push(exports.toMediaSDP(content, opts));\n });\n\n return sdp.join('\\r\\n') + '\\r\\n';\n};\n\nexports.toMediaSDP = function (content, opts) {\n var sdp = [];\n\n var role = opts.role || 'initiator';\n var direction = opts.direction || 'outgoing';\n\n var desc = content.description;\n var transport = content.transport;\n var payloads = desc.payloads || [];\n var fingerprints = (transport && transport.fingerprints) || [];\n\n var mline = [];\n if (desc.descType == 'datachannel') {\n mline.push('application');\n mline.push('1');\n mline.push('DTLS/SCTP');\n if (transport.sctp) {\n transport.sctp.forEach(function (map) {\n mline.push(map.number);\n });\n }\n } else {\n mline.push(desc.media);\n mline.push('1');\n if ((desc.encryption && desc.encryption.length > 0) || (fingerprints.length > 0)) {\n mline.push('RTP/SAVPF');\n } else {\n mline.push('RTP/AVPF');\n }\n payloads.forEach(function (payload) {\n mline.push(payload.id);\n });\n }\n\n\n sdp.push('m=' + mline.join(' '));\n\n sdp.push('c=IN IP4 0.0.0.0');\n if (desc.bandwidth && desc.bandwidth.type && desc.bandwidth.bandwidth) {\n sdp.push('b=' + desc.bandwidth.type + ':' + desc.bandwidth.bandwidth);\n }\n if (desc.descType == 'rtp') {\n sdp.push('a=rtcp:1 IN IP4 0.0.0.0');\n }\n\n if (transport) {\n if (transport.ufrag) {\n sdp.push('a=ice-ufrag:' + transport.ufrag);\n }\n if (transport.pwd) {\n sdp.push('a=ice-pwd:' + transport.pwd);\n }\n\n var pushedSetup = false;\n fingerprints.forEach(function (fingerprint) {\n sdp.push('a=fingerprint:' + fingerprint.hash + ' ' + fingerprint.value);\n if (fingerprint.setup && !pushedSetup) {\n sdp.push('a=setup:' + fingerprint.setup);\n }\n });\n\n if (transport.sctp) {\n transport.sctp.forEach(function (map) {\n sdp.push('a=sctpmap:' + map.number + ' ' + map.protocol + ' ' + map.streams);\n });\n }\n }\n\n if (desc.descType == 'rtp') {\n sdp.push('a=' + (SENDERS[role][direction][content.senders] || 'sendrecv'));\n }\n sdp.push('a=mid:' + content.name);\n\n if (desc.sources && desc.sources.length) {\n (desc.sources[0].parameters || []).forEach(function (param) {\n if (param.key === 'msid') {\n sdp.push('a=msid:' + param.value);\n }\n });\n }\n\n if (desc.mux) {\n sdp.push('a=rtcp-mux');\n }\n\n var encryption = desc.encryption || [];\n encryption.forEach(function (crypto) {\n sdp.push('a=crypto:' + crypto.tag + ' ' + crypto.cipherSuite + ' ' + crypto.keyParams + (crypto.sessionParams ? ' ' + crypto.sessionParams : ''));\n });\n if (desc.googConferenceFlag) {\n sdp.push('a=x-google-flag:conference');\n }\n\n payloads.forEach(function (payload) {\n var rtpmap = 'a=rtpmap:' + payload.id + ' ' + payload.name + '/' + payload.clockrate;\n if (payload.channels && payload.channels != '1') {\n rtpmap += '/' + payload.channels;\n }\n sdp.push(rtpmap);\n\n if (payload.parameters && payload.parameters.length) {\n var fmtp = ['a=fmtp:' + payload.id];\n var parameters = [];\n payload.parameters.forEach(function (param) {\n parameters.push((param.key ? param.key + '=' : '') + param.value);\n });\n fmtp.push(parameters.join(';'));\n sdp.push(fmtp.join(' '));\n }\n\n if (payload.feedback) {\n payload.feedback.forEach(function (fb) {\n if (fb.type === 'trr-int') {\n sdp.push('a=rtcp-fb:' + payload.id + ' trr-int ' + (fb.value ? fb.value : '0'));\n } else {\n sdp.push('a=rtcp-fb:' + payload.id + ' ' + fb.type + (fb.subtype ? ' ' + fb.subtype : ''));\n }\n });\n }\n });\n\n if (desc.feedback) {\n desc.feedback.forEach(function (fb) {\n if (fb.type === 'trr-int') {\n sdp.push('a=rtcp-fb:* trr-int ' + (fb.value ? fb.value : '0'));\n } else {\n sdp.push('a=rtcp-fb:* ' + fb.type + (fb.subtype ? ' ' + fb.subtype : ''));\n }\n });\n }\n\n var hdrExts = desc.headerExtensions || [];\n hdrExts.forEach(function (hdr) {\n sdp.push('a=extmap:' + hdr.id + (hdr.senders ? '/' + SENDERS[role][direction][hdr.senders] : '') + ' ' + hdr.uri);\n });\n\n var ssrcGroups = desc.sourceGroups || [];\n ssrcGroups.forEach(function (ssrcGroup) {\n sdp.push('a=ssrc-group:' + ssrcGroup.semantics + ' ' + ssrcGroup.sources.join(' '));\n });\n\n var ssrcs = desc.sources || [];\n ssrcs.forEach(function (ssrc) {\n for (var i = 0; i < ssrc.parameters.length; i++) {\n var param = ssrc.parameters[i];\n sdp.push('a=ssrc:' + (ssrc.ssrc || desc.ssrc) + ' ' + param.key + (param.value ? (':' + param.value) : ''));\n }\n });\n\n var candidates = transport.candidates || [];\n candidates.forEach(function (candidate) {\n sdp.push(exports.toCandidateSDP(candidate));\n });\n\n return sdp.join('\\r\\n');\n};\n\nexports.toCandidateSDP = function (candidate) {\n var sdp = [];\n\n sdp.push(candidate.foundation);\n sdp.push(candidate.component);\n sdp.push(candidate.protocol.toUpperCase());\n sdp.push(candidate.priority);\n sdp.push(candidate.ip);\n sdp.push(candidate.port);\n\n var type = candidate.type;\n sdp.push('typ');\n sdp.push(type);\n if (type === 'srflx' || type === 'prflx' || type === 'relay') {\n if (candidate.relAddr && candidate.relPort) {\n sdp.push('raddr');\n sdp.push(candidate.relAddr);\n sdp.push('rport');\n sdp.push(candidate.relPort);\n }\n }\n if (candidate.tcpType && candidate.protocol.toUpperCase() == 'TCP') {\n sdp.push('tcptype');\n sdp.push(candidate.tcpType);\n }\n\n sdp.push('generation');\n sdp.push(candidate.generation || '0');\n\n // FIXME: apparently this is wrong per spec\n // but then, we need this when actually putting this into\n // SDP so it's going to stay.\n // decision needs to be revisited when browsers dont\n // accept this any longer\n return 'a=candidate:' + sdp.join(' ');\n};\n","var util = require('util');\nvar webrtc = require('webrtcsupport');\nvar PeerConnection = require('rtcpeerconnection');\nvar WildEmitter = require('wildemitter');\nvar FileTransfer = require('filetransfer');\n\n// the inband-v1 protocol is sending metadata inband in a serialized JSON object\n// followed by the actual data. Receiver closes the datachannel upon completion\nvar INBAND_FILETRANSFER_V1 = 'https://simplewebrtc.com/protocol/filetransfer#inband-v1';\n\nfunction Peer(options) {\n var self = this;\n\n // call emitter constructor\n WildEmitter.call(this);\n\n this.id = options.id;\n this.parent = options.parent;\n this.type = options.type || 'video';\n this.oneway = options.oneway || false;\n this.sharemyscreen = options.sharemyscreen || false;\n this.browserPrefix = options.prefix;\n this.stream = options.stream;\n this.enableDataChannels = options.enableDataChannels === undefined ? this.parent.config.enableDataChannels : options.enableDataChannels;\n this.receiveMedia = options.receiveMedia || this.parent.config.receiveMedia;\n this.channels = {};\n this.sid = options.sid || Date.now().toString();\n // Create an RTCPeerConnection via the polyfill\n this.pc = new PeerConnection(this.parent.config.peerConnectionConfig, this.parent.config.peerConnectionConstraints);\n this.pc.on('ice', this.onIceCandidate.bind(this));\n this.pc.on('offer', function (offer) {\n if (self.parent.config.nick) offer.nick = self.parent.config.nick;\n self.send('offer', offer);\n });\n this.pc.on('answer', function (answer) {\n if (self.parent.config.nick) answer.nick = self.parent.config.nick;\n self.send('answer', answer);\n });\n this.pc.on('addStream', this.handleRemoteStreamAdded.bind(this));\n this.pc.on('addChannel', this.handleDataChannelAdded.bind(this));\n this.pc.on('removeStream', this.handleStreamRemoved.bind(this));\n // Just fire negotiation needed events for now\n // When browser re-negotiation handling seems to work\n // we can use this as the trigger for starting the offer/answer process\n // automatically. We'll just leave it be for now while this stabalizes.\n this.pc.on('negotiationNeeded', this.emit.bind(this, 'negotiationNeeded'));\n this.pc.on('iceConnectionStateChange', this.emit.bind(this, 'iceConnectionStateChange'));\n this.pc.on('iceConnectionStateChange', function () {\n switch (self.pc.iceConnectionState) {\n case 'failed':\n // currently, in chrome only the initiator goes to failed\n // so we need to signal this to the peer\n if (self.pc.pc.peerconnection.localDescription.type === 'offer') {\n self.parent.emit('iceFailed', self);\n self.send('connectivityError');\n }\n break;\n }\n });\n this.pc.on('signalingStateChange', this.emit.bind(this, 'signalingStateChange'));\n this.logger = this.parent.logger;\n\n // handle screensharing/broadcast mode\n if (options.type === 'screen') {\n if (this.parent.localScreen && this.sharemyscreen) {\n this.logger.log('adding local screen stream to peer connection');\n this.pc.addStream(this.parent.localScreen);\n this.broadcaster = options.broadcaster;\n }\n } else {\n this.parent.localStreams.forEach(function (stream) {\n self.pc.addStream(stream);\n });\n }\n\n this.on('channelOpen', function (channel) {\n if (channel.protocol === INBAND_FILETRANSFER_V1) {\n channel.onmessage = function (event) {\n var metadata = JSON.parse(event.data);\n var receiver = new FileTransfer.Receiver();\n receiver.receive(metadata, channel);\n self.emit('fileTransfer', metadata, receiver);\n receiver.on('receivedFile', function (file, metadata) {\n receiver.channel.close();\n });\n };\n }\n });\n\n // proxy events to parent\n this.on('*', function () {\n self.parent.emit.apply(self.parent, arguments);\n });\n}\n\nutil.inherits(Peer, WildEmitter);\n\nPeer.prototype.handleMessage = function (message) {\n var self = this;\n\n this.logger.log('getting', message.type, message);\n\n if (message.prefix) this.browserPrefix = message.prefix;\n\n if (message.type === 'offer') {\n if (!this.nick) this.nick = message.payload.nick;\n delete message.payload.nick;\n // workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1064247\n message.payload.sdp = message.payload.sdp.replace('a=fmtp:0 profile-level-id=0x42e00c;packetization-mode=1\\r\\n', '');\n this.pc.handleOffer(message.payload, function (err) {\n if (err) {\n return;\n }\n // auto-accept\n self.pc.answer(self.receiveMedia, function (err, sessionDescription) {\n //self.send('answer', sessionDescription);\n });\n });\n } else if (message.type === 'answer') {\n if (!this.nick) this.nick = message.payload.nick;\n delete message.payload.nick;\n this.pc.handleAnswer(message.payload);\n } else if (message.type === 'candidate') {\n this.pc.processIce(message.payload);\n } else if (message.type === 'connectivityError') {\n this.parent.emit('connectivityError', self);\n } else if (message.type === 'mute') {\n this.parent.emit('mute', {id: message.from, name: message.payload.name});\n } else if (message.type === 'unmute') {\n this.parent.emit('unmute', {id: message.from, name: message.payload.name});\n }\n};\n\n// send via signalling channel\nPeer.prototype.send = function (messageType, payload) {\n var message = {\n to: this.id,\n sid: this.sid,\n broadcaster: this.broadcaster,\n roomType: this.type,\n type: messageType,\n payload: payload,\n prefix: webrtc.prefix\n };\n this.logger.log('sending', messageType, message);\n this.parent.emit('message', message);\n};\n\n// send via data channel\n// returns true when message was sent and false if channel is not open\nPeer.prototype.sendDirectly = function (channel, messageType, payload) {\n var message = {\n type: messageType,\n payload: payload\n };\n this.logger.log('sending via datachannel', channel, messageType, message);\n var dc = this.getDataChannel(channel);\n if (dc.readyState != 'open') return false;\n dc.send(JSON.stringify(message));\n return true;\n};\n\n// Internal method registering handlers for a data channel and emitting events on the peer\nPeer.prototype._observeDataChannel = function (channel) {\n var self = this;\n channel.onclose = this.emit.bind(this, 'channelClose', channel);\n channel.onerror = this.emit.bind(this, 'channelError', channel);\n channel.onmessage = function (event) {\n self.emit('channelMessage', self, channel.label, JSON.parse(event.data), channel, event);\n };\n channel.onopen = this.emit.bind(this, 'channelOpen', channel);\n};\n\n// Fetch or create a data channel by the given name\nPeer.prototype.getDataChannel = function (name, opts) {\n if (!webrtc.supportDataChannel) return this.emit('error', new Error('createDataChannel not supported'));\n var channel = this.channels[name];\n opts || (opts = {});\n if (channel) return channel;\n // if we don't have one by this label, create it\n channel = this.channels[name] = this.pc.createDataChannel(name, opts);\n this._observeDataChannel(channel);\n return channel;\n};\n\nPeer.prototype.onIceCandidate = function (candidate) {\n if (this.closed) return;\n if (candidate) {\n var pcConfig = this.parent.config.peerConnectionConfig;\n if (webrtc.prefix === 'moz' && pcConfig && pcConfig.iceTransports &&\n candidate.candidate && candidate.candidate.candidate &&\n candidate.candidate.candidate.indexOf(pcConfig.iceTransports) < 0) {\n this.logger.log('Ignoring ice candidate not matching pcConfig iceTransports type: ', pcConfig.iceTransports);\n } else {\n this.send('candidate', candidate);\n }\n } else {\n this.logger.log(\"End of candidates.\");\n }\n};\n\nPeer.prototype.start = function () {\n var self = this;\n\n // well, the webrtc api requires that we either\n // a) create a datachannel a priori\n // b) do a renegotiation later to add the SCTP m-line\n // Let's do (a) first...\n if (this.enableDataChannels) {\n this.getDataChannel('simplewebrtc');\n }\n\n this.pc.offer(this.receiveMedia, function (err, sessionDescription) {\n //self.send('offer', sessionDescription);\n });\n};\n\nPeer.prototype.icerestart = function () {\n var constraints = this.receiveMedia;\n constraints.mandatory.IceRestart = true;\n this.pc.offer(constraints, function (err, success) { });\n};\n\nPeer.prototype.end = function () {\n if (this.closed) return;\n this.pc.close();\n this.handleStreamRemoved();\n};\n\nPeer.prototype.handleRemoteStreamAdded = function (event) {\n var self = this;\n if (this.stream) {\n this.logger.warn('Already have a remote stream');\n } else {\n this.stream = event.stream;\n // FIXME: addEventListener('ended', ...) would be nicer\n // but does not work in firefox\n this.stream.onended = function () {\n self.end();\n };\n this.parent.emit('peerStreamAdded', this);\n }\n};\n\nPeer.prototype.handleStreamRemoved = function () {\n this.parent.peers.splice(this.parent.peers.indexOf(this), 1);\n this.closed = true;\n this.parent.emit('peerStreamRemoved', this);\n};\n\nPeer.prototype.handleDataChannelAdded = function (channel) {\n this.channels[channel.label] = channel;\n this._observeDataChannel(channel);\n};\n\nPeer.prototype.sendFile = function (file) {\n var sender = new FileTransfer.Sender();\n var dc = this.getDataChannel('filetransfer' + (new Date()).getTime(), {\n protocol: INBAND_FILETRANSFER_V1\n });\n // override onopen\n dc.onopen = function () {\n dc.send(JSON.stringify({\n size: file.size,\n name: file.name\n }));\n sender.send(file, dc);\n };\n // override onclose\n dc.onclose = function () {\n console.log('sender received transfer');\n sender.emit('complete');\n };\n return sender;\n};\n\nmodule.exports = Peer;\n","var WebRTC = require('./webrtc');\nvar WildEmitter = require('wildemitter');\nvar webrtcSupport = require('webrtcsupport');\nvar attachMediaStream = require('attachmediastream');\nvar mockconsole = require('mockconsole');\nvar SocketIoConnection = require('./socketioconnection');\n\nfunction SimpleWebRTC(opts) {\n var self = this;\n var options = opts || {};\n var config = this.config = {\n url: 'https://signaling.simplewebrtc.com:443/',\n socketio: {/* 'force new connection':true*/},\n connection: null,\n debug: false,\n localVideoEl: '',\n remoteVideosEl: '',\n enableDataChannels: true,\n autoRequestMedia: false,\n autoRemoveVideos: true,\n adjustPeerVolume: true,\n peerVolumeWhenSpeaking: 0.25,\n media: {\n video: true,\n audio: true\n },\n receiveMedia: { // FIXME: remove old chrome <= 37 constraints format\n mandatory: {\n OfferToReceiveAudio: true,\n OfferToReceiveVideo: true\n }\n },\n localVideo: {\n autoplay: true,\n mirror: true,\n muted: true\n }\n };\n var item, connection;\n\n // We also allow a 'logger' option. It can be any object that implements\n // log, warn, and error methods.\n // We log nothing by default, following \"the rule of silence\":\n // http://www.linfo.org/rule_of_silence.html\n this.logger = function () {\n // we assume that if you're in debug mode and you didn't\n // pass in a logger, you actually want to log as much as\n // possible.\n if (opts.debug) {\n return opts.logger || console;\n } else {\n // or we'll use your logger which should have its own logic\n // for output. Or we'll return the no-op.\n return opts.logger || mockconsole;\n }\n }();\n\n // set our config from options\n for (item in options) {\n this.config[item] = options[item];\n }\n\n // attach detected support for convenience\n this.capabilities = webrtcSupport;\n\n // call WildEmitter constructor\n WildEmitter.call(this);\n\n // create default SocketIoConnection if it's not passed in\n if (this.config.connection === null) {\n connection = this.connection = new SocketIoConnection(this.config);\n } else {\n connection = this.connection = this.config.connection;\n }\n\n connection.on('connect', function () {\n self.emit('connectionReady', connection.getSessionid());\n self.sessionReady = true;\n self.testReadiness();\n });\n\n connection.on('message', function (message) {\n var peers = self.webrtc.getPeers(message.from, message.roomType);\n var peer;\n\n if (message.type === 'offer') {\n if (peers.length) {\n peers.forEach(function (p) {\n if (p.sid == message.sid) peer = p;\n });\n //if (!peer) peer = peers[0]; // fallback for old protocol versions\n }\n if (!peer) {\n peer = self.webrtc.createPeer({\n id: message.from,\n sid: message.sid,\n type: message.roomType,\n enableDataChannels: self.config.enableDataChannels && message.roomType !== 'screen',\n sharemyscreen: message.roomType === 'screen' && !message.broadcaster,\n broadcaster: message.roomType === 'screen' && !message.broadcaster ? self.connection.getSessionid() : null\n });\n self.emit('createdPeer', peer);\n }\n peer.handleMessage(message);\n } else if (peers.length) {\n peers.forEach(function (peer) {\n if (message.sid) {\n if (peer.sid === message.sid) {\n peer.handleMessage(message);\n }\n } else {\n peer.handleMessage(message);\n }\n });\n }\n });\n\n connection.on('remove', function (room) {\n if (room.id !== self.connection.getSessionid()) {\n self.webrtc.removePeers(room.id, room.type);\n }\n });\n\n // instantiate our main WebRTC helper\n // using same logger from logic here\n opts.logger = this.logger;\n opts.debug = false;\n this.webrtc = new WebRTC(opts);\n\n // attach a few methods from underlying lib to simple.\n ['mute', 'unmute', 'pauseVideo', 'resumeVideo', 'pause', 'resume', 'sendToAll', 'sendDirectlyToAll', 'getPeers'].forEach(function (method) {\n self[method] = self.webrtc[method].bind(self.webrtc);\n });\n\n // proxy events from WebRTC\n this.webrtc.on('*', function () {\n self.emit.apply(self, arguments);\n });\n\n // log all events in debug mode\n if (config.debug) {\n this.on('*', this.logger.log.bind(this.logger, 'SimpleWebRTC event:'));\n }\n\n // check for readiness\n this.webrtc.on('localStream', function () {\n self.testReadiness();\n });\n\n this.webrtc.on('message', function (payload) {\n self.connection.emit('message', payload);\n });\n\n this.webrtc.on('peerStreamAdded', this.handlePeerStreamAdded.bind(this));\n this.webrtc.on('peerStreamRemoved', this.handlePeerStreamRemoved.bind(this));\n\n // echo cancellation attempts\n if (this.config.adjustPeerVolume) {\n this.webrtc.on('speaking', this.setVolumeForAll.bind(this, this.config.peerVolumeWhenSpeaking));\n this.webrtc.on('stoppedSpeaking', this.setVolumeForAll.bind(this, 1));\n }\n\n connection.on('stunservers', function (args) {\n // resets/overrides the config\n self.webrtc.config.peerConnectionConfig.iceServers = args;\n self.emit('stunservers', args);\n });\n connection.on('turnservers', function (args) {\n // appends to the config\n self.webrtc.config.peerConnectionConfig.iceServers = self.webrtc.config.peerConnectionConfig.iceServers.concat(args);\n self.emit('turnservers', args);\n });\n\n this.webrtc.on('iceFailed', function (peer) {\n // local ice failure\n });\n this.webrtc.on('connectivityError', function (peer) {\n // remote ice failure\n });\n\n\n // sending mute/unmute to all peers\n this.webrtc.on('audioOn', function () {\n self.webrtc.sendToAll('unmute', {name: 'audio'});\n });\n this.webrtc.on('audioOff', function () {\n self.webrtc.sendToAll('mute', {name: 'audio'});\n });\n this.webrtc.on('videoOn', function () {\n self.webrtc.sendToAll('unmute', {name: 'video'});\n });\n this.webrtc.on('videoOff', function () {\n self.webrtc.sendToAll('mute', {name: 'video'});\n });\n\n // screensharing events\n this.webrtc.on('localScreen', function (stream) {\n var item,\n el = document.createElement('video'),\n container = self.getRemoteVideoContainer();\n\n el.oncontextmenu = function () { return false; };\n el.id = 'localScreen';\n attachMediaStream(stream, el);\n if (container) {\n container.appendChild(el);\n }\n\n self.emit('localScreenAdded', el);\n self.connection.emit('shareScreen');\n\n self.webrtc.peers.forEach(function (existingPeer) {\n var peer;\n if (existingPeer.type === 'video') {\n peer = self.webrtc.createPeer({\n id: existingPeer.id,\n type: 'screen',\n sharemyscreen: true,\n enableDataChannels: false,\n receiveMedia: {\n mandatory: {\n OfferToReceiveAudio: false,\n OfferToReceiveVideo: false\n }\n },\n broadcaster: self.connection.getSessionid(),\n });\n self.emit('createdPeer', peer);\n peer.start();\n }\n });\n });\n this.webrtc.on('localScreenStopped', function (stream) {\n self.stopScreenShare();\n /*\n self.connection.emit('unshareScreen');\n self.webrtc.peers.forEach(function (peer) {\n if (peer.sharemyscreen) {\n peer.end();\n }\n });\n */\n });\n\n this.webrtc.on('channelMessage', function (peer, label, data) {\n if (data.type == 'volume') {\n self.emit('remoteVolumeChange', peer, data.volume);\n }\n });\n\n if (this.config.autoRequestMedia) this.startLocalVideo();\n}\n\n\nSimpleWebRTC.prototype = Object.create(WildEmitter.prototype, {\n constructor: {\n value: SimpleWebRTC\n }\n});\n\nSimpleWebRTC.prototype.leaveRoom = function () {\n if (this.roomName) {\n this.connection.emit('leave');\n this.webrtc.peers.forEach(function (peer) {\n peer.end();\n });\n if (this.getLocalScreen()) {\n this.stopScreenShare();\n }\n this.emit('leftRoom', this.roomName);\n this.roomName = undefined;\n }\n};\n\nSimpleWebRTC.prototype.disconnect = function () {\n this.connection.disconnect();\n delete this.connection;\n};\n\nSimpleWebRTC.prototype.handlePeerStreamAdded = function (peer) {\n var self = this;\n var container = this.getRemoteVideoContainer();\n var video = attachMediaStream(peer.stream);\n\n // store video element as part of peer for easy removal\n peer.videoEl = video;\n video.id = this.getDomId(peer);\n\n if (container) container.appendChild(video);\n\n this.emit('videoAdded', video, peer);\n\n // send our mute status to new peer if we're muted\n // currently called with a small delay because it arrives before\n // the video element is created otherwise (which happens after\n // the async setRemoteDescription-createAnswer)\n window.setTimeout(function () {\n if (!self.webrtc.isAudioEnabled()) {\n peer.send('mute', {name: 'audio'});\n }\n if (!self.webrtc.isVideoEnabled()) {\n peer.send('mute', {name: 'video'});\n }\n }, 250);\n};\n\nSimpleWebRTC.prototype.handlePeerStreamRemoved = function (peer) {\n var container = this.getRemoteVideoContainer();\n var videoEl = peer.videoEl;\n if (this.config.autoRemoveVideos && container && videoEl) {\n container.removeChild(videoEl);\n }\n if (videoEl) this.emit('videoRemoved', videoEl, peer);\n};\n\nSimpleWebRTC.prototype.getDomId = function (peer) {\n return [peer.id, peer.type, peer.broadcaster ? 'broadcasting' : 'incoming'].join('_');\n};\n\n// set volume on video tag for all peers takse a value between 0 and 1\nSimpleWebRTC.prototype.setVolumeForAll = function (volume) {\n this.webrtc.peers.forEach(function (peer) {\n if (peer.videoEl) peer.videoEl.volume = volume;\n });\n};\n\nSimpleWebRTC.prototype.joinRoom = function (name, cb) {\n var self = this;\n this.roomName = name;\n this.connection.emit('join', name, function (err, roomDescription) {\n if (err) {\n self.emit('error', err);\n } else {\n var id,\n client,\n type,\n peer;\n for (id in roomDescription.clients) {\n client = roomDescription.clients[id];\n for (type in client) {\n if (client[type]) {\n peer = self.webrtc.createPeer({\n id: id,\n type: type,\n enableDataChannels: self.config.enableDataChannels && type !== 'screen',\n receiveMedia: {\n mandatory: {\n OfferToReceiveAudio: type !== 'screen' && self.config.receiveMedia.mandatory.OfferToReceiveAudio,\n OfferToReceiveVideo: self.config.receiveMedia.mandatory.OfferToReceiveVideo\n }\n }\n });\n self.emit('createdPeer', peer);\n peer.start();\n }\n }\n }\n }\n\n if (cb) cb(err, roomDescription);\n self.emit('joinedRoom', name);\n });\n};\n\nSimpleWebRTC.prototype.getEl = function (idOrEl) {\n if (typeof idOrEl === 'string') {\n return document.getElementById(idOrEl);\n } else {\n return idOrEl;\n }\n};\n\nSimpleWebRTC.prototype.startLocalVideo = function () {\n var self = this;\n this.webrtc.startLocalMedia(this.config.media, function (err, stream) {\n if (err) {\n self.emit('localMediaError', err);\n } else {\n attachMediaStream(stream, self.getLocalVideoContainer(), self.config.localVideo);\n }\n });\n};\n\nSimpleWebRTC.prototype.stopLocalVideo = function () {\n this.webrtc.stopLocalMedia();\n};\n\n// this accepts either element ID or element\n// and either the video tag itself or a container\n// that will be used to put the video tag into.\nSimpleWebRTC.prototype.getLocalVideoContainer = function () {\n var el = this.getEl(this.config.localVideoEl);\n if (el && el.tagName === 'VIDEO') {\n el.oncontextmenu = function () { return false; };\n return el;\n } else if (el) {\n var video = document.createElement('video');\n video.oncontextmenu = function () { return false; };\n el.appendChild(video);\n return video;\n } else {\n return;\n }\n};\n\nSimpleWebRTC.prototype.getRemoteVideoContainer = function () {\n return this.getEl(this.config.remoteVideosEl);\n};\n\nSimpleWebRTC.prototype.shareScreen = function (cb) {\n this.webrtc.startScreenShare(cb);\n};\n\nSimpleWebRTC.prototype.getLocalScreen = function () {\n return this.webrtc.localScreen;\n};\n\nSimpleWebRTC.prototype.stopScreenShare = function () {\n this.connection.emit('unshareScreen');\n var videoEl = document.getElementById('localScreen');\n var container = this.getRemoteVideoContainer();\n var stream = this.getLocalScreen();\n\n if (this.config.autoRemoveVideos && container && videoEl) {\n container.removeChild(videoEl);\n }\n\n // a hack to emit the event the removes the video\n // element that we want\n if (videoEl) this.emit('videoRemoved', videoEl);\n if (stream) stream.stop();\n this.webrtc.peers.forEach(function (peer) {\n if (peer.broadcaster) {\n peer.end();\n }\n });\n //delete this.webrtc.localScreen;\n};\n\nSimpleWebRTC.prototype.testReadiness = function () {\n var self = this;\n if (this.webrtc.localStream && this.sessionReady) {\n self.emit('readyToCall', self.connection.getSessionid());\n }\n};\n\nSimpleWebRTC.prototype.createRoom = function (name, cb) {\n if (arguments.length === 2) {\n this.connection.emit('create', name, cb);\n } else {\n this.connection.emit('create', name);\n }\n};\n\nSimpleWebRTC.prototype.sendFile = function () {\n if (!webrtcSupport.dataChannel) {\n return this.emit('error', new Error('DataChannelNotSupported'));\n }\n\n};\n\nmodule.exports = SimpleWebRTC;\n","var io = require('socket.io-client');\n\nfunction SocketIoConnection(config) {\n this.connection = io.connect(config.url, config.socketio);\n}\n\nSocketIoConnection.prototype.on = function (ev, fn) {\n this.connection.on(ev, fn);\n};\n\nSocketIoConnection.prototype.emit = function () {\n this.connection.emit.apply(this.connection, arguments);\n};\n\nSocketIoConnection.prototype.getSessionid = function () {\n return this.connection.socket.sessionid;\n};\n\nSocketIoConnection.prototype.disconnect = function () {\n return this.connection.disconnect();\n};\n\nmodule.exports = SocketIoConnection;\n","var util = require('util');\nvar webrtc = require('webrtcsupport');\nvar WildEmitter = require('wildemitter');\nvar mockconsole = require('mockconsole');\nvar localMedia = require('localmedia');\nvar Peer = require('./peer');\n\n\nfunction WebRTC(opts) {\n var self = this;\n var options = opts || {};\n var config = this.config = {\n debug: false,\n // makes the entire PC config overridable\n peerConnectionConfig: {\n iceServers: [{\"url\": \"stun:stun.l.google.com:19302\"}]\n },\n peerConnectionConstraints: {\n optional: [\n {DtlsSrtpKeyAgreement: true}\n ]\n },\n receiveMedia: {\n mandatory: {\n OfferToReceiveAudio: true,\n OfferToReceiveVideo: true\n }\n },\n enableDataChannels: true\n };\n var item;\n\n // expose screensharing check\n this.screenSharingSupport = webrtc.screenSharing;\n\n // We also allow a 'logger' option. It can be any object that implements\n // log, warn, and error methods.\n // We log nothing by default, following \"the rule of silence\":\n // http://www.linfo.org/rule_of_silence.html\n this.logger = function () {\n // we assume that if you're in debug mode and you didn't\n // pass in a logger, you actually want to log as much as\n // possible.\n if (opts.debug) {\n return opts.logger || console;\n } else {\n // or we'll use your logger which should have its own logic\n // for output. Or we'll return the no-op.\n return opts.logger || mockconsole;\n }\n }();\n\n // set options\n for (item in options) {\n this.config[item] = options[item];\n }\n\n // check for support\n if (!webrtc.support) {\n this.logger.error('Your browser doesn\\'t seem to support WebRTC');\n }\n\n // where we'll store our peer connections\n this.peers = [];\n\n // call localMedia constructor\n localMedia.call(this, this.config);\n\n this.on('speaking', function () {\n if (!self.hardMuted) {\n // FIXME: should use sendDirectlyToAll, but currently has different semantics wrt payload\n self.peers.forEach(function (peer) {\n if (peer.enableDataChannels) {\n var dc = peer.getDataChannel('hark');\n if (dc.readyState != 'open') return;\n dc.send(JSON.stringify({type: 'speaking'}));\n }\n });\n }\n });\n this.on('stoppedSpeaking', function () {\n if (!self.hardMuted) {\n // FIXME: should use sendDirectlyToAll, but currently has different semantics wrt payload\n self.peers.forEach(function (peer) {\n if (peer.enableDataChannels) {\n var dc = peer.getDataChannel('hark');\n if (dc.readyState != 'open') return;\n dc.send(JSON.stringify({type: 'stoppedSpeaking'}));\n }\n });\n }\n });\n this.on('volumeChange', function (volume, treshold) {\n if (!self.hardMuted) {\n // FIXME: should use sendDirectlyToAll, but currently has different semantics wrt payload\n self.peers.forEach(function (peer) {\n if (peer.enableDataChannels) {\n var dc = peer.getDataChannel('hark');\n if (dc.readyState != 'open') return;\n dc.send(JSON.stringify({type: 'volume', volume: volume }));\n }\n });\n }\n });\n\n // log events in debug mode\n if (this.config.debug) {\n this.on('*', function (event, val1, val2) {\n var logger;\n // if you didn't pass in a logger and you explicitly turning on debug\n // we're just going to assume you're wanting log output with console\n if (self.config.logger === mockconsole) {\n logger = console;\n } else {\n logger = self.logger;\n }\n logger.log('event:', event, val1, val2);\n });\n }\n}\n\nutil.inherits(WebRTC, localMedia);\n\nWebRTC.prototype.createPeer = function (opts) {\n var peer;\n opts.parent = this;\n peer = new Peer(opts);\n this.peers.push(peer);\n return peer;\n};\n\n// removes peers\nWebRTC.prototype.removePeers = function (id, type) {\n this.getPeers(id, type).forEach(function (peer) {\n peer.end();\n });\n};\n\n// fetches all Peer objects by session id and/or type\nWebRTC.prototype.getPeers = function (sessionId, type) {\n return this.peers.filter(function (peer) {\n return (!sessionId || peer.id === sessionId) && (!type || peer.type === type);\n });\n};\n\n// sends message to all\nWebRTC.prototype.sendToAll = function (message, payload) {\n this.peers.forEach(function (peer) {\n peer.send(message, payload);\n });\n};\n\n// sends message to all using a datachannel\n// only sends to anyone who has an open datachannel\nWebRTC.prototype.sendDirectlyToAll = function (channel, message, payload) {\n this.peers.forEach(function (peer) {\n if (peer.enableDataChannels) {\n peer.sendDirectly(channel, message, payload);\n }\n });\n};\n\nmodule.exports = WebRTC;\n","/*! Socket.IO.js build:0.9.16, development. Copyright(c) 2011 LearnBoost <dev@learnboost.com> MIT Licensed */\n\nvar io = ('undefined' === typeof module ? {} : module.exports);\n(function() {\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, global) {\n\n /**\n * IO namespace.\n *\n * @namespace\n */\n\n var io = exports;\n\n /**\n * Socket.IO version\n *\n * @api public\n */\n\n io.version = '0.9.16';\n\n /**\n * Protocol implemented.\n *\n * @api public\n */\n\n io.protocol = 1;\n\n /**\n * Available transports, these will be populated with the available transports\n *\n * @api public\n */\n\n io.transports = [];\n\n /**\n * Keep track of jsonp callbacks.\n *\n * @api private\n */\n\n io.j = [];\n\n /**\n * Keep track of our io.Sockets\n *\n * @api private\n */\n io.sockets = {};\n\n\n /**\n * Manages connections to hosts.\n *\n * @param {String} uri\n * @Param {Boolean} force creation of new socket (defaults to false)\n * @api public\n */\n\n io.connect = function (host, details) {\n var uri = io.util.parseUri(host)\n , uuri\n , socket;\n\n if (global && global.location) {\n uri.protocol = uri.protocol || global.location.protocol.slice(0, -1);\n uri.host = uri.host || (global.document\n ? global.document.domain : global.location.hostname);\n uri.port = uri.port || global.location.port;\n }\n\n uuri = io.util.uniqueUri(uri);\n\n var options = {\n host: uri.host\n , secure: 'https' == uri.protocol\n , port: uri.port || ('https' == uri.protocol ? 443 : 80)\n , query: uri.query || ''\n };\n\n io.util.merge(options, details);\n\n if (options['force new connection'] || !io.sockets[uuri]) {\n socket = new io.Socket(options);\n }\n\n if (!options['force new connection'] && socket) {\n io.sockets[uuri] = socket;\n }\n\n socket = socket || io.sockets[uuri];\n\n // if path is different from '' or /\n return socket.of(uri.path.length > 1 ? uri.path : '');\n };\n\n})('object' === typeof module ? module.exports : (this.io = {}), this);\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, global) {\n\n /**\n * Utilities namespace.\n *\n * @namespace\n */\n\n var util = exports.util = {};\n\n /**\n * Parses an URI\n *\n * @author Steven Levithan <stevenlevithan.com> (MIT license)\n * @api public\n */\n\n var re = /^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/;\n\n var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password',\n 'host', 'port', 'relative', 'path', 'directory', 'file', 'query',\n 'anchor'];\n\n util.parseUri = function (str) {\n var m = re.exec(str || '')\n , uri = {}\n , i = 14;\n\n while (i--) {\n uri[parts[i]] = m[i] || '';\n }\n\n return uri;\n };\n\n /**\n * Produces a unique url that identifies a Socket.IO connection.\n *\n * @param {Object} uri\n * @api public\n */\n\n util.uniqueUri = function (uri) {\n var protocol = uri.protocol\n , host = uri.host\n , port = uri.port;\n\n if ('document' in global) {\n host = host || document.domain;\n port = port || (protocol == 'https'\n && document.location.protocol !== 'https:' ? 443 : document.location.port);\n } else {\n host = host || 'localhost';\n\n if (!port && protocol == 'https') {\n port = 443;\n }\n }\n\n return (protocol || 'http') + '://' + host + ':' + (port || 80);\n };\n\n /**\n * Mergest 2 query strings in to once unique query string\n *\n * @param {String} base\n * @param {String} addition\n * @api public\n */\n\n util.query = function (base, addition) {\n var query = util.chunkQuery(base || '')\n , components = [];\n\n util.merge(query, util.chunkQuery(addition || ''));\n for (var part in query) {\n if (query.hasOwnProperty(part)) {\n components.push(part + '=' + query[part]);\n }\n }\n\n return components.length ? '?' + components.join('&') : '';\n };\n\n /**\n * Transforms a querystring in to an object\n *\n * @param {String} qs\n * @api public\n */\n\n util.chunkQuery = function (qs) {\n var query = {}\n , params = qs.split('&')\n , i = 0\n , l = params.length\n , kv;\n\n for (; i < l; ++i) {\n kv = params[i].split('=');\n if (kv[0]) {\n query[kv[0]] = kv[1];\n }\n }\n\n return query;\n };\n\n /**\n * Executes the given function when the page is loaded.\n *\n * io.util.load(function () { console.log('page loaded'); });\n *\n * @param {Function} fn\n * @api public\n */\n\n var pageLoaded = false;\n\n util.load = function (fn) {\n if ('document' in global && document.readyState === 'complete' || pageLoaded) {\n return fn();\n }\n\n util.on(global, 'load', fn, false);\n };\n\n /**\n * Adds an event.\n *\n * @api private\n */\n\n util.on = function (element, event, fn, capture) {\n if (element.attachEvent) {\n element.attachEvent('on' + event, fn);\n } else if (element.addEventListener) {\n element.addEventListener(event, fn, capture);\n }\n };\n\n /**\n * Generates the correct `XMLHttpRequest` for regular and cross domain requests.\n *\n * @param {Boolean} [xdomain] Create a request that can be used cross domain.\n * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest.\n * @api private\n */\n\n util.request = function (xdomain) {\n\n if (xdomain && 'undefined' != typeof XDomainRequest && !util.ua.hasCORS) {\n return new XDomainRequest();\n }\n\n if ('undefined' != typeof XMLHttpRequest && (!xdomain || util.ua.hasCORS)) {\n return new XMLHttpRequest();\n }\n\n if (!xdomain) {\n try {\n return new window[(['Active'].concat('Object').join('X'))]('Microsoft.XMLHTTP');\n } catch(e) { }\n }\n\n return null;\n };\n\n /**\n * XHR based transport constructor.\n *\n * @constructor\n * @api public\n */\n\n /**\n * Change the internal pageLoaded value.\n */\n\n if ('undefined' != typeof window) {\n util.load(function () {\n pageLoaded = true;\n });\n }\n\n /**\n * Defers a function to ensure a spinner is not displayed by the browser\n *\n * @param {Function} fn\n * @api public\n */\n\n util.defer = function (fn) {\n if (!util.ua.webkit || 'undefined' != typeof importScripts) {\n return fn();\n }\n\n util.load(function () {\n setTimeout(fn, 100);\n });\n };\n\n /**\n * Merges two objects.\n *\n * @api public\n */\n\n util.merge = function merge (target, additional, deep, lastseen) {\n var seen = lastseen || []\n , depth = typeof deep == 'undefined' ? 2 : deep\n , prop;\n\n for (prop in additional) {\n if (additional.hasOwnProperty(prop) && util.indexOf(seen, prop) < 0) {\n if (typeof target[prop] !== 'object' || !depth) {\n target[prop] = additional[prop];\n seen.push(additional[prop]);\n } else {\n util.merge(target[prop], additional[prop], depth - 1, seen);\n }\n }\n }\n\n return target;\n };\n\n /**\n * Merges prototypes from objects\n *\n * @api public\n */\n\n util.mixin = function (ctor, ctor2) {\n util.merge(ctor.prototype, ctor2.prototype);\n };\n\n /**\n * Shortcut for prototypical and static inheritance.\n *\n * @api private\n */\n\n util.inherit = function (ctor, ctor2) {\n function f() {};\n f.prototype = ctor2.prototype;\n ctor.prototype = new f;\n };\n\n /**\n * Checks if the given object is an Array.\n *\n * io.util.isArray([]); // true\n * io.util.isArray({}); // false\n *\n * @param Object obj\n * @api public\n */\n\n util.isArray = Array.isArray || function (obj) {\n return Object.prototype.toString.call(obj) === '[object Array]';\n };\n\n /**\n * Intersects values of two arrays into a third\n *\n * @api public\n */\n\n util.intersect = function (arr, arr2) {\n var ret = []\n , longest = arr.length > arr2.length ? arr : arr2\n , shortest = arr.length > arr2.length ? arr2 : arr;\n\n for (var i = 0, l = shortest.length; i < l; i++) {\n if (~util.indexOf(longest, shortest[i]))\n ret.push(shortest[i]);\n }\n\n return ret;\n };\n\n /**\n * Array indexOf compatibility.\n *\n * @see bit.ly/a5Dxa2\n * @api public\n */\n\n util.indexOf = function (arr, o, i) {\n\n for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0;\n i < j && arr[i] !== o; i++) {}\n\n return j <= i ? -1 : i;\n };\n\n /**\n * Converts enumerables to array.\n *\n * @api public\n */\n\n util.toArray = function (enu) {\n var arr = [];\n\n for (var i = 0, l = enu.length; i < l; i++)\n arr.push(enu[i]);\n\n return arr;\n };\n\n /**\n * UA / engines detection namespace.\n *\n * @namespace\n */\n\n util.ua = {};\n\n /**\n * Whether the UA supports CORS for XHR.\n *\n * @api public\n */\n\n util.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () {\n try {\n var a = new XMLHttpRequest();\n } catch (e) {\n return false;\n }\n\n return a.withCredentials != undefined;\n })();\n\n /**\n * Detect webkit.\n *\n * @api public\n */\n\n util.ua.webkit = 'undefined' != typeof navigator\n && /webkit/i.test(navigator.userAgent);\n\n /**\n * Detect iPad/iPhone/iPod.\n *\n * @api public\n */\n\n util.ua.iDevice = 'undefined' != typeof navigator\n && /iPad|iPhone|iPod/i.test(navigator.userAgent);\n\n})('undefined' != typeof io ? io : module.exports, this);\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io) {\n\n /**\n * Expose constructor.\n */\n\n exports.EventEmitter = EventEmitter;\n\n /**\n * Event emitter constructor.\n *\n * @api public.\n */\n\n function EventEmitter () {};\n\n /**\n * Adds a listener\n *\n * @api public\n */\n\n EventEmitter.prototype.on = function (name, fn) {\n if (!this.$events) {\n this.$events = {};\n }\n\n if (!this.$events[name]) {\n this.$events[name] = fn;\n } else if (io.util.isArray(this.$events[name])) {\n this.$events[name].push(fn);\n } else {\n this.$events[name] = [this.$events[name], fn];\n }\n\n return this;\n };\n\n EventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n /**\n * Adds a volatile listener.\n *\n * @api public\n */\n\n EventEmitter.prototype.once = function (name, fn) {\n var self = this;\n\n function on () {\n self.removeListener(name, on);\n fn.apply(this, arguments);\n };\n\n on.listener = fn;\n this.on(name, on);\n\n return this;\n };\n\n /**\n * Removes a listener.\n *\n * @api public\n */\n\n EventEmitter.prototype.removeListener = function (name, fn) {\n if (this.$events && this.$events[name]) {\n var list = this.$events[name];\n\n if (io.util.isArray(list)) {\n var pos = -1;\n\n for (var i = 0, l = list.length; i < l; i++) {\n if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {\n pos = i;\n break;\n }\n }\n\n if (pos < 0) {\n return this;\n }\n\n list.splice(pos, 1);\n\n if (!list.length) {\n delete this.$events[name];\n }\n } else if (list === fn || (list.listener && list.listener === fn)) {\n delete this.$events[name];\n }\n }\n\n return this;\n };\n\n /**\n * Removes all listeners for an event.\n *\n * @api public\n */\n\n EventEmitter.prototype.removeAllListeners = function (name) {\n if (name === undefined) {\n this.$events = {};\n return this;\n }\n\n if (this.$events && this.$events[name]) {\n this.$events[name] = null;\n }\n\n return this;\n };\n\n /**\n * Gets all listeners for a certain event.\n *\n * @api publci\n */\n\n EventEmitter.prototype.listeners = function (name) {\n if (!this.$events) {\n this.$events = {};\n }\n\n if (!this.$events[name]) {\n this.$events[name] = [];\n }\n\n if (!io.util.isArray(this.$events[name])) {\n this.$events[name] = [this.$events[name]];\n }\n\n return this.$events[name];\n };\n\n /**\n * Emits an event.\n *\n * @api public\n */\n\n EventEmitter.prototype.emit = function (name) {\n if (!this.$events) {\n return false;\n }\n\n var handler = this.$events[name];\n\n if (!handler) {\n return false;\n }\n\n var args = Array.prototype.slice.call(arguments, 1);\n\n if ('function' == typeof handler) {\n handler.apply(this, args);\n } else if (io.util.isArray(handler)) {\n var listeners = handler.slice();\n\n for (var i = 0, l = listeners.length; i < l; i++) {\n listeners[i].apply(this, args);\n }\n } else {\n return false;\n }\n\n return true;\n };\n\n})(\n 'undefined' != typeof io ? io : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n);\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n/**\n * Based on JSON2 (http://www.JSON.org/js.html).\n */\n\n(function (exports, nativeJSON) {\n \"use strict\";\n\n // use native JSON if it's available\n if (nativeJSON && nativeJSON.parse){\n return exports.JSON = {\n parse: nativeJSON.parse\n , stringify: nativeJSON.stringify\n };\n }\n\n var JSON = exports.JSON = {};\n\n function f(n) {\n // Format integers to have at least two digits.\n return n < 10 ? '0' + n : n;\n }\n\n function date(d, key) {\n return isFinite(d.valueOf()) ?\n d.getUTCFullYear() + '-' +\n f(d.getUTCMonth() + 1) + '-' +\n f(d.getUTCDate()) + 'T' +\n f(d.getUTCHours()) + ':' +\n f(d.getUTCMinutes()) + ':' +\n f(d.getUTCSeconds()) + 'Z' : null;\n };\n\n var cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n gap,\n indent,\n meta = { // table of character substitutions\n '\\b': '\\\\b',\n '\\t': '\\\\t',\n '\\n': '\\\\n',\n '\\f': '\\\\f',\n '\\r': '\\\\r',\n '\"' : '\\\\\"',\n '\\\\': '\\\\\\\\'\n },\n rep;\n\n\n function quote(string) {\n\n// If the string contains no control characters, no quote characters, and no\n// backslash characters, then we can safely slap some quotes around it.\n// Otherwise we must also replace the offending characters with safe escape\n// sequences.\n\n escapable.lastIndex = 0;\n return escapable.test(string) ? '\"' + string.replace(escapable, function (a) {\n var c = meta[a];\n return typeof c === 'string' ? c :\n '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n }) + '\"' : '\"' + string + '\"';\n }\n\n\n function str(key, holder) {\n\n// Produce a string from holder[key].\n\n var i, // The loop counter.\n k, // The member key.\n v, // The member value.\n length,\n mind = gap,\n partial,\n value = holder[key];\n\n// If the value has a toJSON method, call it to obtain a replacement value.\n\n if (value instanceof Date) {\n value = date(key);\n }\n\n// If we were called with a replacer function, then call the replacer to\n// obtain a replacement value.\n\n if (typeof rep === 'function') {\n value = rep.call(holder, key, value);\n }\n\n// What happens next depends on the value's type.\n\n switch (typeof value) {\n case 'string':\n return quote(value);\n\n case 'number':\n\n// JSON numbers must be finite. Encode non-finite numbers as null.\n\n return isFinite(value) ? String(value) : 'null';\n\n case 'boolean':\n case 'null':\n\n// If the value is a boolean or null, convert it to a string. Note:\n// typeof null does not produce 'null'. The case is included here in\n// the remote chance that this gets fixed someday.\n\n return String(value);\n\n// If the type is 'object', we might be dealing with an object or an array or\n// null.\n\n case 'object':\n\n// Due to a specification blunder in ECMAScript, typeof null is 'object',\n// so watch out for that case.\n\n if (!value) {\n return 'null';\n }\n\n// Make an array to hold the partial results of stringifying this object value.\n\n gap += indent;\n partial = [];\n\n// Is the value an array?\n\n if (Object.prototype.toString.apply(value) === '[object Array]') {\n\n// The value is an array. Stringify every element. Use null as a placeholder\n// for non-JSON values.\n\n length = value.length;\n for (i = 0; i < length; i += 1) {\n partial[i] = str(i, value) || 'null';\n }\n\n// Join all of the elements together, separated with commas, and wrap them in\n// brackets.\n\n v = partial.length === 0 ? '[]' : gap ?\n '[\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + ']' :\n '[' + partial.join(',') + ']';\n gap = mind;\n return v;\n }\n\n// If the replacer is an array, use it to select the members to be stringified.\n\n if (rep && typeof rep === 'object') {\n length = rep.length;\n for (i = 0; i < length; i += 1) {\n if (typeof rep[i] === 'string') {\n k = rep[i];\n v = str(k, value);\n if (v) {\n partial.push(quote(k) + (gap ? ': ' : ':') + v);\n }\n }\n }\n } else {\n\n// Otherwise, iterate through all of the keys in the object.\n\n for (k in value) {\n if (Object.prototype.hasOwnProperty.call(value, k)) {\n v = str(k, value);\n if (v) {\n partial.push(quote(k) + (gap ? ': ' : ':') + v);\n }\n }\n }\n }\n\n// Join all of the member texts together, separated with commas,\n// and wrap them in braces.\n\n v = partial.length === 0 ? '{}' : gap ?\n '{\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + '}' :\n '{' + partial.join(',') + '}';\n gap = mind;\n return v;\n }\n }\n\n// If the JSON object does not yet have a stringify method, give it one.\n\n JSON.stringify = function (value, replacer, space) {\n\n// The stringify method takes a value and an optional replacer, and an optional\n// space parameter, and returns a JSON text. The replacer can be a function\n// that can replace values, or an array of strings that will select the keys.\n// A default replacer method can be provided. Use of the space parameter can\n// produce text that is more easily readable.\n\n var i;\n gap = '';\n indent = '';\n\n// If the space parameter is a number, make an indent string containing that\n// many spaces.\n\n if (typeof space === 'number') {\n for (i = 0; i < space; i += 1) {\n indent += ' ';\n }\n\n// If the space parameter is a string, it will be used as the indent string.\n\n } else if (typeof space === 'string') {\n indent = space;\n }\n\n// If there is a replacer, it must be a function or an array.\n// Otherwise, throw an error.\n\n rep = replacer;\n if (replacer && typeof replacer !== 'function' &&\n (typeof replacer !== 'object' ||\n typeof replacer.length !== 'number')) {\n throw new Error('JSON.stringify');\n }\n\n// Make a fake root object containing our value under the key of ''.\n// Return the result of stringifying the value.\n\n return str('', {'': value});\n };\n\n// If the JSON object does not yet have a parse method, give it one.\n\n JSON.parse = function (text, reviver) {\n // The parse method takes a text and an optional reviver function, and returns\n // a JavaScript value if the text is a valid JSON text.\n\n var j;\n\n function walk(holder, key) {\n\n // The walk method is used to recursively walk the resulting structure so\n // that modifications can be made.\n\n var k, v, value = holder[key];\n if (value && typeof value === 'object') {\n for (k in value) {\n if (Object.prototype.hasOwnProperty.call(value, k)) {\n v = walk(value, k);\n if (v !== undefined) {\n value[k] = v;\n } else {\n delete value[k];\n }\n }\n }\n }\n return reviver.call(holder, key, value);\n }\n\n\n // Parsing happens in four stages. In the first stage, we replace certain\n // Unicode characters with escape sequences. JavaScript handles many characters\n // incorrectly, either silently deleting them, or treating them as line endings.\n\n text = String(text);\n cx.lastIndex = 0;\n if (cx.test(text)) {\n text = text.replace(cx, function (a) {\n return '\\\\u' +\n ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n });\n }\n\n // In the second stage, we run the text against regular expressions that look\n // for non-JSON patterns. We are especially concerned with '()' and 'new'\n // because they can cause invocation, and '=' because it can cause mutation.\n // But just to be safe, we want to reject all unexpected forms.\n\n // We split the second stage into 4 regexp operations in order to work around\n // crippling inefficiencies in IE's and Safari's regexp engines. First we\n // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we\n // replace all simple value tokens with ']' characters. Third, we delete all\n // open brackets that follow a colon or comma or that begin the text. Finally,\n // we look to see that the remaining characters are only whitespace or ']' or\n // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.\n\n if (/^[\\],:{}\\s]*$/\n .test(text.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')\n .replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']')\n .replace(/(?:^|:|,)(?:\\s*\\[)+/g, ''))) {\n\n // In the third stage we use the eval function to compile the text into a\n // JavaScript structure. The '{' operator is subject to a syntactic ambiguity\n // in JavaScript: it can begin a block or an object literal. We wrap the text\n // in parens to eliminate the ambiguity.\n\n j = eval('(' + text + ')');\n\n // In the optional fourth stage, we recursively walk the new structure, passing\n // each name/value pair to a reviver function for possible transformation.\n\n return typeof reviver === 'function' ?\n walk({'': j}, '') : j;\n }\n\n // If the text is not JSON parseable, then a SyntaxError is thrown.\n\n throw new SyntaxError('JSON.parse');\n };\n\n})(\n 'undefined' != typeof io ? io : module.exports\n , typeof JSON !== 'undefined' ? JSON : undefined\n);\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io) {\n\n /**\n * Parser namespace.\n *\n * @namespace\n */\n\n var parser = exports.parser = {};\n\n /**\n * Packet types.\n */\n\n var packets = parser.packets = [\n 'disconnect'\n , 'connect'\n , 'heartbeat'\n , 'message'\n , 'json'\n , 'event'\n , 'ack'\n , 'error'\n , 'noop'\n ];\n\n /**\n * Errors reasons.\n */\n\n var reasons = parser.reasons = [\n 'transport not supported'\n , 'client not handshaken'\n , 'unauthorized'\n ];\n\n /**\n * Errors advice.\n */\n\n var advice = parser.advice = [\n 'reconnect'\n ];\n\n /**\n * Shortcuts.\n */\n\n var JSON = io.JSON\n , indexOf = io.util.indexOf;\n\n /**\n * Encodes a packet.\n *\n * @api private\n */\n\n parser.encodePacket = function (packet) {\n var type = indexOf(packets, packet.type)\n , id = packet.id || ''\n , endpoint = packet.endpoint || ''\n , ack = packet.ack\n , data = null;\n\n switch (packet.type) {\n case 'error':\n var reason = packet.reason ? indexOf(reasons, packet.reason) : ''\n , adv = packet.advice ? indexOf(advice, packet.advice) : '';\n\n if (reason !== '' || adv !== '')\n data = reason + (adv !== '' ? ('+' + adv) : '');\n\n break;\n\n case 'message':\n if (packet.data !== '')\n data = packet.data;\n break;\n\n case 'event':\n var ev = { name: packet.name };\n\n if (packet.args && packet.args.length) {\n ev.args = packet.args;\n }\n\n data = JSON.stringify(ev);\n break;\n\n case 'json':\n data = JSON.stringify(packet.data);\n break;\n\n case 'connect':\n if (packet.qs)\n data = packet.qs;\n break;\n\n case 'ack':\n data = packet.ackId\n + (packet.args && packet.args.length\n ? '+' + JSON.stringify(packet.args) : '');\n break;\n }\n\n // construct packet with required fragments\n var encoded = [\n type\n , id + (ack == 'data' ? '+' : '')\n , endpoint\n ];\n\n // data fragment is optional\n if (data !== null && data !== undefined)\n encoded.push(data);\n\n return encoded.join(':');\n };\n\n /**\n * Encodes multiple messages (payload).\n *\n * @param {Array} messages\n * @api private\n */\n\n parser.encodePayload = function (packets) {\n var decoded = '';\n\n if (packets.length == 1)\n return packets[0];\n\n for (var i = 0, l = packets.length; i < l; i++) {\n var packet = packets[i];\n decoded += '\\ufffd' + packet.length + '\\ufffd' + packets[i];\n }\n\n return decoded;\n };\n\n /**\n * Decodes a packet\n *\n * @api private\n */\n\n var regexp = /([^:]+):([0-9]+)?(\\+)?:([^:]+)?:?([\\s\\S]*)?/;\n\n parser.decodePacket = function (data) {\n var pieces = data.match(regexp);\n\n if (!pieces) return {};\n\n var id = pieces[2] || ''\n , data = pieces[5] || ''\n , packet = {\n type: packets[pieces[1]]\n , endpoint: pieces[4] || ''\n };\n\n // whether we need to acknowledge the packet\n if (id) {\n packet.id = id;\n if (pieces[3])\n packet.ack = 'data';\n else\n packet.ack = true;\n }\n\n // handle different packet types\n switch (packet.type) {\n case 'error':\n var pieces = data.split('+');\n packet.reason = reasons[pieces[0]] || '';\n packet.advice = advice[pieces[1]] || '';\n break;\n\n case 'message':\n packet.data = data || '';\n break;\n\n case 'event':\n try {\n var opts = JSON.parse(data);\n packet.name = opts.name;\n packet.args = opts.args;\n } catch (e) { }\n\n packet.args = packet.args || [];\n break;\n\n case 'json':\n try {\n packet.data = JSON.parse(data);\n } catch (e) { }\n break;\n\n case 'connect':\n packet.qs = data || '';\n break;\n\n case 'ack':\n var pieces = data.match(/^([0-9]+)(\\+)?(.*)/);\n if (pieces) {\n packet.ackId = pieces[1];\n packet.args = [];\n\n if (pieces[3]) {\n try {\n packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];\n } catch (e) { }\n }\n }\n break;\n\n case 'disconnect':\n case 'heartbeat':\n break;\n };\n\n return packet;\n };\n\n /**\n * Decodes data payload. Detects multiple messages\n *\n * @return {Array} messages\n * @api public\n */\n\n parser.decodePayload = function (data) {\n // IE doesn't like data[i] for unicode chars, charAt works fine\n if (data.charAt(0) == '\\ufffd') {\n var ret = [];\n\n for (var i = 1, length = ''; i < data.length; i++) {\n if (data.charAt(i) == '\\ufffd') {\n ret.push(parser.decodePacket(data.substr(i + 1).substr(0, length)));\n i += Number(length) + 1;\n length = '';\n } else {\n length += data.charAt(i);\n }\n }\n\n return ret;\n } else {\n return [parser.decodePacket(data)];\n }\n };\n\n})(\n 'undefined' != typeof io ? io : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n);\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io) {\n\n /**\n * Expose constructor.\n */\n\n exports.Transport = Transport;\n\n /**\n * This is the transport template for all supported transport methods.\n *\n * @constructor\n * @api public\n */\n\n function Transport (socket, sessid) {\n this.socket = socket;\n this.sessid = sessid;\n };\n\n /**\n * Apply EventEmitter mixin.\n */\n\n io.util.mixin(Transport, io.EventEmitter);\n\n\n /**\n * Indicates whether heartbeats is enabled for this transport\n *\n * @api private\n */\n\n Transport.prototype.heartbeats = function () {\n return true;\n };\n\n /**\n * Handles the response from the server. When a new response is received\n * it will automatically update the timeout, decode the message and\n * forwards the response to the onMessage function for further processing.\n *\n * @param {String} data Response from the server.\n * @api private\n */\n\n Transport.prototype.onData = function (data) {\n this.clearCloseTimeout();\n\n // If the connection in currently open (or in a reopening state) reset the close\n // timeout since we have just received data. This check is necessary so\n // that we don't reset the timeout on an explicitly disconnected connection.\n if (this.socket.connected || this.socket.connecting || this.socket.reconnecting) {\n this.setCloseTimeout();\n }\n\n if (data !== '') {\n // todo: we should only do decodePayload for xhr transports\n var msgs = io.parser.decodePayload(data);\n\n if (msgs && msgs.length) {\n for (var i = 0, l = msgs.length; i < l; i++) {\n this.onPacket(msgs[i]);\n }\n }\n }\n\n return this;\n };\n\n /**\n * Handles packets.\n *\n * @api private\n */\n\n Transport.prototype.onPacket = function (packet) {\n this.socket.setHeartbeatTimeout();\n\n if (packet.type == 'heartbeat') {\n return this.onHeartbeat();\n }\n\n if (packet.type == 'connect' && packet.endpoint == '') {\n this.onConnect();\n }\n\n if (packet.type == 'error' && packet.advice == 'reconnect') {\n this.isOpen = false;\n }\n\n this.socket.onPacket(packet);\n\n return this;\n };\n\n /**\n * Sets close timeout\n *\n * @api private\n */\n\n Transport.prototype.setCloseTimeout = function () {\n if (!this.closeTimeout) {\n var self = this;\n\n this.closeTimeout = setTimeout(function () {\n self.onDisconnect();\n }, this.socket.closeTimeout);\n }\n };\n\n /**\n * Called when transport disconnects.\n *\n * @api private\n */\n\n Transport.prototype.onDisconnect = function () {\n if (this.isOpen) this.close();\n this.clearTimeouts();\n this.socket.onDisconnect();\n return this;\n };\n\n /**\n * Called when transport connects\n *\n * @api private\n */\n\n Transport.prototype.onConnect = function () {\n this.socket.onConnect();\n return this;\n };\n\n /**\n * Clears close timeout\n *\n * @api private\n */\n\n Transport.prototype.clearCloseTimeout = function () {\n if (this.closeTimeout) {\n clearTimeout(this.closeTimeout);\n this.closeTimeout = null;\n }\n };\n\n /**\n * Clear timeouts\n *\n * @api private\n */\n\n Transport.prototype.clearTimeouts = function () {\n this.clearCloseTimeout();\n\n if (this.reopenTimeout) {\n clearTimeout(this.reopenTimeout);\n }\n };\n\n /**\n * Sends a packet\n *\n * @param {Object} packet object.\n * @api private\n */\n\n Transport.prototype.packet = function (packet) {\n this.send(io.parser.encodePacket(packet));\n };\n\n /**\n * Send the received heartbeat message back to server. So the server\n * knows we are still connected.\n *\n * @param {String} heartbeat Heartbeat response from the server.\n * @api private\n */\n\n Transport.prototype.onHeartbeat = function (heartbeat) {\n this.packet({ type: 'heartbeat' });\n };\n\n /**\n * Called when the transport opens.\n *\n * @api private\n */\n\n Transport.prototype.onOpen = function () {\n this.isOpen = true;\n this.clearCloseTimeout();\n this.socket.onOpen();\n };\n\n /**\n * Notifies the base when the connection with the Socket.IO server\n * has been disconnected.\n *\n * @api private\n */\n\n Transport.prototype.onClose = function () {\n var self = this;\n\n /* FIXME: reopen delay causing a infinit loop\n this.reopenTimeout = setTimeout(function () {\n self.open();\n }, this.socket.options['reopen delay']);*/\n\n this.isOpen = false;\n this.socket.onClose();\n this.onDisconnect();\n };\n\n /**\n * Generates a connection url based on the Socket.IO URL Protocol.\n * See <https://github.com/learnboost/socket.io-node/> for more details.\n *\n * @returns {String} Connection url\n * @api private\n */\n\n Transport.prototype.prepareUrl = function () {\n var options = this.socket.options;\n\n return this.scheme() + '://'\n + options.host + ':' + options.port + '/'\n + options.resource + '/' + io.protocol\n + '/' + this.name + '/' + this.sessid;\n };\n\n /**\n * Checks if the transport is ready to start a connection.\n *\n * @param {Socket} socket The socket instance that needs a transport\n * @param {Function} fn The callback\n * @api private\n */\n\n Transport.prototype.ready = function (socket, fn) {\n fn.call(this);\n };\n})(\n 'undefined' != typeof io ? io : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n);\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io, global) {\n\n /**\n * Expose constructor.\n */\n\n exports.Socket = Socket;\n\n /**\n * Create a new `Socket.IO client` which can establish a persistent\n * connection with a Socket.IO enabled server.\n *\n * @api public\n */\n\n function Socket (options) {\n this.options = {\n port: 80\n , secure: false\n , document: 'document' in global ? document : false\n , resource: 'socket.io'\n , transports: io.transports\n , 'connect timeout': 10000\n , 'try multiple transports': true\n , 'reconnect': true\n , 'reconnection delay': 500\n , 'reconnection limit': Infinity\n , 'reopen delay': 3000\n , 'max reconnection attempts': 10\n , 'sync disconnect on unload': false\n , 'auto connect': true\n , 'flash policy port': 10843\n , 'manualFlush': false\n };\n\n io.util.merge(this.options, options);\n\n this.connected = false;\n this.open = false;\n this.connecting = false;\n this.reconnecting = false;\n this.namespaces = {};\n this.buffer = [];\n this.doBuffer = false;\n\n if (this.options['sync disconnect on unload'] &&\n (!this.isXDomain() || io.util.ua.hasCORS)) {\n var self = this;\n io.util.on(global, 'beforeunload', function () {\n self.disconnectSync();\n }, false);\n }\n\n if (this.options['auto connect']) {\n this.connect();\n }\n};\n\n /**\n * Apply EventEmitter mixin.\n */\n\n io.util.mixin(Socket, io.EventEmitter);\n\n /**\n * Returns a namespace listener/emitter for this socket\n *\n * @api public\n */\n\n Socket.prototype.of = function (name) {\n if (!this.namespaces[name]) {\n this.namespaces[name] = new io.SocketNamespace(this, name);\n\n if (name !== '') {\n this.namespaces[name].packet({ type: 'connect' });\n }\n }\n\n return this.namespaces[name];\n };\n\n /**\n * Emits the given event to the Socket and all namespaces\n *\n * @api private\n */\n\n Socket.prototype.publish = function () {\n this.emit.apply(this, arguments);\n\n var nsp;\n\n for (var i in this.namespaces) {\n if (this.namespaces.hasOwnProperty(i)) {\n nsp = this.of(i);\n nsp.$emit.apply(nsp, arguments);\n }\n }\n };\n\n /**\n * Performs the handshake\n *\n * @api private\n */\n\n function empty () { };\n\n Socket.prototype.handshake = function (fn) {\n var self = this\n , options = this.options;\n\n function complete (data) {\n if (data instanceof Error) {\n self.connecting = false;\n self.onError(data.message);\n } else {\n fn.apply(null, data.split(':'));\n }\n };\n\n var url = [\n 'http' + (options.secure ? 's' : '') + ':/'\n , options.host + ':' + options.port\n , options.resource\n , io.protocol\n , io.util.query(this.options.query, 't=' + +new Date)\n ].join('/');\n\n if (this.isXDomain() && !io.util.ua.hasCORS) {\n var insertAt = document.getElementsByTagName('script')[0]\n , script = document.createElement('script');\n\n script.src = url + '&jsonp=' + io.j.length;\n insertAt.parentNode.insertBefore(script, insertAt);\n\n io.j.push(function (data) {\n complete(data);\n script.parentNode.removeChild(script);\n });\n } else {\n var xhr = io.util.request();\n\n xhr.open('GET', url, true);\n if (this.isXDomain()) {\n xhr.withCredentials = true;\n }\n xhr.onreadystatechange = function () {\n if (xhr.readyState == 4) {\n xhr.onreadystatechange = empty;\n\n if (xhr.status == 200) {\n complete(xhr.responseText);\n } else if (xhr.status == 403) {\n self.onError(xhr.responseText);\n } else {\n self.connecting = false; \n !self.reconnecting && self.onError(xhr.responseText);\n }\n }\n };\n xhr.send(null);\n }\n };\n\n /**\n * Find an available transport based on the options supplied in the constructor.\n *\n * @api private\n */\n\n Socket.prototype.getTransport = function (override) {\n var transports = override || this.transports, match;\n\n for (var i = 0, transport; transport = transports[i]; i++) {\n if (io.Transport[transport]\n && io.Transport[transport].check(this)\n && (!this.isXDomain() || io.Transport[transport].xdomainCheck(this))) {\n return new io.Transport[transport](this, this.sessionid);\n }\n }\n\n return null;\n };\n\n /**\n * Connects to the server.\n *\n * @param {Function} [fn] Callback.\n * @returns {io.Socket}\n * @api public\n */\n\n Socket.prototype.connect = function (fn) {\n if (this.connecting) {\n return this;\n }\n\n var self = this;\n self.connecting = true;\n \n this.handshake(function (sid, heartbeat, close, transports) {\n self.sessionid = sid;\n self.closeTimeout = close * 1000;\n self.heartbeatTimeout = heartbeat * 1000;\n if(!self.transports)\n self.transports = self.origTransports = (transports ? io.util.intersect(\n transports.split(',')\n , self.options.transports\n ) : self.options.transports);\n\n self.setHeartbeatTimeout();\n\n function connect (transports){\n if (self.transport) self.transport.clearTimeouts();\n\n self.transport = self.getTransport(transports);\n if (!self.transport) return self.publish('connect_failed');\n\n // once the transport is ready\n self.transport.ready(self, function () {\n self.connecting = true;\n self.publish('connecting', self.transport.name);\n self.transport.open();\n\n if (self.options['connect timeout']) {\n self.connectTimeoutTimer = setTimeout(function () {\n if (!self.connected) {\n self.connecting = false;\n\n if (self.options['try multiple transports']) {\n var remaining = self.transports;\n\n while (remaining.length > 0 && remaining.splice(0,1)[0] !=\n self.transport.name) {}\n\n if (remaining.length){\n connect(remaining);\n } else {\n self.publish('connect_failed');\n }\n }\n }\n }, self.options['connect timeout']);\n }\n });\n }\n\n connect(self.transports);\n\n self.once('connect', function (){\n clearTimeout(self.connectTimeoutTimer);\n\n fn && typeof fn == 'function' && fn();\n });\n });\n\n return this;\n };\n\n /**\n * Clears and sets a new heartbeat timeout using the value given by the\n * server during the handshake.\n *\n * @api private\n */\n\n Socket.prototype.setHeartbeatTimeout = function () {\n clearTimeout(this.heartbeatTimeoutTimer);\n if(this.transport && !this.transport.heartbeats()) return;\n\n var self = this;\n this.heartbeatTimeoutTimer = setTimeout(function () {\n self.transport.onClose();\n }, this.heartbeatTimeout);\n };\n\n /**\n * Sends a message.\n *\n * @param {Object} data packet.\n * @returns {io.Socket}\n * @api public\n */\n\n Socket.prototype.packet = function (data) {\n if (this.connected && !this.doBuffer) {\n this.transport.packet(data);\n } else {\n this.buffer.push(data);\n }\n\n return this;\n };\n\n /**\n * Sets buffer state\n *\n * @api private\n */\n\n Socket.prototype.setBuffer = function (v) {\n this.doBuffer = v;\n\n if (!v && this.connected && this.buffer.length) {\n if (!this.options['manualFlush']) {\n this.flushBuffer();\n }\n }\n };\n\n /**\n * Flushes the buffer data over the wire.\n * To be invoked manually when 'manualFlush' is set to true.\n *\n * @api public\n */\n\n Socket.prototype.flushBuffer = function() {\n this.transport.payload(this.buffer);\n this.buffer = [];\n };\n \n\n /**\n * Disconnect the established connect.\n *\n * @returns {io.Socket}\n * @api public\n */\n\n Socket.prototype.disconnect = function () {\n if (this.connected || this.connecting) {\n if (this.open) {\n this.of('').packet({ type: 'disconnect' });\n }\n\n // handle disconnection immediately\n this.onDisconnect('booted');\n }\n\n return this;\n };\n\n /**\n * Disconnects the socket with a sync XHR.\n *\n * @api private\n */\n\n Socket.prototype.disconnectSync = function () {\n // ensure disconnection\n var xhr = io.util.request();\n var uri = [\n 'http' + (this.options.secure ? 's' : '') + ':/'\n , this.options.host + ':' + this.options.port\n , this.options.resource\n , io.protocol\n , ''\n , this.sessionid\n ].join('/') + '/?disconnect=1';\n\n xhr.open('GET', uri, false);\n xhr.send(null);\n\n // handle disconnection immediately\n this.onDisconnect('booted');\n };\n\n /**\n * Check if we need to use cross domain enabled transports. Cross domain would\n * be a different port or different domain name.\n *\n * @returns {Boolean}\n * @api private\n */\n\n Socket.prototype.isXDomain = function () {\n\n var port = global.location.port ||\n ('https:' == global.location.protocol ? 443 : 80);\n\n return this.options.host !== global.location.hostname \n || this.options.port != port;\n };\n\n /**\n * Called upon handshake.\n *\n * @api private\n */\n\n Socket.prototype.onConnect = function () {\n if (!this.connected) {\n this.connected = true;\n this.connecting = false;\n if (!this.doBuffer) {\n // make sure to flush the buffer\n this.setBuffer(false);\n }\n this.emit('connect');\n }\n };\n\n /**\n * Called when the transport opens\n *\n * @api private\n */\n\n Socket.prototype.onOpen = function () {\n this.open = true;\n };\n\n /**\n * Called when the transport closes.\n *\n * @api private\n */\n\n Socket.prototype.onClose = function () {\n this.open = false;\n clearTimeout(this.heartbeatTimeoutTimer);\n };\n\n /**\n * Called when the transport first opens a connection\n *\n * @param text\n */\n\n Socket.prototype.onPacket = function (packet) {\n this.of(packet.endpoint).onPacket(packet);\n };\n\n /**\n * Handles an error.\n *\n * @api private\n */\n\n Socket.prototype.onError = function (err) {\n if (err && err.advice) {\n if (err.advice === 'reconnect' && (this.connected || this.connecting)) {\n this.disconnect();\n if (this.options.reconnect) {\n this.reconnect();\n }\n }\n }\n\n this.publish('error', err && err.reason ? err.reason : err);\n };\n\n /**\n * Called when the transport disconnects.\n *\n * @api private\n */\n\n Socket.prototype.onDisconnect = function (reason) {\n var wasConnected = this.connected\n , wasConnecting = this.connecting;\n\n this.connected = false;\n this.connecting = false;\n this.open = false;\n\n if (wasConnected || wasConnecting) {\n this.transport.close();\n this.transport.clearTimeouts();\n if (wasConnected) {\n this.publish('disconnect', reason);\n\n if ('booted' != reason && this.options.reconnect && !this.reconnecting) {\n this.reconnect();\n }\n }\n }\n };\n\n /**\n * Called upon reconnection.\n *\n * @api private\n */\n\n Socket.prototype.reconnect = function () {\n this.reconnecting = true;\n this.reconnectionAttempts = 0;\n this.reconnectionDelay = this.options['reconnection delay'];\n\n var self = this\n , maxAttempts = this.options['max reconnection attempts']\n , tryMultiple = this.options['try multiple transports']\n , limit = this.options['reconnection limit'];\n\n function reset () {\n if (self.connected) {\n for (var i in self.namespaces) {\n if (self.namespaces.hasOwnProperty(i) && '' !== i) {\n self.namespaces[i].packet({ type: 'connect' });\n }\n }\n self.publish('reconnect', self.transport.name, self.reconnectionAttempts);\n }\n\n clearTimeout(self.reconnectionTimer);\n\n self.removeListener('connect_failed', maybeReconnect);\n self.removeListener('connect', maybeReconnect);\n\n self.reconnecting = false;\n\n delete self.reconnectionAttempts;\n delete self.reconnectionDelay;\n delete self.reconnectionTimer;\n delete self.redoTransports;\n\n self.options['try multiple transports'] = tryMultiple;\n };\n\n function maybeReconnect () {\n if (!self.reconnecting) {\n return;\n }\n\n if (self.connected) {\n return reset();\n };\n\n if (self.connecting && self.reconnecting) {\n return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);\n }\n\n if (self.reconnectionAttempts++ >= maxAttempts) {\n if (!self.redoTransports) {\n self.on('connect_failed', maybeReconnect);\n self.options['try multiple transports'] = true;\n self.transports = self.origTransports;\n self.transport = self.getTransport();\n self.redoTransports = true;\n self.connect();\n } else {\n self.publish('reconnect_failed');\n reset();\n }\n } else {\n if (self.reconnectionDelay < limit) {\n self.reconnectionDelay *= 2; // exponential back off\n }\n\n self.connect();\n self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);\n self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);\n }\n };\n\n this.options['try multiple transports'] = false;\n this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);\n\n this.on('connect', maybeReconnect);\n };\n\n})(\n 'undefined' != typeof io ? io : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n , this\n);\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io) {\n\n /**\n * Expose constructor.\n */\n\n exports.SocketNamespace = SocketNamespace;\n\n /**\n * Socket namespace constructor.\n *\n * @constructor\n * @api public\n */\n\n function SocketNamespace (socket, name) {\n this.socket = socket;\n this.name = name || '';\n this.flags = {};\n this.json = new Flag(this, 'json');\n this.ackPackets = 0;\n this.acks = {};\n };\n\n /**\n * Apply EventEmitter mixin.\n */\n\n io.util.mixin(SocketNamespace, io.EventEmitter);\n\n /**\n * Copies emit since we override it\n *\n * @api private\n */\n\n SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;\n\n /**\n * Creates a new namespace, by proxying the request to the socket. This\n * allows us to use the synax as we do on the server.\n *\n * @api public\n */\n\n SocketNamespace.prototype.of = function () {\n return this.socket.of.apply(this.socket, arguments);\n };\n\n /**\n * Sends a packet.\n *\n * @api private\n */\n\n SocketNamespace.prototype.packet = function (packet) {\n packet.endpoint = this.name;\n this.socket.packet(packet);\n this.flags = {};\n return this;\n };\n\n /**\n * Sends a message\n *\n * @api public\n */\n\n SocketNamespace.prototype.send = function (data, fn) {\n var packet = {\n type: this.flags.json ? 'json' : 'message'\n , data: data\n };\n\n if ('function' == typeof fn) {\n packet.id = ++this.ackPackets;\n packet.ack = true;\n this.acks[packet.id] = fn;\n }\n\n return this.packet(packet);\n };\n\n /**\n * Emits an event\n *\n * @api public\n */\n \n SocketNamespace.prototype.emit = function (name) {\n var args = Array.prototype.slice.call(arguments, 1)\n , lastArg = args[args.length - 1]\n , packet = {\n type: 'event'\n , name: name\n };\n\n if ('function' == typeof lastArg) {\n packet.id = ++this.ackPackets;\n packet.ack = 'data';\n this.acks[packet.id] = lastArg;\n args = args.slice(0, args.length - 1);\n }\n\n packet.args = args;\n\n return this.packet(packet);\n };\n\n /**\n * Disconnects the namespace\n *\n * @api private\n */\n\n SocketNamespace.prototype.disconnect = function () {\n if (this.name === '') {\n this.socket.disconnect();\n } else {\n this.packet({ type: 'disconnect' });\n this.$emit('disconnect');\n }\n\n return this;\n };\n\n /**\n * Handles a packet\n *\n * @api private\n */\n\n SocketNamespace.prototype.onPacket = function (packet) {\n var self = this;\n\n function ack () {\n self.packet({\n type: 'ack'\n , args: io.util.toArray(arguments)\n , ackId: packet.id\n });\n };\n\n switch (packet.type) {\n case 'connect':\n this.$emit('connect');\n break;\n\n case 'disconnect':\n if (this.name === '') {\n this.socket.onDisconnect(packet.reason || 'booted');\n } else {\n this.$emit('disconnect', packet.reason);\n }\n break;\n\n case 'message':\n case 'json':\n var params = ['message', packet.data];\n\n if (packet.ack == 'data') {\n params.push(ack);\n } else if (packet.ack) {\n this.packet({ type: 'ack', ackId: packet.id });\n }\n\n this.$emit.apply(this, params);\n break;\n\n case 'event':\n var params = [packet.name].concat(packet.args);\n\n if (packet.ack == 'data')\n params.push(ack);\n\n this.$emit.apply(this, params);\n break;\n\n case 'ack':\n if (this.acks[packet.ackId]) {\n this.acks[packet.ackId].apply(this, packet.args);\n delete this.acks[packet.ackId];\n }\n break;\n\n case 'error':\n if (packet.advice){\n this.socket.onError(packet);\n } else {\n if (packet.reason == 'unauthorized') {\n this.$emit('connect_failed', packet.reason);\n } else {\n this.$emit('error', packet.reason);\n }\n }\n break;\n }\n };\n\n /**\n * Flag interface.\n *\n * @api private\n */\n\n function Flag (nsp, name) {\n this.namespace = nsp;\n this.name = name;\n };\n\n /**\n * Send a message\n *\n * @api public\n */\n\n Flag.prototype.send = function () {\n this.namespace.flags[this.name] = true;\n this.namespace.send.apply(this.namespace, arguments);\n };\n\n /**\n * Emit an event\n *\n * @api public\n */\n\n Flag.prototype.emit = function () {\n this.namespace.flags[this.name] = true;\n this.namespace.emit.apply(this.namespace, arguments);\n };\n\n})(\n 'undefined' != typeof io ? io : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n);\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io, global) {\n\n /**\n * Expose constructor.\n */\n\n exports.websocket = WS;\n\n /**\n * The WebSocket transport uses the HTML5 WebSocket API to establish an\n * persistent connection with the Socket.IO server. This transport will also\n * be inherited by the FlashSocket fallback as it provides a API compatible\n * polyfill for the WebSockets.\n *\n * @constructor\n * @extends {io.Transport}\n * @api public\n */\n\n function WS (socket) {\n io.Transport.apply(this, arguments);\n };\n\n /**\n * Inherits from Transport.\n */\n\n io.util.inherit(WS, io.Transport);\n\n /**\n * Transport name\n *\n * @api public\n */\n\n WS.prototype.name = 'websocket';\n\n /**\n * Initializes a new `WebSocket` connection with the Socket.IO server. We attach\n * all the appropriate listeners to handle the responses from the server.\n *\n * @returns {Transport}\n * @api public\n */\n\n WS.prototype.open = function () {\n var query = io.util.query(this.socket.options.query)\n , self = this\n , Socket\n\n\n if (!Socket) {\n Socket = global.MozWebSocket || global.WebSocket;\n }\n\n this.websocket = new Socket(this.prepareUrl() + query);\n\n this.websocket.onopen = function () {\n self.onOpen();\n self.socket.setBuffer(false);\n };\n this.websocket.onmessage = function (ev) {\n self.onData(ev.data);\n };\n this.websocket.onclose = function () {\n self.onClose();\n self.socket.setBuffer(true);\n };\n this.websocket.onerror = function (e) {\n self.onError(e);\n };\n\n return this;\n };\n\n /**\n * Send a message to the Socket.IO server. The message will automatically be\n * encoded in the correct message format.\n *\n * @returns {Transport}\n * @api public\n */\n\n // Do to a bug in the current IDevices browser, we need to wrap the send in a \n // setTimeout, when they resume from sleeping the browser will crash if \n // we don't allow the browser time to detect the socket has been closed\n if (io.util.ua.iDevice) {\n WS.prototype.send = function (data) {\n var self = this;\n setTimeout(function() {\n self.websocket.send(data);\n },0);\n return this;\n };\n } else {\n WS.prototype.send = function (data) {\n this.websocket.send(data);\n return this;\n };\n }\n\n /**\n * Payload\n *\n * @api private\n */\n\n WS.prototype.payload = function (arr) {\n for (var i = 0, l = arr.length; i < l; i++) {\n this.packet(arr[i]);\n }\n return this;\n };\n\n /**\n * Disconnect the established `WebSocket` connection.\n *\n * @returns {Transport}\n * @api public\n */\n\n WS.prototype.close = function () {\n this.websocket.close();\n return this;\n };\n\n /**\n * Handle the errors that `WebSocket` might be giving when we\n * are attempting to connect or send messages.\n *\n * @param {Error} e The error.\n * @api private\n */\n\n WS.prototype.onError = function (e) {\n this.socket.onError(e);\n };\n\n /**\n * Returns the appropriate scheme for the URI generation.\n *\n * @api private\n */\n WS.prototype.scheme = function () {\n return this.socket.options.secure ? 'wss' : 'ws';\n };\n\n /**\n * Checks if the browser has support for native `WebSockets` and that\n * it's not the polyfill created for the FlashSocket transport.\n *\n * @return {Boolean}\n * @api public\n */\n\n WS.check = function () {\n return ('WebSocket' in global && !('__addTask' in WebSocket))\n || 'MozWebSocket' in global;\n };\n\n /**\n * Check if the `WebSocket` transport support cross domain communications.\n *\n * @returns {Boolean}\n * @api public\n */\n\n WS.xdomainCheck = function () {\n return true;\n };\n\n /**\n * Add the transport to your public io.transports array.\n *\n * @api private\n */\n\n io.transports.push('websocket');\n\n})(\n 'undefined' != typeof io ? io.Transport : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n , this\n);\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io) {\n\n /**\n * Expose constructor.\n */\n\n exports.flashsocket = Flashsocket;\n\n /**\n * The FlashSocket transport. This is a API wrapper for the HTML5 WebSocket\n * specification. It uses a .swf file to communicate with the server. If you want\n * to serve the .swf file from a other server than where the Socket.IO script is\n * coming from you need to use the insecure version of the .swf. More information\n * about this can be found on the github page.\n *\n * @constructor\n * @extends {io.Transport.websocket}\n * @api public\n */\n\n function Flashsocket () {\n io.Transport.websocket.apply(this, arguments);\n };\n\n /**\n * Inherits from Transport.\n */\n\n io.util.inherit(Flashsocket, io.Transport.websocket);\n\n /**\n * Transport name\n *\n * @api public\n */\n\n Flashsocket.prototype.name = 'flashsocket';\n\n /**\n * Disconnect the established `FlashSocket` connection. This is done by adding a \n * new task to the FlashSocket. The rest will be handled off by the `WebSocket` \n * transport.\n *\n * @returns {Transport}\n * @api public\n */\n\n Flashsocket.prototype.open = function () {\n var self = this\n , args = arguments;\n\n WebSocket.__addTask(function () {\n io.Transport.websocket.prototype.open.apply(self, args);\n });\n return this;\n };\n \n /**\n * Sends a message to the Socket.IO server. This is done by adding a new\n * task to the FlashSocket. The rest will be handled off by the `WebSocket` \n * transport.\n *\n * @returns {Transport}\n * @api public\n */\n\n Flashsocket.prototype.send = function () {\n var self = this, args = arguments;\n WebSocket.__addTask(function () {\n io.Transport.websocket.prototype.send.apply(self, args);\n });\n return this;\n };\n\n /**\n * Disconnects the established `FlashSocket` connection.\n *\n * @returns {Transport}\n * @api public\n */\n\n Flashsocket.prototype.close = function () {\n WebSocket.__tasks.length = 0;\n io.Transport.websocket.prototype.close.call(this);\n return this;\n };\n\n /**\n * The WebSocket fall back needs to append the flash container to the body\n * element, so we need to make sure we have access to it. Or defer the call\n * until we are sure there is a body element.\n *\n * @param {Socket} socket The socket instance that needs a transport\n * @param {Function} fn The callback\n * @api private\n */\n\n Flashsocket.prototype.ready = function (socket, fn) {\n function init () {\n var options = socket.options\n , port = options['flash policy port']\n , path = [\n 'http' + (options.secure ? 's' : '') + ':/'\n , options.host + ':' + options.port\n , options.resource\n , 'static/flashsocket'\n , 'WebSocketMain' + (socket.isXDomain() ? 'Insecure' : '') + '.swf'\n ];\n\n // Only start downloading the swf file when the checked that this browser\n // actually supports it\n if (!Flashsocket.loaded) {\n if (typeof WEB_SOCKET_SWF_LOCATION === 'undefined') {\n // Set the correct file based on the XDomain settings\n WEB_SOCKET_SWF_LOCATION = path.join('/');\n }\n\n if (port !== 843) {\n WebSocket.loadFlashPolicyFile('xmlsocket://' + options.host + ':' + port);\n }\n\n WebSocket.__initialize();\n Flashsocket.loaded = true;\n }\n\n fn.call(self);\n }\n\n var self = this;\n if (document.body) return init();\n\n io.util.load(init);\n };\n\n /**\n * Check if the FlashSocket transport is supported as it requires that the Adobe\n * Flash Player plug-in version `10.0.0` or greater is installed. And also check if\n * the polyfill is correctly loaded.\n *\n * @returns {Boolean}\n * @api public\n */\n\n Flashsocket.check = function () {\n if (\n typeof WebSocket == 'undefined'\n || !('__initialize' in WebSocket) || !swfobject\n ) return false;\n\n return swfobject.getFlashPlayerVersion().major >= 10;\n };\n\n /**\n * Check if the FlashSocket transport can be used as cross domain / cross origin \n * transport. Because we can't see which type (secure or insecure) of .swf is used\n * we will just return true.\n *\n * @returns {Boolean}\n * @api public\n */\n\n Flashsocket.xdomainCheck = function () {\n return true;\n };\n\n /**\n * Disable AUTO_INITIALIZATION\n */\n\n if (typeof window != 'undefined') {\n WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;\n }\n\n /**\n * Add the transport to your public io.transports array.\n *\n * @api private\n */\n\n io.transports.push('flashsocket');\n})(\n 'undefined' != typeof io ? io.Transport : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n);\n/*\tSWFObject v2.2 <http://code.google.com/p/swfobject/> \n\tis released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \n*/\nif ('undefined' != typeof window) {\nvar swfobject=function(){var D=\"undefined\",r=\"object\",S=\"Shockwave Flash\",W=\"ShockwaveFlash.ShockwaveFlash\",q=\"application/x-shockwave-flash\",R=\"SWFObjectExprInst\",x=\"onreadystatechange\",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\\/(\\d+(\\.\\d+)?).*$/,\"$1\")):false,X=!+\"\\v1\",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\\s+(\\S+\\s+\\S+$)/,\"$1\");ag[0]=parseInt(ab.replace(/^(.*)\\..*$/,\"$1\"),10);ag[1]=parseInt(ab.replace(/^.*\\.(.*)\\s.*$/,\"$1\"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,\"$1\"),10):0}}else{if(typeof O[(['Active'].concat('Object').join('X'))]!=D){try{var ad=new window[(['Active'].concat('Object').join('X'))](W);if(ad){ab=ad.GetVariable(\"$version\");if(ab){X=true;ab=ab.split(\" \")[1].split(\",\");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState==\"complete\")||(typeof j.readyState==D&&(j.getElementsByTagName(\"body\")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener(\"DOMContentLoaded\",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState==\"complete\"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll(\"left\")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName(\"body\")[0].appendChild(C(\"span\"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener(\"load\",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener(\"load\",Y,false)}else{if(typeof O.attachEvent!=D){i(O,\"onload\",Y)}else{if(typeof O.onload==\"function\"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName(\"body\")[0];var aa=C(r);aa.setAttribute(\"type\",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable(\"$version\");if(ab){ab=ab.split(\" \")[1].split(\",\");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute(\"width\")||\"0\";ai.height=ae.getAttribute(\"height\")||\"0\";if(ae.getAttribute(\"class\")){ai.styleclass=ae.getAttribute(\"class\")}if(ae.getAttribute(\"align\")){ai.align=ae.getAttribute(\"align\")}var ah={};var X=ae.getElementsByTagName(\"param\");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute(\"name\").toLowerCase()!=\"movie\"){ah[X[ad].getAttribute(\"name\")]=X[ad].getAttribute(\"value\")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName==\"OBJECT\"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F(\"6.0.65\")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName==\"OBJECT\"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width=\"310\"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height=\"137\"}j.title=j.title.slice(0,47)+\" - Flash Player Installation\";var ad=M.ie&&M.win?(['Active'].concat('').join('X')):\"PlugIn\",ac=\"MMredirectURL=\"+O.location.toString().replace(/&/g,\"%26\")+\"&MMplayerType=\"+ad+\"&MMdoctitle=\"+j.title;if(typeof ab.flashvars!=D){ab.flashvars+=\"&\"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C(\"div\");X+=\"SWFObjectNew\";Y.setAttribute(\"id\",X);ae.parentNode.insertBefore(Y,ae);ae.style.display=\"none\";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C(\"div\");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display=\"none\";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C(\"div\");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName==\"PARAM\")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah=\"\";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()==\"data\"){ag.movie=ai[ae]}else{if(ae.toLowerCase()==\"styleclass\"){ah+=' class=\"'+ai[ae]+'\"'}else{if(ae.toLowerCase()!=\"classid\"){ah+=\" \"+ae+'=\"'+ai[ae]+'\"'}}}}}var af=\"\";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name=\"'+ad+'\" value=\"'+ag[ad]+'\" />'}}aa.outerHTML='<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"'+ah+\">\"+af+\"</object>\";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute(\"type\",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()==\"styleclass\"){Z.setAttribute(\"class\",ai[ac])}else{if(ac.toLowerCase()!=\"classid\"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!=\"movie\"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C(\"param\");aa.setAttribute(\"name\",X);aa.setAttribute(\"value\",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName==\"OBJECT\"){if(M.ie&&M.win){X.style.display=\"none\";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]==\"function\"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(\".\");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName(\"head\")[0];if(!aa){return}var X=(ad&&typeof ad==\"string\")?ad:\"screen\";if(ab){n=null;G=null}if(!n||G!=X){var Z=C(\"style\");Z.setAttribute(\"type\",\"text/css\");Z.setAttribute(\"media\",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+\" {\"+Y+\"}\"))}}}function w(Z,X){if(!m){return}var Y=X?\"visible\":\"hidden\";if(J&&c(Z)){c(Z).style.visibility=Y}else{v(\"#\"+Z,\"visibility:\"+Y)}}function L(Y){var Z=/[\\\\\\\"<>\\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent(\"onunload\",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+=\"\";ag+=\"\";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+=\"&\"+ai+\"=\"+Z[ai]}else{am.flashvars=ai+\"=\"+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\\?/.test(Z)){Z=Z.split(\"?\")[1]}if(aa==null){return L(Z)}var Y=Z.split(\"&\");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf(\"=\"))==aa){return L(Y[X].substring((Y[X].indexOf(\"=\")+1)))}}}return\"\"},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display=\"block\"}}if(E){E(B)}}a=false}}}}();\n}\n// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>\n// License: New BSD License\n// Reference: http://dev.w3.org/html5/websockets/\n// Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol\n\n(function() {\n \n if ('undefined' == typeof window || window.WebSocket) return;\n\n var console = window.console;\n if (!console || !console.log || !console.error) {\n console = {log: function(){ }, error: function(){ }};\n }\n \n if (!swfobject.hasFlashPlayerVersion(\"10.0.0\")) {\n console.error(\"Flash Player >= 10.0.0 is required.\");\n return;\n }\n if (location.protocol == \"file:\") {\n console.error(\n \"WARNING: web-socket-js doesn't work in file:///... URL \" +\n \"unless you set Flash Security Settings properly. \" +\n \"Open the page via Web server i.e. http://...\");\n }\n\n /**\n * This class represents a faux web socket.\n * @param {string} url\n * @param {array or string} protocols\n * @param {string} proxyHost\n * @param {int} proxyPort\n * @param {string} headers\n */\n WebSocket = function(url, protocols, proxyHost, proxyPort, headers) {\n var self = this;\n self.__id = WebSocket.__nextId++;\n WebSocket.__instances[self.__id] = self;\n self.readyState = WebSocket.CONNECTING;\n self.bufferedAmount = 0;\n self.__events = {};\n if (!protocols) {\n protocols = [];\n } else if (typeof protocols == \"string\") {\n protocols = [protocols];\n }\n // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.\n // Otherwise, when onopen fires immediately, onopen is called before it is set.\n setTimeout(function() {\n WebSocket.__addTask(function() {\n WebSocket.__flash.create(\n self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null);\n });\n }, 0);\n };\n\n /**\n * Send data to the web socket.\n * @param {string} data The data to send to the socket.\n * @return {boolean} True for success, false for failure.\n */\n WebSocket.prototype.send = function(data) {\n if (this.readyState == WebSocket.CONNECTING) {\n throw \"INVALID_STATE_ERR: Web Socket connection has not been established\";\n }\n // We use encodeURIComponent() here, because FABridge doesn't work if\n // the argument includes some characters. We don't use escape() here\n // because of this:\n // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions\n // But it looks decodeURIComponent(encodeURIComponent(s)) doesn't\n // preserve all Unicode characters either e.g. \"\\uffff\" in Firefox.\n // Note by wtritch: Hopefully this will not be necessary using ExternalInterface. Will require\n // additional testing.\n var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data));\n if (result < 0) { // success\n return true;\n } else {\n this.bufferedAmount += result;\n return false;\n }\n };\n\n /**\n * Close this web socket gracefully.\n */\n WebSocket.prototype.close = function() {\n if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) {\n return;\n }\n this.readyState = WebSocket.CLOSING;\n WebSocket.__flash.close(this.__id);\n };\n\n /**\n * Implementation of {@link <a href=\"http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration\">DOM 2 EventTarget Interface</a>}\n *\n * @param {string} type\n * @param {function} listener\n * @param {boolean} useCapture\n * @return void\n */\n WebSocket.prototype.addEventListener = function(type, listener, useCapture) {\n if (!(type in this.__events)) {\n this.__events[type] = [];\n }\n this.__events[type].push(listener);\n };\n\n /**\n * Implementation of {@link <a href=\"http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration\">DOM 2 EventTarget Interface</a>}\n *\n * @param {string} type\n * @param {function} listener\n * @param {boolean} useCapture\n * @return void\n */\n WebSocket.prototype.removeEventListener = function(type, listener, useCapture) {\n if (!(type in this.__events)) return;\n var events = this.__events[type];\n for (var i = events.length - 1; i >= 0; --i) {\n if (events[i] === listener) {\n events.splice(i, 1);\n break;\n }\n }\n };\n\n /**\n * Implementation of {@link <a href=\"http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration\">DOM 2 EventTarget Interface</a>}\n *\n * @param {Event} event\n * @return void\n */\n WebSocket.prototype.dispatchEvent = function(event) {\n var events = this.__events[event.type] || [];\n for (var i = 0; i < events.length; ++i) {\n events[i](event);\n }\n var handler = this[\"on\" + event.type];\n if (handler) handler(event);\n };\n\n /**\n * Handles an event from Flash.\n * @param {Object} flashEvent\n */\n WebSocket.prototype.__handleEvent = function(flashEvent) {\n if (\"readyState\" in flashEvent) {\n this.readyState = flashEvent.readyState;\n }\n if (\"protocol\" in flashEvent) {\n this.protocol = flashEvent.protocol;\n }\n \n var jsEvent;\n if (flashEvent.type == \"open\" || flashEvent.type == \"error\") {\n jsEvent = this.__createSimpleEvent(flashEvent.type);\n } else if (flashEvent.type == \"close\") {\n // TODO implement jsEvent.wasClean\n jsEvent = this.__createSimpleEvent(\"close\");\n } else if (flashEvent.type == \"message\") {\n var data = decodeURIComponent(flashEvent.message);\n jsEvent = this.__createMessageEvent(\"message\", data);\n } else {\n throw \"unknown event type: \" + flashEvent.type;\n }\n \n this.dispatchEvent(jsEvent);\n };\n \n WebSocket.prototype.__createSimpleEvent = function(type) {\n if (document.createEvent && window.Event) {\n var event = document.createEvent(\"Event\");\n event.initEvent(type, false, false);\n return event;\n } else {\n return {type: type, bubbles: false, cancelable: false};\n }\n };\n \n WebSocket.prototype.__createMessageEvent = function(type, data) {\n if (document.createEvent && window.MessageEvent && !window.opera) {\n var event = document.createEvent(\"MessageEvent\");\n event.initMessageEvent(\"message\", false, false, data, null, null, window, null);\n return event;\n } else {\n // IE and Opera, the latter one truncates the data parameter after any 0x00 bytes.\n return {type: type, data: data, bubbles: false, cancelable: false};\n }\n };\n \n /**\n * Define the WebSocket readyState enumeration.\n */\n WebSocket.CONNECTING = 0;\n WebSocket.OPEN = 1;\n WebSocket.CLOSING = 2;\n WebSocket.CLOSED = 3;\n\n WebSocket.__flash = null;\n WebSocket.__instances = {};\n WebSocket.__tasks = [];\n WebSocket.__nextId = 0;\n \n /**\n * Load a new flash security policy file.\n * @param {string} url\n */\n WebSocket.loadFlashPolicyFile = function(url){\n WebSocket.__addTask(function() {\n WebSocket.__flash.loadManualPolicyFile(url);\n });\n };\n\n /**\n * Loads WebSocketMain.swf and creates WebSocketMain object in Flash.\n */\n WebSocket.__initialize = function() {\n if (WebSocket.__flash) return;\n \n if (WebSocket.__swfLocation) {\n // For backword compatibility.\n window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;\n }\n if (!window.WEB_SOCKET_SWF_LOCATION) {\n console.error(\"[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf\");\n return;\n }\n var container = document.createElement(\"div\");\n container.id = \"webSocketContainer\";\n // Hides Flash box. We cannot use display: none or visibility: hidden because it prevents\n // Flash from loading at least in IE. So we move it out of the screen at (-100, -100).\n // But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash\n // Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is\n // the best we can do as far as we know now.\n container.style.position = \"absolute\";\n if (WebSocket.__isFlashLite()) {\n container.style.left = \"0px\";\n container.style.top = \"0px\";\n } else {\n container.style.left = \"-100px\";\n container.style.top = \"-100px\";\n }\n var holder = document.createElement(\"div\");\n holder.id = \"webSocketFlash\";\n container.appendChild(holder);\n document.body.appendChild(container);\n // See this article for hasPriority:\n // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html\n swfobject.embedSWF(\n WEB_SOCKET_SWF_LOCATION,\n \"webSocketFlash\",\n \"1\" /* width */,\n \"1\" /* height */,\n \"10.0.0\" /* SWF version */,\n null,\n null,\n {hasPriority: true, swliveconnect : true, allowScriptAccess: \"always\"},\n null,\n function(e) {\n if (!e.success) {\n console.error(\"[WebSocket] swfobject.embedSWF failed\");\n }\n });\n };\n \n /**\n * Called by Flash to notify JS that it's fully loaded and ready\n * for communication.\n */\n WebSocket.__onFlashInitialized = function() {\n // We need to set a timeout here to avoid round-trip calls\n // to flash during the initialization process.\n setTimeout(function() {\n WebSocket.__flash = document.getElementById(\"webSocketFlash\");\n WebSocket.__flash.setCallerUrl(location.href);\n WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG);\n for (var i = 0; i < WebSocket.__tasks.length; ++i) {\n WebSocket.__tasks[i]();\n }\n WebSocket.__tasks = [];\n }, 0);\n };\n \n /**\n * Called by Flash to notify WebSockets events are fired.\n */\n WebSocket.__onFlashEvent = function() {\n setTimeout(function() {\n try {\n // Gets events using receiveEvents() instead of getting it from event object\n // of Flash event. This is to make sure to keep message order.\n // It seems sometimes Flash events don't arrive in the same order as they are sent.\n var events = WebSocket.__flash.receiveEvents();\n for (var i = 0; i < events.length; ++i) {\n WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]);\n }\n } catch (e) {\n console.error(e);\n }\n }, 0);\n return true;\n };\n \n // Called by Flash.\n WebSocket.__log = function(message) {\n console.log(decodeURIComponent(message));\n };\n \n // Called by Flash.\n WebSocket.__error = function(message) {\n console.error(decodeURIComponent(message));\n };\n \n WebSocket.__addTask = function(task) {\n if (WebSocket.__flash) {\n task();\n } else {\n WebSocket.__tasks.push(task);\n }\n };\n \n /**\n * Test if the browser is running flash lite.\n * @return {boolean} True if flash lite is running, false otherwise.\n */\n WebSocket.__isFlashLite = function() {\n if (!window.navigator || !window.navigator.mimeTypes) {\n return false;\n }\n var mimeType = window.navigator.mimeTypes[\"application/x-shockwave-flash\"];\n if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) {\n return false;\n }\n return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;\n };\n \n if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {\n if (window.addEventListener) {\n window.addEventListener(\"load\", function(){\n WebSocket.__initialize();\n }, false);\n } else {\n window.attachEvent(\"onload\", function(){\n WebSocket.__initialize();\n });\n }\n }\n \n})();\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io, global) {\n\n /**\n * Expose constructor.\n *\n * @api public\n */\n\n exports.XHR = XHR;\n\n /**\n * XHR constructor\n *\n * @costructor\n * @api public\n */\n\n function XHR (socket) {\n if (!socket) return;\n\n io.Transport.apply(this, arguments);\n this.sendBuffer = [];\n };\n\n /**\n * Inherits from Transport.\n */\n\n io.util.inherit(XHR, io.Transport);\n\n /**\n * Establish a connection\n *\n * @returns {Transport}\n * @api public\n */\n\n XHR.prototype.open = function () {\n this.socket.setBuffer(false);\n this.onOpen();\n this.get();\n\n // we need to make sure the request succeeds since we have no indication\n // whether the request opened or not until it succeeded.\n this.setCloseTimeout();\n\n return this;\n };\n\n /**\n * Check if we need to send data to the Socket.IO server, if we have data in our\n * buffer we encode it and forward it to the `post` method.\n *\n * @api private\n */\n\n XHR.prototype.payload = function (payload) {\n var msgs = [];\n\n for (var i = 0, l = payload.length; i < l; i++) {\n msgs.push(io.parser.encodePacket(payload[i]));\n }\n\n this.send(io.parser.encodePayload(msgs));\n };\n\n /**\n * Send data to the Socket.IO server.\n *\n * @param data The message\n * @returns {Transport}\n * @api public\n */\n\n XHR.prototype.send = function (data) {\n this.post(data);\n return this;\n };\n\n /**\n * Posts a encoded message to the Socket.IO server.\n *\n * @param {String} data A encoded message.\n * @api private\n */\n\n function empty () { };\n\n XHR.prototype.post = function (data) {\n var self = this;\n this.socket.setBuffer(true);\n\n function stateChange () {\n if (this.readyState == 4) {\n this.onreadystatechange = empty;\n self.posting = false;\n\n if (this.status == 200){\n self.socket.setBuffer(false);\n } else {\n self.onClose();\n }\n }\n }\n\n function onload () {\n this.onload = empty;\n self.socket.setBuffer(false);\n };\n\n this.sendXHR = this.request('POST');\n\n if (global.XDomainRequest && this.sendXHR instanceof XDomainRequest) {\n this.sendXHR.onload = this.sendXHR.onerror = onload;\n } else {\n this.sendXHR.onreadystatechange = stateChange;\n }\n\n this.sendXHR.send(data);\n };\n\n /**\n * Disconnects the established `XHR` connection.\n *\n * @returns {Transport}\n * @api public\n */\n\n XHR.prototype.close = function () {\n this.onClose();\n return this;\n };\n\n /**\n * Generates a configured XHR request\n *\n * @param {String} url The url that needs to be requested.\n * @param {String} method The method the request should use.\n * @returns {XMLHttpRequest}\n * @api private\n */\n\n XHR.prototype.request = function (method) {\n var req = io.util.request(this.socket.isXDomain())\n , query = io.util.query(this.socket.options.query, 't=' + +new Date);\n\n req.open(method || 'GET', this.prepareUrl() + query, true);\n\n if (method == 'POST') {\n try {\n if (req.setRequestHeader) {\n req.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');\n } else {\n // XDomainRequest\n req.contentType = 'text/plain';\n }\n } catch (e) {}\n }\n\n return req;\n };\n\n /**\n * Returns the scheme to use for the transport URLs.\n *\n * @api private\n */\n\n XHR.prototype.scheme = function () {\n return this.socket.options.secure ? 'https' : 'http';\n };\n\n /**\n * Check if the XHR transports are supported\n *\n * @param {Boolean} xdomain Check if we support cross domain requests.\n * @returns {Boolean}\n * @api public\n */\n\n XHR.check = function (socket, xdomain) {\n try {\n var request = io.util.request(xdomain),\n usesXDomReq = (global.XDomainRequest && request instanceof XDomainRequest),\n socketProtocol = (socket && socket.options && socket.options.secure ? 'https:' : 'http:'),\n isXProtocol = (global.location && socketProtocol != global.location.protocol);\n if (request && !(usesXDomReq && isXProtocol)) {\n return true;\n }\n } catch(e) {}\n\n return false;\n };\n\n /**\n * Check if the XHR transport supports cross domain requests.\n *\n * @returns {Boolean}\n * @api public\n */\n\n XHR.xdomainCheck = function (socket) {\n return XHR.check(socket, true);\n };\n\n})(\n 'undefined' != typeof io ? io.Transport : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n , this\n);\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io) {\n\n /**\n * Expose constructor.\n */\n\n exports.htmlfile = HTMLFile;\n\n /**\n * The HTMLFile transport creates a `forever iframe` based transport\n * for Internet Explorer. Regular forever iframe implementations will \n * continuously trigger the browsers buzy indicators. If the forever iframe\n * is created inside a `htmlfile` these indicators will not be trigged.\n *\n * @constructor\n * @extends {io.Transport.XHR}\n * @api public\n */\n\n function HTMLFile (socket) {\n io.Transport.XHR.apply(this, arguments);\n };\n\n /**\n * Inherits from XHR transport.\n */\n\n io.util.inherit(HTMLFile, io.Transport.XHR);\n\n /**\n * Transport name\n *\n * @api public\n */\n\n HTMLFile.prototype.name = 'htmlfile';\n\n /**\n * Creates a new Ac...eX `htmlfile` with a forever loading iframe\n * that can be used to listen to messages. Inside the generated\n * `htmlfile` a reference will be made to the HTMLFile transport.\n *\n * @api private\n */\n\n HTMLFile.prototype.get = function () {\n this.doc = new window[(['Active'].concat('Object').join('X'))]('htmlfile');\n this.doc.open();\n this.doc.write('<html></html>');\n this.doc.close();\n this.doc.parentWindow.s = this;\n\n var iframeC = this.doc.createElement('div');\n iframeC.className = 'socketio';\n\n this.doc.body.appendChild(iframeC);\n this.iframe = this.doc.createElement('iframe');\n\n iframeC.appendChild(this.iframe);\n\n var self = this\n , query = io.util.query(this.socket.options.query, 't='+ +new Date);\n\n this.iframe.src = this.prepareUrl() + query;\n\n io.util.on(window, 'unload', function () {\n self.destroy();\n });\n };\n\n /**\n * The Socket.IO server will write script tags inside the forever\n * iframe, this function will be used as callback for the incoming\n * information.\n *\n * @param {String} data The message\n * @param {document} doc Reference to the context\n * @api private\n */\n\n HTMLFile.prototype._ = function (data, doc) {\n // unescape all forward slashes. see GH-1251\n data = data.replace(/\\\\\\//g, '/');\n this.onData(data);\n try {\n var script = doc.getElementsByTagName('script')[0];\n script.parentNode.removeChild(script);\n } catch (e) { }\n };\n\n /**\n * Destroy the established connection, iframe and `htmlfile`.\n * And calls the `CollectGarbage` function of Internet Explorer\n * to release the memory.\n *\n * @api private\n */\n\n HTMLFile.prototype.destroy = function () {\n if (this.iframe){\n try {\n this.iframe.src = 'about:blank';\n } catch(e){}\n\n this.doc = null;\n this.iframe.parentNode.removeChild(this.iframe);\n this.iframe = null;\n\n CollectGarbage();\n }\n };\n\n /**\n * Disconnects the established connection.\n *\n * @returns {Transport} Chaining.\n * @api public\n */\n\n HTMLFile.prototype.close = function () {\n this.destroy();\n return io.Transport.XHR.prototype.close.call(this);\n };\n\n /**\n * Checks if the browser supports this transport. The browser\n * must have an `Ac...eXObject` implementation.\n *\n * @return {Boolean}\n * @api public\n */\n\n HTMLFile.check = function (socket) {\n if (typeof window != \"undefined\" && (['Active'].concat('Object').join('X')) in window){\n try {\n var a = new window[(['Active'].concat('Object').join('X'))]('htmlfile');\n return a && io.Transport.XHR.check(socket);\n } catch(e){}\n }\n return false;\n };\n\n /**\n * Check if cross domain requests are supported.\n *\n * @returns {Boolean}\n * @api public\n */\n\n HTMLFile.xdomainCheck = function () {\n // we can probably do handling for sub-domains, we should\n // test that it's cross domain but a subdomain here\n return false;\n };\n\n /**\n * Add the transport to your public io.transports array.\n *\n * @api private\n */\n\n io.transports.push('htmlfile');\n\n})(\n 'undefined' != typeof io ? io.Transport : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n);\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io, global) {\n\n /**\n * Expose constructor.\n */\n\n exports['xhr-polling'] = XHRPolling;\n\n /**\n * The XHR-polling transport uses long polling XHR requests to create a\n * \"persistent\" connection with the server.\n *\n * @constructor\n * @api public\n */\n\n function XHRPolling () {\n io.Transport.XHR.apply(this, arguments);\n };\n\n /**\n * Inherits from XHR transport.\n */\n\n io.util.inherit(XHRPolling, io.Transport.XHR);\n\n /**\n * Merge the properties from XHR transport\n */\n\n io.util.merge(XHRPolling, io.Transport.XHR);\n\n /**\n * Transport name\n *\n * @api public\n */\n\n XHRPolling.prototype.name = 'xhr-polling';\n\n /**\n * Indicates whether heartbeats is enabled for this transport\n *\n * @api private\n */\n\n XHRPolling.prototype.heartbeats = function () {\n return false;\n };\n\n /** \n * Establish a connection, for iPhone and Android this will be done once the page\n * is loaded.\n *\n * @returns {Transport} Chaining.\n * @api public\n */\n\n XHRPolling.prototype.open = function () {\n var self = this;\n\n io.Transport.XHR.prototype.open.call(self);\n return false;\n };\n\n /**\n * Starts a XHR request to wait for incoming messages.\n *\n * @api private\n */\n\n function empty () {};\n\n XHRPolling.prototype.get = function () {\n if (!this.isOpen) return;\n\n var self = this;\n\n function stateChange () {\n if (this.readyState == 4) {\n this.onreadystatechange = empty;\n\n if (this.status == 200) {\n self.onData(this.responseText);\n self.get();\n } else {\n self.onClose();\n }\n }\n };\n\n function onload () {\n this.onload = empty;\n this.onerror = empty;\n self.retryCounter = 1;\n self.onData(this.responseText);\n self.get();\n };\n\n function onerror () {\n self.retryCounter ++;\n if(!self.retryCounter || self.retryCounter > 3) {\n self.onClose(); \n } else {\n self.get();\n }\n };\n\n this.xhr = this.request();\n\n if (global.XDomainRequest && this.xhr instanceof XDomainRequest) {\n this.xhr.onload = onload;\n this.xhr.onerror = onerror;\n } else {\n this.xhr.onreadystatechange = stateChange;\n }\n\n this.xhr.send(null);\n };\n\n /**\n * Handle the unclean close behavior.\n *\n * @api private\n */\n\n XHRPolling.prototype.onClose = function () {\n io.Transport.XHR.prototype.onClose.call(this);\n\n if (this.xhr) {\n this.xhr.onreadystatechange = this.xhr.onload = this.xhr.onerror = empty;\n try {\n this.xhr.abort();\n } catch(e){}\n this.xhr = null;\n }\n };\n\n /**\n * Webkit based browsers show a infinit spinner when you start a XHR request\n * before the browsers onload event is called so we need to defer opening of\n * the transport until the onload event is called. Wrapping the cb in our\n * defer method solve this.\n *\n * @param {Socket} socket The socket instance that needs a transport\n * @param {Function} fn The callback\n * @api private\n */\n\n XHRPolling.prototype.ready = function (socket, fn) {\n var self = this;\n\n io.util.defer(function () {\n fn.call(self);\n });\n };\n\n /**\n * Add the transport to your public io.transports array.\n *\n * @api private\n */\n\n io.transports.push('xhr-polling');\n\n})(\n 'undefined' != typeof io ? io.Transport : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n , this\n);\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost <dev@learnboost.com>\n * MIT Licensed\n */\n\n(function (exports, io, global) {\n /**\n * There is a way to hide the loading indicator in Firefox. If you create and\n * remove a iframe it will stop showing the current loading indicator.\n * Unfortunately we can't feature detect that and UA sniffing is evil.\n *\n * @api private\n */\n\n var indicator = global.document && \"MozAppearance\" in\n global.document.documentElement.style;\n\n /**\n * Expose constructor.\n */\n\n exports['jsonp-polling'] = JSONPPolling;\n\n /**\n * The JSONP transport creates an persistent connection by dynamically\n * inserting a script tag in the page. This script tag will receive the\n * information of the Socket.IO server. When new information is received\n * it creates a new script tag for the new data stream.\n *\n * @constructor\n * @extends {io.Transport.xhr-polling}\n * @api public\n */\n\n function JSONPPolling (socket) {\n io.Transport['xhr-polling'].apply(this, arguments);\n\n this.index = io.j.length;\n\n var self = this;\n\n io.j.push(function (msg) {\n self._(msg);\n });\n };\n\n /**\n * Inherits from XHR polling transport.\n */\n\n io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);\n\n /**\n * Transport name\n *\n * @api public\n */\n\n JSONPPolling.prototype.name = 'jsonp-polling';\n\n /**\n * Posts a encoded message to the Socket.IO server using an iframe.\n * The iframe is used because script tags can create POST based requests.\n * The iframe is positioned outside of the view so the user does not\n * notice it's existence.\n *\n * @param {String} data A encoded message.\n * @api private\n */\n\n JSONPPolling.prototype.post = function (data) {\n var self = this\n , query = io.util.query(\n this.socket.options.query\n , 't='+ (+new Date) + '&i=' + this.index\n );\n\n if (!this.form) {\n var form = document.createElement('form')\n , area = document.createElement('textarea')\n , id = this.iframeId = 'socketio_iframe_' + this.index\n , iframe;\n\n form.className = 'socketio';\n form.style.position = 'absolute';\n form.style.top = '0px';\n form.style.left = '0px';\n form.style.display = 'none';\n form.target = id;\n form.method = 'POST';\n form.setAttribute('accept-charset', 'utf-8');\n area.name = 'd';\n form.appendChild(area);\n document.body.appendChild(form);\n\n this.form = form;\n this.area = area;\n }\n\n this.form.action = this.prepareUrl() + query;\n\n function complete () {\n initIframe();\n self.socket.setBuffer(false);\n };\n\n function initIframe () {\n if (self.iframe) {\n self.form.removeChild(self.iframe);\n }\n\n try {\n // ie6 dynamic iframes with target=\"\" support (thanks Chris Lambacher)\n iframe = document.createElement('<iframe name=\"'+ self.iframeId +'\">');\n } catch (e) {\n iframe = document.createElement('iframe');\n iframe.name = self.iframeId;\n }\n\n iframe.id = self.iframeId;\n\n self.form.appendChild(iframe);\n self.iframe = iframe;\n };\n\n initIframe();\n\n // we temporarily stringify until we figure out how to prevent\n // browsers from turning `\\n` into `\\r\\n` in form inputs\n this.area.value = io.JSON.stringify(data);\n\n try {\n this.form.submit();\n } catch(e) {}\n\n if (this.iframe.attachEvent) {\n iframe.onreadystatechange = function () {\n if (self.iframe.readyState == 'complete') {\n complete();\n }\n };\n } else {\n this.iframe.onload = complete;\n }\n\n this.socket.setBuffer(true);\n };\n\n /**\n * Creates a new JSONP poll that can be used to listen\n * for messages from the Socket.IO server.\n *\n * @api private\n */\n\n JSONPPolling.prototype.get = function () {\n var self = this\n , script = document.createElement('script')\n , query = io.util.query(\n this.socket.options.query\n , 't='+ (+new Date) + '&i=' + this.index\n );\n\n if (this.script) {\n this.script.parentNode.removeChild(this.script);\n this.script = null;\n }\n\n script.async = true;\n script.src = this.prepareUrl() + query;\n script.onerror = function () {\n self.onClose();\n };\n\n var insertAt = document.getElementsByTagName('script')[0];\n insertAt.parentNode.insertBefore(script, insertAt);\n this.script = script;\n\n if (indicator) {\n setTimeout(function () {\n var iframe = document.createElement('iframe');\n document.body.appendChild(iframe);\n document.body.removeChild(iframe);\n }, 100);\n }\n };\n\n /**\n * Callback function for the incoming message stream from the Socket.IO server.\n *\n * @param {String} data The message\n * @api private\n */\n\n JSONPPolling.prototype._ = function (msg) {\n this.onData(msg);\n if (this.isOpen) {\n this.get();\n }\n return this;\n };\n\n /**\n * The indicator hack only works after onload\n *\n * @param {Socket} socket The socket instance that needs a transport\n * @param {Function} fn The callback\n * @api private\n */\n\n JSONPPolling.prototype.ready = function (socket, fn) {\n var self = this;\n if (!indicator) return fn.call(this);\n\n io.util.load(function () {\n fn.call(self);\n });\n };\n\n /**\n * Checks if browser supports this transport.\n *\n * @return {Boolean}\n * @api public\n */\n\n JSONPPolling.check = function () {\n return 'document' in global;\n };\n\n /**\n * Check if cross domain requests are supported\n *\n * @returns {Boolean}\n * @api public\n */\n\n JSONPPolling.xdomainCheck = function () {\n return true;\n };\n\n /**\n * Add the transport to your public io.transports array.\n *\n * @api private\n */\n\n io.transports.push('jsonp-polling');\n\n})(\n 'undefined' != typeof io ? io.Transport : module.exports\n , 'undefined' != typeof io ? io : module.parent.exports\n , this\n);\n\nif (typeof define === \"function\" && define.amd) {\n define([], function () { return io; });\n}\n})();","// based on https://github.com/ESTOS/strophe.jingle/\n// adds wildemitter support\nvar util = require('util');\nvar adapter = require('webrtc-adapter-test');\nvar WildEmitter = require('wildemitter');\n\nfunction dumpSDP(description) {\n return {\n type: description.type,\n sdp: description.sdp\n };\n}\n\nfunction dumpStream(stream) {\n var info = {\n label: stream.id,\n };\n if (stream.getAudioTracks().length) {\n info.audio = stream.getAudioTracks().map(function (track) {\n return track.id;\n });\n }\n if (stream.getVideoTracks().length) {\n info.video = stream.getVideoTracks().map(function (track) {\n return track.id;\n });\n }\n return info;\n}\n\nfunction TraceablePeerConnection(config, constraints) {\n var self = this;\n WildEmitter.call(this);\n\n this.peerconnection = new window.RTCPeerConnection(config, constraints);\n\n this.trace = function (what, info) {\n self.emit('PeerConnectionTrace', {\n time: new Date(),\n type: what,\n value: info || \"\"\n });\n };\n\n this.onicecandidate = null;\n this.peerconnection.onicecandidate = function (event) {\n self.trace('onicecandidate', event.candidate);\n if (self.onicecandidate !== null) {\n self.onicecandidate(event);\n }\n };\n this.onaddstream = null;\n this.peerconnection.onaddstream = function (event) {\n self.trace('onaddstream', dumpStream(event.stream));\n if (self.onaddstream !== null) {\n self.onaddstream(event);\n }\n };\n this.onremovestream = null;\n this.peerconnection.onremovestream = function (event) {\n self.trace('onremovestream', dumpStream(event.stream));\n if (self.onremovestream !== null) {\n self.onremovestream(event);\n }\n };\n this.onsignalingstatechange = null;\n this.peerconnection.onsignalingstatechange = function (event) {\n self.trace('onsignalingstatechange', self.signalingState);\n if (self.onsignalingstatechange !== null) {\n self.onsignalingstatechange(event);\n }\n };\n this.oniceconnectionstatechange = null;\n this.peerconnection.oniceconnectionstatechange = function (event) {\n self.trace('oniceconnectionstatechange', self.iceConnectionState);\n if (self.oniceconnectionstatechange !== null) {\n self.oniceconnectionstatechange(event);\n }\n };\n this.onnegotiationneeded = null;\n this.peerconnection.onnegotiationneeded = function (event) {\n self.trace('onnegotiationneeded');\n if (self.onnegotiationneeded !== null) {\n self.onnegotiationneeded(event);\n }\n };\n self.ondatachannel = null;\n this.peerconnection.ondatachannel = function (event) {\n self.trace('ondatachannel', event);\n if (self.ondatachannel !== null) {\n self.ondatachannel(event);\n }\n };\n this.getLocalStreams = this.peerconnection.getLocalStreams.bind(this.peerconnection);\n this.getRemoteStreams = this.peerconnection.getRemoteStreams.bind(this.peerconnection);\n}\n\nutil.inherits(TraceablePeerConnection, WildEmitter);\n\n['signalingState', 'iceConnectionState', 'localDescription', 'remoteDescription'].forEach(function (prop) {\n Object.defineProperty(TraceablePeerConnection.prototype, prop, {\n get: function () {\n return this.peerconnection[prop];\n }\n });\n});\n\nTraceablePeerConnection.prototype.addStream = function (stream) {\n this.trace('addStream', dumpStream(stream));\n this.peerconnection.addStream(stream);\n};\n\nTraceablePeerConnection.prototype.removeStream = function (stream) {\n this.trace('removeStream', dumpStream(stream));\n this.peerconnection.removeStream(stream);\n};\n\nTraceablePeerConnection.prototype.createDataChannel = function (label, opts) {\n this.trace('createDataChannel', label, opts);\n return this.peerconnection.createDataChannel(label, opts);\n};\n\nTraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) {\n var self = this;\n this.trace('setLocalDescription', dumpSDP(description));\n this.peerconnection.setLocalDescription(description,\n function () {\n self.trace('setLocalDescriptionOnSuccess');\n if (successCallback) successCallback();\n },\n function (err) {\n self.trace('setLocalDescriptionOnFailure', err);\n if (failureCallback) failureCallback(err);\n }\n );\n};\n\nTraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) {\n var self = this;\n this.trace('setRemoteDescription', dumpSDP(description));\n this.peerconnection.setRemoteDescription(description,\n function () {\n self.trace('setRemoteDescriptionOnSuccess');\n if (successCallback) successCallback();\n },\n function (err) {\n self.trace('setRemoteDescriptionOnFailure', err);\n if (failureCallback) failureCallback(err);\n }\n );\n};\n\nTraceablePeerConnection.prototype.close = function () {\n this.trace('stop');\n if (this.peerconnection.signalingState != 'closed') {\n this.peerconnection.close();\n }\n};\n\nTraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) {\n var self = this;\n this.trace('createOffer', constraints);\n this.peerconnection.createOffer(\n function (offer) {\n self.trace('createOfferOnSuccess', dumpSDP(offer));\n if (successCallback) successCallback(offer);\n },\n function (err) {\n self.trace('createOfferOnFailure', err);\n if (failureCallback) failureCallback(err);\n },\n constraints\n );\n};\n\nTraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) {\n var self = this;\n this.trace('createAnswer', constraints);\n this.peerconnection.createAnswer(\n function (answer) {\n self.trace('createAnswerOnSuccess', dumpSDP(answer));\n if (successCallback) successCallback(answer);\n },\n function (err) {\n self.trace('createAnswerOnFailure', err);\n if (failureCallback) failureCallback(err);\n },\n constraints\n );\n};\n\nTraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) {\n var self = this;\n this.trace('addIceCandidate', candidate);\n this.peerconnection.addIceCandidate(candidate,\n function () {\n //self.trace('addIceCandidateOnSuccess');\n if (successCallback) successCallback();\n },\n function (err) {\n self.trace('addIceCandidateOnFailure', err);\n if (failureCallback) failureCallback(err);\n }\n );\n};\n\nTraceablePeerConnection.prototype.getStats = function () {\n this.peerconnection.getStats.apply(this.peerconnection, arguments);\n};\n\nmodule.exports = TraceablePeerConnection;\n","/*\n * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.\n *\n * Use of this source code is governed by a BSD-style license\n * that can be found in the LICENSE file in the root of the source\n * tree.\n */\n\n/* More information about these options at jshint.com/docs/options */\n/* jshint browser: true, camelcase: true, curly: true, devel: true,\n eqeqeq: true, forin: false, globalstrict: true, node: true,\n quotmark: single, undef: true, unused: strict */\n/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,\nmozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */\n/* exported trace,requestUserMedia */\n\n'use strict';\n\nvar getUserMedia = null;\nvar attachMediaStream = null;\nvar reattachMediaStream = null;\nvar webrtcDetectedBrowser = null;\nvar webrtcDetectedVersion = null;\nvar webrtcMinimumVersion = null;\nvar webrtcUtils = {\n log: function() {\n // suppress console.log output when being included as a module.\n if (typeof module !== 'undefined' ||\n typeof require === 'function' && typeof define === 'function') {\n return;\n }\n console.log.apply(console, arguments);\n },\n extractVersion: function(uastring, expr, pos) {\n var match = uastring.match(expr);\n return match && match.length >= pos && parseInt(match[pos]);\n }\n};\n\nfunction trace(text) {\n // This function is used for logging.\n if (text[text.length - 1] === '\\n') {\n text = text.substring(0, text.length - 1);\n }\n if (window.performance) {\n var now = (window.performance.now() / 1000).toFixed(3);\n webrtcUtils.log(now + ': ' + text);\n } else {\n webrtcUtils.log(text);\n }\n}\n\nif (typeof window === 'object') {\n if (window.HTMLMediaElement &&\n !('srcObject' in window.HTMLMediaElement.prototype)) {\n // Shim the srcObject property, once, when HTMLMediaElement is found.\n Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {\n get: function() {\n // If prefixed srcObject property exists, return it.\n // Otherwise use the shimmed property, _srcObject\n return 'mozSrcObject' in this ? this.mozSrcObject : this._srcObject;\n },\n set: function(stream) {\n if ('mozSrcObject' in this) {\n this.mozSrcObject = stream;\n } else {\n // Use _srcObject as a private property for this shim\n this._srcObject = stream;\n // TODO: revokeObjectUrl(this.src) when !stream to release resources?\n this.src = URL.createObjectURL(stream);\n }\n }\n });\n }\n // Proxy existing globals\n getUserMedia = window.navigator && window.navigator.getUserMedia;\n}\n\n// Attach a media stream to an element.\nattachMediaStream = function(element, stream) {\n element.srcObject = stream;\n};\n\nreattachMediaStream = function(to, from) {\n to.srcObject = from.srcObject;\n};\n\nif (typeof window === 'undefined' || !window.navigator) {\n webrtcUtils.log('This does not appear to be a browser');\n webrtcDetectedBrowser = 'not a browser';\n} else if (navigator.mozGetUserMedia && window.mozRTCPeerConnection) {\n webrtcUtils.log('This appears to be Firefox');\n\n webrtcDetectedBrowser = 'firefox';\n\n // the detected firefox version.\n webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,\n /Firefox\\/([0-9]+)\\./, 1);\n\n // the minimum firefox version still supported by adapter.\n webrtcMinimumVersion = 31;\n\n // The RTCPeerConnection object.\n window.RTCPeerConnection = function(pcConfig, pcConstraints) {\n if (webrtcDetectedVersion < 38) {\n // .urls is not supported in FF < 38.\n // create RTCIceServers with a single url.\n if (pcConfig && pcConfig.iceServers) {\n var newIceServers = [];\n for (var i = 0; i < pcConfig.iceServers.length; i++) {\n var server = pcConfig.iceServers[i];\n if (server.hasOwnProperty('urls')) {\n for (var j = 0; j < server.urls.length; j++) {\n var newServer = {\n url: server.urls[j]\n };\n if (server.urls[j].indexOf('turn') === 0) {\n newServer.username = server.username;\n newServer.credential = server.credential;\n }\n newIceServers.push(newServer);\n }\n } else {\n newIceServers.push(pcConfig.iceServers[i]);\n }\n }\n pcConfig.iceServers = newIceServers;\n }\n }\n return new mozRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors\n };\n\n // The RTCSessionDescription object.\n if (!window.RTCSessionDescription) {\n window.RTCSessionDescription = mozRTCSessionDescription;\n }\n\n // The RTCIceCandidate object.\n if (!window.RTCIceCandidate) {\n window.RTCIceCandidate = mozRTCIceCandidate;\n }\n\n // getUserMedia constraints shim.\n getUserMedia = function(constraints, onSuccess, onError) {\n var constraintsToFF37 = function(c) {\n if (typeof c !== 'object' || c.require) {\n return c;\n }\n var require = [];\n Object.keys(c).forEach(function(key) {\n if (key === 'require' || key === 'advanced' || key === 'mediaSource') {\n return;\n }\n var r = c[key] = (typeof c[key] === 'object') ?\n c[key] : {ideal: c[key]};\n if (r.min !== undefined ||\n r.max !== undefined || r.exact !== undefined) {\n require.push(key);\n }\n if (r.exact !== undefined) {\n if (typeof r.exact === 'number') {\n r.min = r.max = r.exact;\n } else {\n c[key] = r.exact;\n }\n delete r.exact;\n }\n if (r.ideal !== undefined) {\n c.advanced = c.advanced || [];\n var oc = {};\n if (typeof r.ideal === 'number') {\n oc[key] = {min: r.ideal, max: r.ideal};\n } else {\n oc[key] = r.ideal;\n }\n c.advanced.push(oc);\n delete r.ideal;\n if (!Object.keys(r).length) {\n delete c[key];\n }\n }\n });\n if (require.length) {\n c.require = require;\n }\n return c;\n };\n if (webrtcDetectedVersion < 38) {\n webrtcUtils.log('spec: ' + JSON.stringify(constraints));\n if (constraints.audio) {\n constraints.audio = constraintsToFF37(constraints.audio);\n }\n if (constraints.video) {\n constraints.video = constraintsToFF37(constraints.video);\n }\n webrtcUtils.log('ff37: ' + JSON.stringify(constraints));\n }\n return navigator.mozGetUserMedia(constraints, onSuccess, onError);\n };\n\n navigator.getUserMedia = getUserMedia;\n\n // Shim for mediaDevices on older versions.\n if (!navigator.mediaDevices) {\n navigator.mediaDevices = {getUserMedia: requestUserMedia,\n addEventListener: function() { },\n removeEventListener: function() { }\n };\n }\n navigator.mediaDevices.enumerateDevices =\n navigator.mediaDevices.enumerateDevices || function() {\n return new Promise(function(resolve) {\n var infos = [\n {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},\n {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}\n ];\n resolve(infos);\n });\n };\n\n if (webrtcDetectedVersion < 41) {\n // Work around http://bugzil.la/1169665\n var orgEnumerateDevices =\n navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);\n navigator.mediaDevices.enumerateDevices = function() {\n return orgEnumerateDevices().then(undefined, function(e) {\n if (e.name === 'NotFoundError') {\n return [];\n }\n throw e;\n });\n };\n }\n} else if (navigator.webkitGetUserMedia && window.webkitRTCPeerConnection) {\n webrtcUtils.log('This appears to be Chrome');\n\n webrtcDetectedBrowser = 'chrome';\n\n // the detected chrome version.\n webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,\n /Chrom(e|ium)\\/([0-9]+)\\./, 2);\n\n // the minimum chrome version still supported by adapter.\n webrtcMinimumVersion = 38;\n\n // The RTCPeerConnection object.\n window.RTCPeerConnection = function(pcConfig, pcConstraints) {\n // Translate iceTransportPolicy to iceTransports,\n // see https://code.google.com/p/webrtc/issues/detail?id=4869\n if (pcConfig && pcConfig.iceTransportPolicy) {\n pcConfig.iceTransports = pcConfig.iceTransportPolicy;\n }\n\n var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors\n var origGetStats = pc.getStats.bind(pc);\n pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line\n var self = this;\n var args = arguments;\n\n // If selector is a function then we are in the old style stats so just\n // pass back the original getStats format to avoid breaking old users.\n if (arguments.length > 0 && typeof selector === 'function') {\n return origGetStats(selector, successCallback);\n }\n\n var fixChromeStats = function(response) {\n var standardReport = {};\n var reports = response.result();\n reports.forEach(function(report) {\n var standardStats = {\n id: report.id,\n timestamp: report.timestamp,\n type: report.type\n };\n report.names().forEach(function(name) {\n standardStats[name] = report.stat(name);\n });\n standardReport[standardStats.id] = standardStats;\n });\n\n return standardReport;\n };\n\n if (arguments.length >= 2) {\n var successCallbackWrapper = function(response) {\n args[1](fixChromeStats(response));\n };\n\n return origGetStats.apply(this, [successCallbackWrapper, arguments[0]]);\n }\n\n // promise-support\n return new Promise(function(resolve, reject) {\n if (args.length === 1 && selector === null) {\n origGetStats.apply(self, [\n function(response) {\n resolve.apply(null, [fixChromeStats(response)]);\n }, reject]);\n } else {\n origGetStats.apply(self, [resolve, reject]);\n }\n });\n };\n\n return pc;\n };\n\n // add promise support\n ['createOffer', 'createAnswer'].forEach(function(method) {\n var nativeMethod = webkitRTCPeerConnection.prototype[method];\n webkitRTCPeerConnection.prototype[method] = function() {\n var self = this;\n if (arguments.length < 1 || (arguments.length === 1 &&\n typeof(arguments[0]) === 'object')) {\n var opts = arguments.length === 1 ? arguments[0] : undefined;\n return new Promise(function(resolve, reject) {\n nativeMethod.apply(self, [resolve, reject, opts]);\n });\n } else {\n return nativeMethod.apply(this, arguments);\n }\n };\n });\n\n ['setLocalDescription', 'setRemoteDescription',\n 'addIceCandidate'].forEach(function(method) {\n var nativeMethod = webkitRTCPeerConnection.prototype[method];\n webkitRTCPeerConnection.prototype[method] = function() {\n var args = arguments;\n var self = this;\n return new Promise(function(resolve, reject) {\n nativeMethod.apply(self, [args[0],\n function() {\n resolve();\n if (args.length >= 2) {\n args[1].apply(null, []);\n }\n },\n function(err) {\n reject(err);\n if (args.length >= 3) {\n args[2].apply(null, [err]);\n }\n }]\n );\n });\n };\n });\n\n // getUserMedia constraints shim.\n var constraintsToChrome = function(c) {\n if (typeof c !== 'object' || c.mandatory || c.optional) {\n return c;\n }\n var cc = {};\n Object.keys(c).forEach(function(key) {\n if (key === 'require' || key === 'advanced' || key === 'mediaSource') {\n return;\n }\n var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};\n if (r.exact !== undefined && typeof r.exact === 'number') {\n r.min = r.max = r.exact;\n }\n var oldname = function(prefix, name) {\n if (prefix) {\n return prefix + name.charAt(0).toUpperCase() + name.slice(1);\n }\n return (name === 'deviceId') ? 'sourceId' : name;\n };\n if (r.ideal !== undefined) {\n cc.optional = cc.optional || [];\n var oc = {};\n if (typeof r.ideal === 'number') {\n oc[oldname('min', key)] = r.ideal;\n cc.optional.push(oc);\n oc = {};\n oc[oldname('max', key)] = r.ideal;\n cc.optional.push(oc);\n } else {\n oc[oldname('', key)] = r.ideal;\n cc.optional.push(oc);\n }\n }\n if (r.exact !== undefined && typeof r.exact !== 'number') {\n cc.mandatory = cc.mandatory || {};\n cc.mandatory[oldname('', key)] = r.exact;\n } else {\n ['min', 'max'].forEach(function(mix) {\n if (r[mix] !== undefined) {\n cc.mandatory = cc.mandatory || {};\n cc.mandatory[oldname(mix, key)] = r[mix];\n }\n });\n }\n });\n if (c.advanced) {\n cc.optional = (cc.optional || []).concat(c.advanced);\n }\n return cc;\n };\n\n getUserMedia = function(constraints, onSuccess, onError) {\n if (constraints.audio) {\n constraints.audio = constraintsToChrome(constraints.audio);\n }\n if (constraints.video) {\n constraints.video = constraintsToChrome(constraints.video);\n }\n webrtcUtils.log('chrome: ' + JSON.stringify(constraints));\n return navigator.webkitGetUserMedia(constraints, onSuccess, onError);\n };\n navigator.getUserMedia = getUserMedia;\n\n if (!navigator.mediaDevices) {\n navigator.mediaDevices = {getUserMedia: requestUserMedia,\n enumerateDevices: function() {\n return new Promise(function(resolve) {\n var kinds = {audio: 'audioinput', video: 'videoinput'};\n return MediaStreamTrack.getSources(function(devices) {\n resolve(devices.map(function(device) {\n return {label: device.label,\n kind: kinds[device.kind],\n deviceId: device.id,\n groupId: ''};\n }));\n });\n });\n }};\n }\n\n // A shim for getUserMedia method on the mediaDevices object.\n // TODO(KaptenJansson) remove once implemented in Chrome stable.\n if (!navigator.mediaDevices.getUserMedia) {\n navigator.mediaDevices.getUserMedia = function(constraints) {\n return requestUserMedia(constraints);\n };\n } else {\n // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia\n // function which returns a Promise, it does not accept spec-style\n // constraints.\n var origGetUserMedia = navigator.mediaDevices.getUserMedia.\n bind(navigator.mediaDevices);\n navigator.mediaDevices.getUserMedia = function(c) {\n webrtcUtils.log('spec: ' + JSON.stringify(c)); // whitespace for alignment\n c.audio = constraintsToChrome(c.audio);\n c.video = constraintsToChrome(c.video);\n webrtcUtils.log('chrome: ' + JSON.stringify(c));\n return origGetUserMedia(c);\n };\n }\n\n // Dummy devicechange event methods.\n // TODO(KaptenJansson) remove once implemented in Chrome stable.\n if (typeof navigator.mediaDevices.addEventListener === 'undefined') {\n navigator.mediaDevices.addEventListener = function() {\n webrtcUtils.log('Dummy mediaDevices.addEventListener called.');\n };\n }\n if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {\n navigator.mediaDevices.removeEventListener = function() {\n webrtcUtils.log('Dummy mediaDevices.removeEventListener called.');\n };\n }\n\n // Attach a media stream to an element.\n attachMediaStream = function(element, stream) {\n if (webrtcDetectedVersion >= 43) {\n element.srcObject = stream;\n } else if (typeof element.src !== 'undefined') {\n element.src = URL.createObjectURL(stream);\n } else {\n webrtcUtils.log('Error attaching stream to element.');\n }\n };\n reattachMediaStream = function(to, from) {\n if (webrtcDetectedVersion >= 43) {\n to.srcObject = from.srcObject;\n } else {\n to.src = from.src;\n }\n };\n\n} else if (navigator.mediaDevices && navigator.userAgent.match(\n /Edge\\/(\\d+).(\\d+)$/)) {\n webrtcUtils.log('This appears to be Edge');\n webrtcDetectedBrowser = 'edge';\n\n webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,\n /Edge\\/(\\d+).(\\d+)$/, 2);\n\n // the minimum version still supported by adapter.\n webrtcMinimumVersion = 12;\n} else {\n webrtcUtils.log('Browser does not appear to be WebRTC-capable');\n}\n\n// Returns the result of getUserMedia as a Promise.\nfunction requestUserMedia(constraints) {\n return new Promise(function(resolve, reject) {\n getUserMedia(constraints, resolve, reject);\n });\n}\n\nvar webrtcTesting = {};\ntry {\n Object.defineProperty(webrtcTesting, 'version', {\n set: function(version) {\n webrtcDetectedVersion = version;\n }\n });\n} catch (e) {}\n\nif (typeof module !== 'undefined') {\n var RTCPeerConnection;\n if (typeof window !== 'undefined') {\n RTCPeerConnection = window.RTCPeerConnection;\n }\n module.exports = {\n RTCPeerConnection: RTCPeerConnection,\n getUserMedia: getUserMedia,\n attachMediaStream: attachMediaStream,\n reattachMediaStream: reattachMediaStream,\n webrtcDetectedBrowser: webrtcDetectedBrowser,\n webrtcDetectedVersion: webrtcDetectedVersion,\n webrtcMinimumVersion: webrtcMinimumVersion,\n webrtcTesting: webrtcTesting,\n webrtcUtils: webrtcUtils\n //requestUserMedia: not exposed on purpose.\n //trace: not exposed on purpose.\n };\n} else if ((typeof require === 'function') && (typeof define === 'function')) {\n // Expose objects and functions when RequireJS is doing the loading.\n define([], function() {\n return {\n RTCPeerConnection: window.RTCPeerConnection,\n getUserMedia: getUserMedia,\n attachMediaStream: attachMediaStream,\n reattachMediaStream: reattachMediaStream,\n webrtcDetectedBrowser: webrtcDetectedBrowser,\n webrtcDetectedVersion: webrtcDetectedVersion,\n webrtcMinimumVersion: webrtcMinimumVersion,\n webrtcTesting: webrtcTesting,\n webrtcUtils: webrtcUtils\n //requestUserMedia: not exposed on purpose.\n //trace: not exposed on purpose.\n };\n });\n}\n","// created by @HenrikJoreteg\nvar prefix;\nvar version;\n\nif (window.mozRTCPeerConnection || navigator.mozGetUserMedia) {\n prefix = 'moz';\n version = parseInt(navigator.userAgent.match(/Firefox\\/([0-9]+)\\./)[1], 10);\n} else if (window.webkitRTCPeerConnection || navigator.webkitGetUserMedia) {\n prefix = 'webkit';\n version = navigator.userAgent.match(/Chrom(e|ium)/) && parseInt(navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./)[2], 10);\n}\n\nvar PC = window.mozRTCPeerConnection || window.webkitRTCPeerConnection;\nvar IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;\nvar SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;\nvar MediaStream = window.webkitMediaStream || window.MediaStream;\nvar screenSharing = window.location.protocol === 'https:' &&\n ((prefix === 'webkit' && version >= 26) ||\n (prefix === 'moz' && version >= 33))\nvar AudioContext = window.AudioContext || window.webkitAudioContext;\nvar videoEl = document.createElement('video');\nvar supportVp8 = videoEl && videoEl.canPlayType && videoEl.canPlayType('video/webm; codecs=\"vp8\", vorbis') === \"probably\";\nvar getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia;\n\n// export support flags and constructors.prototype && PC\nmodule.exports = {\n prefix: prefix,\n browserVersion: version,\n support: !!PC && supportVp8 && !!getUserMedia,\n // new support style\n supportRTCPeerConnection: !!PC,\n supportVp8: supportVp8,\n supportGetUserMedia: !!getUserMedia,\n supportDataChannel: !!(PC && PC.prototype && PC.prototype.createDataChannel),\n supportWebAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource),\n supportMediaStream: !!(MediaStream && MediaStream.prototype.removeTrack),\n supportScreenSharing: !!screenSharing,\n // old deprecated style. Dont use this anymore\n dataChannel: !!(PC && PC.prototype && PC.prototype.createDataChannel),\n webAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource),\n mediaStream: !!(MediaStream && MediaStream.prototype.removeTrack),\n screenSharing: !!screenSharing,\n // constructors\n AudioContext: AudioContext,\n PeerConnection: PC,\n SessionDescription: SessionDescription,\n IceCandidate: IceCandidate,\n MediaStream: MediaStream,\n getUserMedia: getUserMedia\n};\n","/*\r\nWildEmitter.js is a slim little event emitter by @henrikjoreteg largely based\r\non @visionmedia's Emitter from UI Kit.\r\n\r\nWhy? I wanted it standalone.\r\n\r\nI also wanted support for wildcard emitters like this:\r\n\r\nemitter.on('*', function (eventName, other, event, payloads) {\r\n\r\n});\r\n\r\nemitter.on('somenamespace*', function (eventName, payloads) {\r\n\r\n});\r\n\r\nPlease note that callbacks triggered by wildcard registered events also get\r\nthe event name as the first argument.\r\n*/\r\n\r\nmodule.exports = WildEmitter;\r\n\r\nfunction WildEmitter() { }\r\n\r\nWildEmitter.mixin = function (constructor) {\r\n var prototype = constructor.prototype || constructor;\r\n\r\n prototype.isWildEmitter= true;\r\n\r\n // Listen on the given `event` with `fn`. Store a group name if present.\r\n prototype.on = function (event, groupName, fn) {\r\n this.callbacks = this.callbacks || {};\r\n var hasGroup = (arguments.length === 3),\r\n group = hasGroup ? arguments[1] : undefined,\r\n func = hasGroup ? arguments[2] : arguments[1];\r\n func._groupName = group;\r\n (this.callbacks[event] = this.callbacks[event] || []).push(func);\r\n return this;\r\n };\r\n\r\n // Adds an `event` listener that will be invoked a single\r\n // time then automatically removed.\r\n prototype.once = function (event, groupName, fn) {\r\n var self = this,\r\n hasGroup = (arguments.length === 3),\r\n group = hasGroup ? arguments[1] : undefined,\r\n func = hasGroup ? arguments[2] : arguments[1];\r\n function on() {\r\n self.off(event, on);\r\n func.apply(this, arguments);\r\n }\r\n this.on(event, group, on);\r\n return this;\r\n };\r\n\r\n // Unbinds an entire group\r\n prototype.releaseGroup = function (groupName) {\r\n this.callbacks = this.callbacks || {};\r\n var item, i, len, handlers;\r\n for (item in this.callbacks) {\r\n handlers = this.callbacks[item];\r\n for (i = 0, len = handlers.length; i < len; i++) {\r\n if (handlers[i]._groupName === groupName) {\r\n //console.log('removing');\r\n // remove it and shorten the array we're looping through\r\n handlers.splice(i, 1);\r\n i--;\r\n len--;\r\n }\r\n }\r\n }\r\n return this;\r\n };\r\n\r\n // Remove the given callback for `event` or all\r\n // registered callbacks.\r\n prototype.off = function (event, fn) {\r\n this.callbacks = this.callbacks || {};\r\n var callbacks = this.callbacks[event],\r\n i;\r\n\r\n if (!callbacks) return this;\r\n\r\n // remove all handlers\r\n if (arguments.length === 1) {\r\n delete this.callbacks[event];\r\n return this;\r\n }\r\n\r\n // remove specific handler\r\n i = callbacks.indexOf(fn);\r\n callbacks.splice(i, 1);\r\n if (callbacks.length === 0) {\r\n delete this.callbacks[event];\r\n }\r\n return this;\r\n };\r\n\r\n /// Emit `event` with the given args.\r\n // also calls any `*` handlers\r\n prototype.emit = function (event) {\r\n this.callbacks = this.callbacks || {};\r\n var args = [].slice.call(arguments, 1),\r\n callbacks = this.callbacks[event],\r\n specialCallbacks = this.getWildcardCallbacks(event),\r\n i,\r\n len,\r\n item,\r\n listeners;\r\n\r\n if (callbacks) {\r\n listeners = callbacks.slice();\r\n for (i = 0, len = listeners.length; i < len; ++i) {\r\n if (!listeners[i]) {\r\n break;\r\n }\r\n listeners[i].apply(this, args);\r\n }\r\n }\r\n\r\n if (specialCallbacks) {\r\n len = specialCallbacks.length;\r\n listeners = specialCallbacks.slice();\r\n for (i = 0, len = listeners.length; i < len; ++i) {\r\n if (!listeners[i]) {\r\n break;\r\n }\r\n listeners[i].apply(this, [event].concat(args));\r\n }\r\n }\r\n\r\n return this;\r\n };\r\n\r\n // Helper for for finding special wildcard event handlers that match the event\r\n prototype.getWildcardCallbacks = function (eventName) {\r\n this.callbacks = this.callbacks || {};\r\n var item,\r\n split,\r\n result = [];\r\n\r\n for (item in this.callbacks) {\r\n split = item.split('*');\r\n if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {\r\n result = result.concat(this.callbacks[item]);\r\n }\r\n }\r\n return result;\r\n };\r\n\r\n};\r\n\r\nWildEmitter.mixin(WildEmitter);\r\n","/* global Y */\r\n'use strict'\r\n\r\nvar SimpleWebRTC = require('simplewebrtc')\r\n\r\nfunction extend (Y) {\r\n class WebRTC extends Y.AbstractConnector {\r\n constructor (y, options) {\r\n if (options === undefined) {\r\n throw new Error('Options must not be undefined!')\r\n }\r\n if (options.room == null) {\r\n throw new Error('You must define a room name!')\r\n }\r\n options.role = 'slave'\r\n super(y, options)\r\n this.webrtcOptions = {\r\n url: options.url || 'http://yatta.ninja:8888',\r\n room: options.room\r\n }\r\n var swr = new SimpleWebRTC(this.webrtcOptions)\r\n this.swr = swr\r\n var self = this\r\n swr.once('connectionReady', function (userId) {\r\n // SimpleWebRTC (swr) is initialized\r\n swr.joinRoom(self.webrtcOptions.room)\r\n\r\n swr.once('joinedRoom', function () {\r\n self.setUserId(userId)\r\n /*\r\n var i\r\n // notify the connector class about all the users that already\r\n // joined the session\r\n for(i in self.swr.webrtc.peers){\r\n self.userJoined(self.swr.webrtc.peers[i].id, \"master\")\r\n }*/\r\n swr.on('channelMessage', function (peer, room_, message) {\r\n // The client received a message\r\n // Check if the connector is already initialized,\r\n // only then forward the message to the connector class\r\n if (message.type != null) {\r\n self.receiveMessage(peer.id, message.payload)\r\n }\r\n })\r\n })\r\n\r\n swr.on('createdPeer', function (peer) {\r\n // a new peer/client joined the session.\r\n // Notify the connector class, if the connector\r\n // is already initialized\r\n self.userJoined(peer.id, 'master')\r\n })\r\n\r\n swr.on('peerStreamRemoved', function (peer) {\r\n // a client left the session.\r\n // Notify the connector class, if the connector\r\n // is already initialized\r\n self.userLeft(peer.id)\r\n })\r\n })\r\n }\r\n disconnect () {\r\n this.swr.leaveRoom()\r\n super.disconnect()\r\n }\r\n reconnect () {\r\n this.swr.joinRoom(this.webrtcOptions.room)\r\n super.reconnect()\r\n }\r\n send (uid, message) {\r\n var self = this\r\n // we have to make sure that the message is sent under all circumstances\r\n var send = function () {\r\n // check if the clients still exists\r\n var peer = self.swr.webrtc.getPeers(uid)[0]\r\n var success\r\n if (peer) {\r\n // success is true, if the message is successfully sent\r\n success = peer.sendDirectly('simplewebrtc', 'yjs', message)\r\n }\r\n if (!success) {\r\n // resend the message if it didn't work\r\n setTimeout(send, 500)\r\n }\r\n }\r\n // try to send the message\r\n send()\r\n }\r\n broadcast (message) {\r\n this.swr.sendDirectlyToAll('simplewebrtc', 'yjs', message)\r\n }\r\n isDisconnected () {\r\n return false\r\n }\r\n }\r\n Y.extend('webrtc', WebRTC)\r\n}\r\n\r\nmodule.exports = extend\r\nif (typeof Y !== 'undefined') {\r\n extend(Y)\r\n}\r\n","if (typeof Object.create === 'function') {\n // implementation from standard node.js 'util' module\n module.exports = function inherits(ctor, superCtor) {\n ctor.super_ = superCtor\n ctor.prototype = Object.create(superCtor.prototype, {\n constructor: {\n value: ctor,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n };\n} else {\n // old school shim for old browsers\n module.exports = function inherits(ctor, superCtor) {\n ctor.super_ = superCtor\n var TempCtor = function () {}\n TempCtor.prototype = superCtor.prototype\n ctor.prototype = new TempCtor()\n ctor.prototype.constructor = ctor\n }\n}\n","// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = setTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n clearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n setTimeout(drainQueue, 0);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n","module.exports = function isBuffer(arg) {\n return arg && typeof arg === 'object'\n && typeof arg.copy === 'function'\n && typeof arg.fill === 'function'\n && typeof arg.readUInt8 === 'function';\n}","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n if (!isString(f)) {\n var objects = [];\n for (var i = 0; i < arguments.length; i++) {\n objects.push(inspect(arguments[i]));\n }\n return objects.join(' ');\n }\n\n var i = 1;\n var args = arguments;\n var len = args.length;\n var str = String(f).replace(formatRegExp, function(x) {\n if (x === '%%') return '%';\n if (i >= len) return x;\n switch (x) {\n case '%s': return String(args[i++]);\n case '%d': return Number(args[i++]);\n case '%j':\n try {\n return JSON.stringify(args[i++]);\n } catch (_) {\n return '[Circular]';\n }\n default:\n return x;\n }\n });\n for (var x = args[i]; i < len; x = args[++i]) {\n if (isNull(x) || !isObject(x)) {\n str += ' ' + x;\n } else {\n str += ' ' + inspect(x);\n }\n }\n return str;\n};\n\n\n// Mark that a method should not be used.\n// Returns a modified function which warns once by default.\n// If --no-deprecation is set, then it is a no-op.\nexports.deprecate = function(fn, msg) {\n // Allow for deprecating things in the process of starting up.\n if (isUndefined(global.process)) {\n return function() {\n return exports.deprecate(fn, msg).apply(this, arguments);\n };\n }\n\n if (process.noDeprecation === true) {\n return fn;\n }\n\n var warned = false;\n function deprecated() {\n if (!warned) {\n if (process.throwDeprecation) {\n throw new Error(msg);\n } else if (process.traceDeprecation) {\n console.trace(msg);\n } else {\n console.error(msg);\n }\n warned = true;\n }\n return fn.apply(this, arguments);\n }\n\n return deprecated;\n};\n\n\nvar debugs = {};\nvar debugEnviron;\nexports.debuglog = function(set) {\n if (isUndefined(debugEnviron))\n debugEnviron = process.env.NODE_DEBUG || '';\n set = set.toUpperCase();\n if (!debugs[set]) {\n if (new RegExp('\\\\b' + set + '\\\\b', 'i').test(debugEnviron)) {\n var pid = process.pid;\n debugs[set] = function() {\n var msg = exports.format.apply(exports, arguments);\n console.error('%s %d: %s', set, pid, msg);\n };\n } else {\n debugs[set] = function() {};\n }\n }\n return debugs[set];\n};\n\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n // default options\n var ctx = {\n seen: [],\n stylize: stylizeNoColor\n };\n // legacy...\n if (arguments.length >= 3) ctx.depth = arguments[2];\n if (arguments.length >= 4) ctx.colors = arguments[3];\n if (isBoolean(opts)) {\n // legacy...\n ctx.showHidden = opts;\n } else if (opts) {\n // got an \"options\" object\n exports._extend(ctx, opts);\n }\n // set default options\n if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n if (isUndefined(ctx.depth)) ctx.depth = 2;\n if (isUndefined(ctx.colors)) ctx.colors = false;\n if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n if (ctx.colors) ctx.stylize = stylizeWithColor;\n return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n 'bold' : [1, 22],\n 'italic' : [3, 23],\n 'underline' : [4, 24],\n 'inverse' : [7, 27],\n 'white' : [37, 39],\n 'grey' : [90, 39],\n 'black' : [30, 39],\n 'blue' : [34, 39],\n 'cyan' : [36, 39],\n 'green' : [32, 39],\n 'magenta' : [35, 39],\n 'red' : [31, 39],\n 'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n 'special': 'cyan',\n 'number': 'yellow',\n 'boolean': 'yellow',\n 'undefined': 'grey',\n 'null': 'bold',\n 'string': 'green',\n 'date': 'magenta',\n // \"name\": intentionally not styling\n 'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n var style = inspect.styles[styleType];\n\n if (style) {\n return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n '\\u001b[' + inspect.colors[style][1] + 'm';\n } else {\n return str;\n }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n return str;\n}\n\n\nfunction arrayToHash(array) {\n var hash = {};\n\n array.forEach(function(val, idx) {\n hash[val] = true;\n });\n\n return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n // Provide a hook for user-specified inspect functions.\n // Check that value is an object with an inspect function on it\n if (ctx.customInspect &&\n value &&\n isFunction(value.inspect) &&\n // Filter out the util module, it's inspect function is special\n value.inspect !== exports.inspect &&\n // Also filter out any prototype objects using the circular check.\n !(value.constructor && value.constructor.prototype === value)) {\n var ret = value.inspect(recurseTimes, ctx);\n if (!isString(ret)) {\n ret = formatValue(ctx, ret, recurseTimes);\n }\n return ret;\n }\n\n // Primitive types cannot have properties\n var primitive = formatPrimitive(ctx, value);\n if (primitive) {\n return primitive;\n }\n\n // Look up the keys of the object.\n var keys = Object.keys(value);\n var visibleKeys = arrayToHash(keys);\n\n if (ctx.showHidden) {\n keys = Object.getOwnPropertyNames(value);\n }\n\n // IE doesn't make error fields non-enumerable\n // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx\n if (isError(value)\n && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {\n return formatError(value);\n }\n\n // Some type of object without properties can be shortcutted.\n if (keys.length === 0) {\n if (isFunction(value)) {\n var name = value.name ? ': ' + value.name : '';\n return ctx.stylize('[Function' + name + ']', 'special');\n }\n if (isRegExp(value)) {\n return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n }\n if (isDate(value)) {\n return ctx.stylize(Date.prototype.toString.call(value), 'date');\n }\n if (isError(value)) {\n return formatError(value);\n }\n }\n\n var base = '', array = false, braces = ['{', '}'];\n\n // Make Array say that they are Array\n if (isArray(value)) {\n array = true;\n braces = ['[', ']'];\n }\n\n // Make functions say that they are functions\n if (isFunction(value)) {\n var n = value.name ? ': ' + value.name : '';\n base = ' [Function' + n + ']';\n }\n\n // Make RegExps say that they are RegExps\n if (isRegExp(value)) {\n base = ' ' + RegExp.prototype.toString.call(value);\n }\n\n // Make dates with properties first say the date\n if (isDate(value)) {\n base = ' ' + Date.prototype.toUTCString.call(value);\n }\n\n // Make error with message first say the error\n if (isError(value)) {\n base = ' ' + formatError(value);\n }\n\n if (keys.length === 0 && (!array || value.length == 0)) {\n return braces[0] + base + braces[1];\n }\n\n if (recurseTimes < 0) {\n if (isRegExp(value)) {\n return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n } else {\n return ctx.stylize('[Object]', 'special');\n }\n }\n\n ctx.seen.push(value);\n\n var output;\n if (array) {\n output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n } else {\n output = keys.map(function(key) {\n return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n });\n }\n\n ctx.seen.pop();\n\n return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n if (isUndefined(value))\n return ctx.stylize('undefined', 'undefined');\n if (isString(value)) {\n var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\\\\"/g, '\"') + '\\'';\n return ctx.stylize(simple, 'string');\n }\n if (isNumber(value))\n return ctx.stylize('' + value, 'number');\n if (isBoolean(value))\n return ctx.stylize('' + value, 'boolean');\n // For some reason typeof null is \"object\", so special case here.\n if (isNull(value))\n return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n var output = [];\n for (var i = 0, l = value.length; i < l; ++i) {\n if (hasOwnProperty(value, String(i))) {\n output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n String(i), true));\n } else {\n output.push('');\n }\n }\n keys.forEach(function(key) {\n if (!key.match(/^\\d+$/)) {\n output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n key, true));\n }\n });\n return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n var name, str, desc;\n desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n if (desc.get) {\n if (desc.set) {\n str = ctx.stylize('[Getter/Setter]', 'special');\n } else {\n str = ctx.stylize('[Getter]', 'special');\n }\n } else {\n if (desc.set) {\n str = ctx.stylize('[Setter]', 'special');\n }\n }\n if (!hasOwnProperty(visibleKeys, key)) {\n name = '[' + key + ']';\n }\n if (!str) {\n if (ctx.seen.indexOf(desc.value) < 0) {\n if (isNull(recurseTimes)) {\n str = formatValue(ctx, desc.value, null);\n } else {\n str = formatValue(ctx, desc.value, recurseTimes - 1);\n }\n if (str.indexOf('\\n') > -1) {\n if (array) {\n str = str.split('\\n').map(function(line) {\n return ' ' + line;\n }).join('\\n').substr(2);\n } else {\n str = '\\n' + str.split('\\n').map(function(line) {\n return ' ' + line;\n }).join('\\n');\n }\n }\n } else {\n str = ctx.stylize('[Circular]', 'special');\n }\n }\n if (isUndefined(name)) {\n if (array && key.match(/^\\d+$/)) {\n return str;\n }\n name = JSON.stringify('' + key);\n if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n name = name.substr(1, name.length - 2);\n name = ctx.stylize(name, 'name');\n } else {\n name = name.replace(/'/g, \"\\\\'\")\n .replace(/\\\\\"/g, '\"')\n .replace(/(^\"|\"$)/g, \"'\");\n name = ctx.stylize(name, 'string');\n }\n }\n\n return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n var numLinesEst = 0;\n var length = output.reduce(function(prev, cur) {\n numLinesEst++;\n if (cur.indexOf('\\n') >= 0) numLinesEst++;\n return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n }, 0);\n\n if (length > 60) {\n return braces[0] +\n (base === '' ? '' : base + '\\n ') +\n ' ' +\n output.join(',\\n ') +\n ' ' +\n braces[1];\n }\n\n return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n return Array.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n return typeof arg === 'object' && arg !== null;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n return isObject(e) &&\n (objectToString(e) === '[object Error]' || e instanceof Error);\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n return arg === null ||\n typeof arg === 'boolean' ||\n typeof arg === 'number' ||\n typeof arg === 'string' ||\n typeof arg === 'symbol' || // ES6 symbol\n typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nexports.isBuffer = require('./support/isBuffer');\n\nfunction objectToString(o) {\n return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n 'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n var d = new Date();\n var time = [pad(d.getHours()),\n pad(d.getMinutes()),\n pad(d.getSeconds())].join(':');\n return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n * prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = require('inherits');\n\nexports._extend = function(origin, add) {\n // Don't do anything if add isn't an object\n if (!add || !isObject(add)) return origin;\n\n var keys = Object.keys(add);\n var i = keys.length;\n while (i--) {\n origin[keys[i]] = add[keys[i]];\n }\n return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n"]} |