{"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 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.7.0 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.7.0 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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) \n * Build: `lodash modern modularize exports=\"npm\" -o ./`\n * Copyright 2012-2015 The Dojo Foundation \n * Based on Underscore.js 1.8.3 \n * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Available under MIT 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 MIT Licensed */\n\nvar io = ('undefined' === typeof module ? {} : module.exports);\n(function() {\n\n/**\n * socket.io\n * Copyright(c) 2011 LearnBoost \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 \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 (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 \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 \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 \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 \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 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 \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 \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 \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 \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 \n\tis released under the MIT License \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;Y0){for(var af=0;af0){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'}}aa.outerHTML='\"+af+\"\";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\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 DOM 2 EventTarget Interface}\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 DOM 2 EventTarget Interface}\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 DOM 2 EventTarget Interface}\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 \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 \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('');\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 \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 \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('