diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e4e7572 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +package-lock.json +node_modules +.idea +.DS* \ No newline at end of file diff --git a/dist/flexgl.js b/dist/flexgl.js new file mode 100644 index 0000000..7c061bc --- /dev/null +++ b/dist/flexgl.js @@ -0,0 +1,2 @@ +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";function n(e,t,r,i){var a=this instanceof n?this:{},u=e;function o(e){var t=[];return e.forEach(function(e){t=t.concat(e)}),t}return a.create=function(e,t,r){Array.isArray(r)&&(r.filter(function(e){return Array.isArray(e)})&&(r=o(r)));return a[e]={type:t,name:e,data:r,location:null,size:parseInt(t.slice(3,4))||parseInt(t.slice(4,5))||1},a[e].link=function(e){return void 0!==this.data&&null!==this.data&&(this.location=u.getUniformLocation(e,this.name),function(){var e,t=this.type,r=this.location,n=this.size,i=this.data;Array.isArray(i)&&i.filter(function(e){return Array.isArray(e)})&&(i=o(i)),"float"!=t&&"int"!=t||Array.isArray(i)||ArrayBuffer.isView(i)||(i=[i]),"vec"==t.slice(0,3)||"float"==t?(e=new Float32Array(i),u["uniform"+n+"fv"](r,e)):"ivec"==t.slice(0,4)||"int"==t?(e=new Int32Array(i),u["uniform"+n+"iv"](r,e)):"mat"==t.slice(0,3)?(e=new Float32Array(i),u["uniformMatrix"+n+"fv"](r,!1,e)):"sampler2D"==t&&i.hasOwnProperty("resourceType")&&"texture"==i.resourceType&&(u.activeTexture(u.TEXTURE0+i.index),u.bindTexture(u.TEXTURE_2D,i.ptr),u.uniform1i(r,i.index))}.call(this)),this},a[e].load=function(e){return this.data=e,this},a[e].header=function(){var e="uniform "+this.type+" "+this.name,r=0;return"sampler2D"!=this.type&&(r=this.data.length/this.size),r>1&&"mat4"!=t&&(e+="["+r+"]"),e+";\n"},a[e]},a}function i(e){var t=this instanceof i?this:{},r=e,a=0;function u(e,n){var i=r[t[e].type.toUpperCase()],a=r[t[e].channel.toUpperCase()],u=t[e].dim[0],o=t[e].dim[1];t[e].data=n,r.bindTexture(r.TEXTURE_2D,t[e].ptr),r.texImage2D(r.TEXTURE_2D,0,a,u,o,0,a,i,n),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.NEAREST),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MAG_FILTER,r.NEAREST),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE),r.bindTexture(r.TEXTURE_2D,null)}return t.create=function(i,o,s,f,c,l){var d=t.hasOwnProperty(i)?t[i].index:a++;return t[i]={name:i,index:d,type:o||"float",dim:s||[512,512],channel:f||"alpha",data:null,location:null,sampler:l||null,ptr:r.createTexture()},u(i,c),null===t[i].sampler?t[i].sampler=n(r).create(i,"sampler2D",t[i]):t[i].sampler.data=t[i],t[i].link=function(e){return void 0!==this.sampler.data&&null!==this.sampler.data||(this.sampler.data=t[i]),this.sampler.link(e),this},t[i].load=function(e){return u(this.name,e),this},t[i].copyFromFBO=function(){r.bindTexture(r.TEXTURE_2D,this.ptr),r.copyTexImage2D(r.TEXTURE_2D,0,r.RGBA,0,0,this.dim[0],this.dim[1],0),r.bindTexture(r.TEXTURE_2D,null)},t[i].update=function(e,n,i){return function(e,n,i,a){var u=r[t[e].type.toUpperCase()],o=r[t[e].channel.toUpperCase()],s=a[0]||t[e].dim[0],f=a[1]||t[e].dim[1];r.bindTexture(r.TEXTURE_2D,t[e].ptr),r.texSubImage2D(r.TEXTURE_2D,0,i[0],i[1],s,f,o,u,n),r.bindTexture(r.TEXTURE_2D,null)}(this.name,e,n,i),this},t[i].resize=function(e,t){this.dim=e,u(this.name,t)},t[i].delete=function(){e.deleteTexture(this.ptr)},t[i].header=function(){return this.name==this.sampler.name?"uniform sampler2D "+this.sampler.name+";\n":""},t[i]},t}function a(e){var t=this instanceof a?this:{},r={};t.uniform=new n(e),t.attribute=new function e(t){var r=this instanceof e?this:{},n=t,i=0;function a(e,t){(Array.isArray(t)||ArrayBuffer.isView(t))&&(ArrayBuffer.isView(t)||(t=new Float32Array(t)),r[e].data=t,n.bindBuffer(n.ARRAY_BUFFER,r[e].ptr),n.bufferData(n.ARRAY_BUFFER,t,n.STATIC_DRAW))}return r.create=function(e,t,u){return r[e]={name:e,type:t||"float",data:null,location:i++,ptr:n.createBuffer(),size:parseInt(t.slice(3,4))||1},null!==u&&u.length&&a(e,u),r[e].link=function(e){return n.bindBuffer(n.ARRAY_BUFFER,this.ptr),this.location=n.getAttribLocation(e,this.name),n.vertexAttribPointer(this.location,this.size,n.FLOAT,!1,0,0),n.enableVertexAttribArray(this.location),this},r[e].load=function(e){return a(this.name,e),this},r[e].header=function(){return"attribute "+this.type+" "+this.name+";\n"},r[e].delete=function(){n.deleteBuffer(this.ptr)},r[e]},r}(e),t.texture=new i(e),t.varying=new function e(t){var r=this instanceof e?this:{};return r.create=function(e,t,n){return r[e]={name:e,type:t||"float",size:n||1},r[e].link=function(){},r[e].header=function(){var e="varying "+this.type+" "+this.name;return this.size>1&&(e+="["+this.size+"]"),e+";\n"},r[e]},r}(e),t.subroutine=new function e(){var t=this instanceof e?this:{};return t.create=function(e,r,n){return t[e]={name:e,type:r||"float",fn:n,resourceType:"subroutine"},t[e].link=function(e){return this},t[e].load=function(r){return t[e].fn=r,this},t[e].header=function(){return this.fn.toString()},t[e]},t};var u=["uniform","attribute","texture","varying","subroutine"];return t.allocate=function(e){if(-1===u.indexOf(e))throw Error("Error: Invalid resource type: "+e);var n=t[e].create.apply(null,Array.prototype.slice.call(arguments,1));return n.resourceType=e,r[n.name]=n,r.hasOwnProperty(n.name)||Object.defineProperty(r,n.name,{get:function(){return r[n.name]},set:function(e){r[n.name].load(e)}}),n},t.link=function(e,t){(Array.isArray(t)?t:Object.keys(r)).forEach(function(t){r.hasOwnProperty(t)&&r[t].link(e)})},t.get=function(e){return r[e]},t.create=t.allocate,t}function u(e,t){var r={},n=e,i={},a=new function e(t){var r=this instanceof e?this:{},n=t;return r.create=function(e,t,i){function a(e,t,r){var n=e.createShader(t);if(e.shaderSource(n,r),e.compileShader(n),e.getShaderParameter(n,e.COMPILE_STATUS))return n;console.log(e.getShaderInfoLog(n)),e.deleteShader(n)}function u(e,t){var r=/\s*(attribute|uniform)\s+\w+\s+(\w+)/;e.split("\n").forEach(function(e){var n=r.exec(e);n&&t.push(n[2])})}r[e]={name:e,vertex_shader_source:t,fragment_shader_source:i,vs:a(n,n.VERTEX_SHADER,t),fs:a(n,n.FRAGMENT_SHADER,i)},r[e].vs.deps=[],u(t,r[e].vs.deps),r[e].fs.deps=[],u(i,r[e].vs.deps)},r}(e);return r.create=function(e,t,r){e=e||"default",t=t||"default",r=r||"default";var a=[];if(i.hasOwnProperty(e)&&this.delete(e),i[e]=n.createProgram(),i[e].vs=t,i[e].fs=r,n.attachShader(i[e],i[e].vs),n.attachShader(i[e],i[e].fs),n.linkProgram(i[e]),!n.getProgramParameter(i[e],n.LINK_STATUS))throw"Error in program linking:"+n.getProgramInfoLog(i[e]);a=(a=a.concat(i[e].vs.deps)).concat(i[e].fs.deps),i[e].deps=a},r.use=function(e,r,u){return i.hasOwnProperty(e)?(n.useProgram(i[e]),t.link(i[e],i[e].deps),i[e]):(a.create(e,r,u),this.create(e,a[e].vs,a[e].fs),n.useProgram(i[e]),t.link(i[e],i[e].deps),i[e])},r.delete=function(e){i.hasOwnProperty(e)&&(n.detachShader(i[e],i[e].vs),n.detachShader(i[e],i[e].fs),n.deleteProgram(i[e]),delete i[e])},r}function o(e){var t=this instanceof o?this:{},r=e||{},n=r.container||null,i=r.canvas||document.createElement("canvas"),s=r.width||null,f=r.height||null,c=r.padding||{left:0,right:0,top:0,bottom:0},l=r.context||r.ctx||null;r.sharedFunction;"string"==typeof i&&(i="#"==i[0]?document.getElementById(cavnas.substring(1)):document.getElementById(cavnas)),n&&(n="string"==typeof n?document.getElementById(n):n,null===s&&(s=n.clientWidth),null===f&&(f=n.clientHeight)),i.width=s,i.height=f,i.style.position="absolute",i.style.marginLeft=c.left+"px",i.style.marginTop=c.top+"px",null===l&&(l=function(e){for(var t=["webgl","experimental-webgl"],r=null,n=0;nd.attribute[e],set(t){d.attribute[e].load(t)}}),t},t.uniform=function(e,r,n){return d.allocate("uniform",e,r,n),t.uniform.hasOwnProperty(e)||Object.defineProperty(t.uniform,e,{get:function(){return d.uniform[e]},set:function(t){d.uniform[e].load(t),l.isProgram(m)&&d.uniform[e].link(m)}}),t},t.uniform.serialize=function(e){var t=[];return e.forEach(function(e){t=t.concat(e)}),t},t.texture=function(e,r,n,i,a,u){return d.allocate("texture",e,r,i,a,n,u),Object.defineProperty(t.texture,e,{get:function(){return d.texture[e]},set:function(t){d.texture[e].load(t)}}),t},t.texture.update=function(e,t,r,n){d.texture[e].update(t,r,n)},t.varying=function(e,r,n){return d.allocate("varying",e,r,n),t},t.framebuffer=function(e,r,n,i){i=i||d.allocate("texture",e,r,n,"rgba",null);return h.create(e,r,n,i),t.framebuffer.hasOwnProperty(e)||Object.defineProperty(t.framebuffer,e,{get:function(){return h[e]}}),t},t.framebuffer.enableRead=function(e,t){h[e].enableRead(t)},t.bindFramebuffer=function(e){null===e?l.bindFramebuffer(l.FRAMEBUFFER,null):l.bindFramebuffer(l.FRAMEBUFFER,h[e].ptr)},t.subroutine=function(e,r,n){return d.allocate("subroutine",e,r,n),t},t.parameter=function(e){return Object.keys(e).forEach(function(t){if(l._dict[t]=e[t],Array.isArray(l._dict[t])){var r=0;Object.defineProperty(l._dict,t,{get:function(){return e[t][r++]},set:function(e){r=0,l._dict[t]=e}})}else if("object"==typeof l._dict[t]){var n=Object.keys(l._dict[t]);fxgl.uniform("dict"+t,"float",n.map(e=>l._dict[t][e]))}}),t},t.dictionary=t.parameter,t.shader=p.shader,t.app=function(e,r){return function(n){return m=p.use(e,r.vertex_shader_source,r.fragment_shader_source),r.render.call(t,n)}},t.dimension=function(){return[i.width,i.height]},t}r.r(t),"undefined"!=typeof window&&(window.FlexGL=o)}]); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vc3JjL3VuaWZvcm0uanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3RleHR1cmUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3Jlc291cmNlLmpzIiwid2VicGFjazovLy8uL3NyYy9hdHRyaWJ1dGUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3ZhcnlpbmcuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3N1YnJvdXRpbmUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3Byb2dyYW0uanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3NoYWRlci5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvZmxleGdsLmpzIiwid2VicGFjazovLy8uL3NyYy9mcmFtZWJ1ZmZlci5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvYnVuZGxlLmpzIl0sIm5hbWVzIjpbImluc3RhbGxlZE1vZHVsZXMiLCJfX3dlYnBhY2tfcmVxdWlyZV9fIiwibW9kdWxlSWQiLCJleHBvcnRzIiwibW9kdWxlIiwiaSIsImwiLCJtb2R1bGVzIiwiY2FsbCIsIm0iLCJjIiwiZCIsIm5hbWUiLCJnZXR0ZXIiLCJvIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwiZ2V0IiwiciIsIlN5bWJvbCIsInRvU3RyaW5nVGFnIiwidmFsdWUiLCJ0IiwibW9kZSIsIl9fZXNNb2R1bGUiLCJucyIsImNyZWF0ZSIsImtleSIsImJpbmQiLCJuIiwib2JqZWN0IiwicHJvcGVydHkiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsInAiLCJzIiwiVW5pZm9ybSIsImdsQ29udGV4dCIsInR5cGUiLCJkYXRhIiwidW5pZm9ybSIsInRoaXMiLCJjdHgiLCJzZXJpYWxpemVBcnJheSIsImFycmF5T2ZBcnJheSIsInNhIiwiZm9yRWFjaCIsImEiLCJjb25jYXQiLCJBcnJheSIsImlzQXJyYXkiLCJmaWx0ZXIiLCJsb2NhdGlvbiIsInNpemUiLCJwYXJzZUludCIsInNsaWNlIiwibGluayIsInByb2dyYW0iLCJnZXRVbmlmb3JtTG9jYXRpb24iLCJidWYiLCJBcnJheUJ1ZmZlciIsImlzVmlldyIsIkZsb2F0MzJBcnJheSIsIkludDMyQXJyYXkiLCJyZXNvdXJjZVR5cGUiLCJhY3RpdmVUZXh0dXJlIiwiVEVYVFVSRTAiLCJpbmRleCIsImJpbmRUZXh0dXJlIiwiVEVYVFVSRV8yRCIsInB0ciIsInVuaWZvcm0xaSIsImxvYWQiLCJoZWFkZXIiLCJsZW4iLCJsZW5ndGgiLCJUZXh0dXJlIiwidGV4dHVyZSIsInRleHR1cmVJRCIsInNldFRleHR1cmUiLCJ0ZXhEYXRhIiwidG9VcHBlckNhc2UiLCJmb3JtYXQiLCJjaGFubmVsIiwid2lkdGgiLCJkaW0iLCJoZWlnaHQiLCJ0ZXhJbWFnZTJEIiwidGV4UGFyYW1ldGVyaSIsIlRFWFRVUkVfTUlOX0ZJTFRFUiIsIk5FQVJFU1QiLCJURVhUVVJFX01BR19GSUxURVIiLCJURVhUVVJFX1dSQVBfUyIsIkNMQU1QX1RPX0VER0UiLCJURVhUVVJFX1dSQVBfVCIsInNhbXBsZXIiLCJ0ZXhJbmRleCIsImNyZWF0ZVRleHR1cmUiLCJjb3B5RnJvbUZCTyIsImNvcHlUZXhJbWFnZTJEIiwiUkdCQSIsInVwZGF0ZSIsIm9mZnNldCIsInRleFN1YkltYWdlMkQiLCJ1cGRhdGVUZXh0dXJlIiwicmVzaXplIiwiZGVsZXRlIiwiZGVsZXRlVGV4dHVyZSIsIlJlc291cmNlIiwicmVzb3VyY2UiLCJncHVSZXNvdXJjZXMiLCJhdHRyaWJ1dGUiLCJBdHRyaWJ1dGUiLCJhdHRyaWJ1dGVJRCIsInNldEF0dHJpYnV0ZSIsImJpbmRCdWZmZXIiLCJBUlJBWV9CVUZGRVIiLCJidWZmZXJEYXRhIiwiU1RBVElDX0RSQVciLCJjcmVhdGVCdWZmZXIiLCJnZXRBdHRyaWJMb2NhdGlvbiIsInZlcnRleEF0dHJpYlBvaW50ZXIiLCJGTE9BVCIsImVuYWJsZVZlcnRleEF0dHJpYkFycmF5IiwiYXJyYXlCdWZmZXIiLCJkZWxldGVCdWZmZXIiLCJ2YXJ5aW5nIiwiVmFyeWluZyIsInN1YnJvdXRpbmUiLCJTdWJyb3V0aW5lIiwiZm4iLCJ0b1N0cmluZyIsInJlc291cmNlVHlwZXMiLCJhbGxvY2F0ZSIsImluZGV4T2YiLCJFcnJvciIsInJlcyIsImFwcGx5IiwiYXJndW1lbnRzIiwic2V0IiwicmVzb3VyY2VfbmFtZXMiLCJrZXlzIiwicmVzb3VyY2VOYW1lIiwiUHJvZ3JhbSIsInJlc291cmNlcyIsImtlcm5lbHMiLCJzaGFkZXIiLCJTaGFkZXIiLCJ2ZXJ0ZXhfc2hhZGVyX3NvdXJjZSIsImZyYWdtZW50X3NoYWRlcl9zb3VyY2UiLCJjcmVhdGVTaGFkZXIiLCJnbCIsInNvdXJjZSIsInNoYWRlclNvdXJjZSIsImNvbXBpbGVTaGFkZXIiLCJnZXRTaGFkZXJQYXJhbWV0ZXIiLCJDT01QSUxFX1NUQVRVUyIsImNvbnNvbGUiLCJsb2ciLCJnZXRTaGFkZXJJbmZvTG9nIiwiZGVsZXRlU2hhZGVyIiwiYWRkRGVwcyIsImRlcHMiLCJyZSIsInNwbGl0IiwidiIsInJlc3VsdCIsImV4ZWMiLCJwdXNoIiwidnMiLCJWRVJURVhfU0hBREVSIiwiZnMiLCJGUkFHTUVOVF9TSEFERVIiLCJjcmVhdGVQcm9ncmFtIiwiYXR0YWNoU2hhZGVyIiwibGlua1Byb2dyYW0iLCJnZXRQcm9ncmFtUGFyYW1ldGVyIiwiTElOS19TVEFUVVMiLCJnZXRQcm9ncmFtSW5mb0xvZyIsInVzZSIsInVzZVByb2dyYW0iLCJkZXRhY2hTaGFkZXIiLCJkZWxldGVQcm9ncmFtIiwiRmxleEdMIiwiYXJnIiwiZmxleGdsIiwib3B0aW9ucyIsImNvbnRhaW5lciIsImNhbnZhcyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudCIsInBhZGRpbmciLCJsZWZ0IiwicmlnaHQiLCJ0b3AiLCJib3R0b20iLCJjb250ZXh0Iiwic2hhcmVkRnVuY3Rpb24iLCJnZXRFbGVtZW50QnlJZCIsImNhdm5hcyIsInN1YnN0cmluZyIsImNsaWVudFdpZHRoIiwiY2xpZW50SGVpZ2h0Iiwic3R5bGUiLCJwb3NpdGlvbiIsIm1hcmdpbkxlZnQiLCJtYXJnaW5Ub3AiLCJuYW1lcyIsImdldENvbnRleHQiLCJlIiwic2V0dXBXZWJHTCIsIl9kaWN0IiwiZW52IiwiZGljdCIsImRpY3Rpb25hcnkiLCJmcmFtZWJ1ZmZlcnMiLCJGcmFtZWJ1ZmZlciIsImZyYW1lYnVmZmVyIiwiY3JlYXRlRnJhbWVidWZmZXIiLCJiaW5kRnJhbWVidWZmZXIiLCJGUkFNRUJVRkZFUiIsImZyYW1lYnVmZmVyVGV4dHVyZTJEIiwiQ09MT1JfQVRUQUNITUVOVDAiLCJlbmFibGVSZWFkIiwiYmluZFJlbmRlcmJ1ZmZlciIsIlJFTkRFUkJVRkZFUiIsImRlbGV0ZVJlbmRlcmJ1ZmZlciIsInJlbmRlcmJ1ZmZlciIsImRlbGV0ZUZyYW1lYnVmZmVyIiwicmVhbFByb2dyYW0iLCJibGVuZEV4dCIsImdldEV4dGVuc2lvbiIsImVuYWJsZUV4dGVuc2lvbiIsImV4dGVuc2lvbnMiLCJleHRlbnNpb24iLCJleHRQcm9wcyIsImVwIiwiZXh0IiwiTUFYX0VYVCIsIk1JTl9FWFQiLCJhcHBlbmRDaGlsZCIsIltvYmplY3QgT2JqZWN0XSIsImlzUHJvZ3JhbSIsInNlcmlhbGl6ZSIsImFvYSIsImZiTmFtZSIsInBhcmFtZXRlciIsImtleVZhbHVlUGFpcnMiLCJuZXdBcnJheSIsImRpY3RLZXlzIiwiZnhnbCIsIm1hcCIsImFwcCIsImFyZ3MiLCJyZW5kZXIiLCJkaW1lbnNpb24iLCJ3aW5kb3ciXSwibWFwcGluZ3MiOiJhQUNBLElBQUFBLEtBR0EsU0FBQUMsRUFBQUMsR0FHQSxHQUFBRixFQUFBRSxHQUNBLE9BQUFGLEVBQUFFLEdBQUFDLFFBR0EsSUFBQUMsRUFBQUosRUFBQUUsSUFDQUcsRUFBQUgsRUFDQUksR0FBQSxFQUNBSCxZQVVBLE9BTkFJLEVBQUFMLEdBQUFNLEtBQUFKLEVBQUFELFFBQUFDLElBQUFELFFBQUFGLEdBR0FHLEVBQUFFLEdBQUEsRUFHQUYsRUFBQUQsUUFLQUYsRUFBQVEsRUFBQUYsRUFHQU4sRUFBQVMsRUFBQVYsRUFHQUMs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S0FBQTBHLEdBQUF6TSxRQUFBLFNBQUFuQixHQUVBLEdBREFlLEVBQUF5SyxNQUFBeEwsR0FBQTROLEVBQUE1TixHQUNBc0IsTUFBQUMsUUFBQVIsRUFBQXlLLE1BQUF4TCxJQUFBLENBQ0EsSUFBQXZCLEVBQUEsRUFDQVUsT0FBQUMsZUFBQTJCLEVBQUF5SyxNQUFBeEwsR0FDQVYsSUFBQSxXQUNBLE9BQUFzTyxFQUFBNU4sR0FBQXZCLE1BRUF1SSxJQUFBLFNBQUE2RyxHQUNBcFAsRUFBQSxFQUNBc0MsRUFBQXlLLE1BQUF4TCxHQUFBNk4sVUFHYSxvQkFBQTlNLEVBQUF5SyxNQUFBeEwsR0FBQSxDQUNiLElBQUE4TixFQUFBM08sT0FBQStILEtBQUFuRyxFQUFBeUssTUFBQXhMLElBQ0ErTixLQUFBbE4sUUFBQSxPQUFBYixFQUFBLFFBQUE4TixFQUFBRSxJQUFBalAsR0FBQWdDLEVBQUF5SyxNQUFBeEwsR0FBQWpCLFFBR0ErSyxHQUdBQSxFQUFBNkIsV0FBQTdCLEVBQUE2RCxVQUNBN0QsRUFBQXZDLE9BQUF6RixFQUFBeUYsT0FHQXVDLEVBQUFtRSxJQUFBLFNBQUFqUCxFQUFBK0ssR0FDQSxnQkFBQW1FLEdBRUEsT0FEQXhCLEVBQUE1SyxFQUFBMEgsSUFBQXhLLEVBQUErSyxFQUFBdEMscUJBQUFzQyxFQUFBckMsd0JBQ0FxQyxFQUFBb0UsT0FBQXZQLEtBQUFrTCxFQUFBb0UsS0FJQXBFLEVBQUFzRSxVQUFBLFdBQ0EsT0FBQW5FLEVBQUF4RyxNQUFBd0csRUFBQXRHLFNBR0FtRyxTRTNRQSxvQkFBQXVFLFNBQ0FBLE9BQUF6RSIsImZpbGUiOiJmbGV4Z2wuanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBnZXR0ZXIgfSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiBcdFx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG4gXHRcdH1cbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbiBcdH07XG5cbiBcdC8vIGNyZWF0ZSBhIGZha2UgbmFtZXNwYWNlIG9iamVjdFxuIFx0Ly8gbW9kZSAmIDE6IHZhbHVlIGlzIGEgbW9kdWxlIGlkLCByZXF1aXJlIGl0XG4gXHQvLyBtb2RlICYgMjogbWVyZ2UgYWxsIHByb3BlcnRpZXMgb2YgdmFsdWUgaW50byB0aGUgbnNcbiBcdC8vIG1vZGUgJiA0OiByZXR1cm4gdmFsdWUgd2hlbiBhbHJlYWR5IG5zIG9iamVjdFxuIFx0Ly8gbW9kZSAmIDh8MTogYmVoYXZlIGxpa2UgcmVxdWlyZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy50ID0gZnVuY3Rpb24odmFsdWUsIG1vZGUpIHtcbiBcdFx0aWYobW9kZSAmIDEpIHZhbHVlID0gX193ZWJwYWNrX3JlcXVpcmVfXyh2YWx1ZSk7XG4gXHRcdGlmKG1vZGUgJiA4KSByZXR1cm4gdmFsdWU7XG4gXHRcdGlmKChtb2RlICYgNCkgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAmJiB2YWx1ZS5fX2VzTW9kdWxlKSByZXR1cm4gdmFsdWU7XG4gXHRcdHZhciBucyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18ucihucyk7XG4gXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShucywgJ2RlZmF1bHQnLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2YWx1ZSB9KTtcbiBcdFx0aWYobW9kZSAmIDIgJiYgdHlwZW9mIHZhbHVlICE9ICdzdHJpbmcnKSBmb3IodmFyIGtleSBpbiB2YWx1ZSkgX193ZWJwYWNrX3JlcXVpcmVfXy5kKG5zLCBrZXksIGZ1bmN0aW9uKGtleSkgeyByZXR1cm4gdmFsdWVba2V5XTsgfS5iaW5kKG51bGwsIGtleSkpO1xuIFx0XHRyZXR1cm4gbnM7XG4gXHR9O1xuXG4gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gXHRcdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHsgcmV0dXJuIG1vZHVsZTsgfTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgJ2EnLCBnZXR0ZXIpO1xuIFx0XHRyZXR1cm4gZ2V0dGVyO1xuIFx0fTtcblxuIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMCk7XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBVbmlmb3JtKGdsQ29udGV4dCwgbmFtZSwgdHlwZSwgZGF0YSkge1xuXG4gICAgdmFyIHVuaWZvcm0gPSAodGhpcyBpbnN0YW5jZW9mIFVuaWZvcm0pID8gdGhpcyA6IHt9LFxuICAgICAgICBjdHggPSBnbENvbnRleHQ7XG5cbiAgICBmdW5jdGlvbiBzZXJpYWxpemVBcnJheShhcnJheU9mQXJyYXkpIHtcbiAgICAgICAgdmFyIHNhID0gW107XG4gICAgICAgIGFycmF5T2ZBcnJheS5mb3JFYWNoKGZ1bmN0aW9uKGEpe1xuICAgICAgICAgICAgc2EgPSBzYS5jb25jYXQoYSk7XG4gICAgICAgIH0pXG4gICAgICAgIHJldHVybiBzYTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRVbmlmb3JtKCkge1xuICAgICAgICB2YXIgdHlwZSA9IHRoaXMudHlwZSxcbiAgICAgICAgICAgIGxvY2F0aW9uID0gdGhpcy5sb2NhdGlvbixcbiAgICAgICAgICAgIHNpemUgPSB0aGlzLnNpemUsXG4gICAgICAgICAgICBkYXRhID0gdGhpcy5kYXRhO1xuXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgICAgIHZhciBoYXNBcnJheSA9IGRhdGEuZmlsdGVyKGZ1bmN0aW9uKGQpe3JldHVybiBBcnJheS5pc0FycmF5KGQpO30pO1xuICAgICAgICAgICAgaWYoaGFzQXJyYXkpXG4gICAgICAgICAgICAgICAgZGF0YSA9IHNlcmlhbGl6ZUFycmF5KGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoKHR5cGUgPT0gJ2Zsb2F0JyB8fCB0eXBlID09ICdpbnQnKSAmJiAhQXJyYXkuaXNBcnJheShkYXRhKSAmJiAhQXJyYXlCdWZmZXIuaXNWaWV3KGRhdGEpKVxuICAgICAgICAgICAgZGF0YSA9IFtkYXRhXTtcblxuICAgICAgICB2YXIgYnVmO1xuICAgICAgICBpZiAodHlwZS5zbGljZSgwLDMpID09ICd2ZWMnIHx8IHR5cGUgPT0gJ2Zsb2F0Jykge1xuICAgICAgICAgICAgYnVmID0gbmV3IEZsb2F0MzJBcnJheShkYXRhKTtcbiAgICAgICAgICAgIGN0eFsndW5pZm9ybScgKyBzaXplICsgJ2Z2J10obG9jYXRpb24sIGJ1Zik7XG4gICAgICAgIH0gZWxzZSBpZih0eXBlLnNsaWNlKDAsNCkgPT0gJ2l2ZWMnIHx8IHR5cGUgPT0gJ2ludCcpe1xuICAgICAgICAgICAgYnVmID0gbmV3IEludDMyQXJyYXkoZGF0YSk7XG4gICAgICAgICAgICBjdHhbJ3VuaWZvcm0nICsgc2l6ZSArICdpdiddKGxvY2F0aW9uLCBidWYpO1xuICAgICAgICB9IGVsc2UgaWYodHlwZS5zbGljZSgwLDMpID09ICdtYXQnKSB7XG4gICAgICAgICAgICBidWYgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEpO1xuICAgICAgICAgICAgY3R4Wyd1bmlmb3JtTWF0cml4JyArIHNpemUgKyAnZnYnXShsb2NhdGlvbiwgZmFsc2UsIGJ1Zik7XG4gICAgICAgIH0gZWxzZSBpZih0eXBlID09ICdzYW1wbGVyMkQnKSB7XG4gICAgICAgICAgICBpZihkYXRhLmhhc093blByb3BlcnR5KCdyZXNvdXJjZVR5cGUnKSAmJiBkYXRhLnJlc291cmNlVHlwZSA9PSAndGV4dHVyZScpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnYmluZCAnICsgZGF0YS5pbmRleCk7XG4gICAgICAgICAgICAgICAgY3R4LmFjdGl2ZVRleHR1cmUoY3R4LlRFWFRVUkUwICsgZGF0YS5pbmRleCk7XG4gICAgICAgICAgICAgICAgY3R4LmJpbmRUZXh0dXJlKGN0eC5URVhUVVJFXzJELCBkYXRhLnB0cik7XG4gICAgICAgICAgICAgICAgY3R4LnVuaWZvcm0xaShsb2NhdGlvbiwgZGF0YS5pbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB1bmlmb3JtLmNyZWF0ZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIGRhdGEpIHtcblxuICAgICAgICBpZihBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgICAgICB2YXIgaGFzQXJyYXkgPSBkYXRhLmZpbHRlcihmdW5jdGlvbihkKXtyZXR1cm4gQXJyYXkuaXNBcnJheShkKTt9KTtcbiAgICAgICAgICAgIGlmKGhhc0FycmF5KVxuICAgICAgICAgICAgICAgIGRhdGEgPSBzZXJpYWxpemVBcnJheShkYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHVuaWZvcm1bbmFtZV0gPSB7XG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICBsb2NhdGlvbjogbnVsbCxcbiAgICAgICAgICAgIHNpemU6IHBhcnNlSW50KHR5cGUuc2xpY2UoMyw0KSkgfHwgcGFyc2VJbnQodHlwZS5zbGljZSg0LDUpKSB8fCAxXG4gICAgICAgIH07XG5cbiAgICAgICAgdW5pZm9ybVtuYW1lXS5saW5rID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICAgICAgICAgICAgaWYodHlwZW9mIHRoaXMuZGF0YSAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5kYXRhICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhdGlvbiA9IGN0eC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgdGhpcy5uYW1lKTtcbiAgICAgICAgICAgICAgICBzZXRVbmlmb3JtLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcblxuICAgICAgICB1bmlmb3JtW25hbWVdLmxvYWQgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH07XG5cbiAgICAgICAgdW5pZm9ybVtuYW1lXS5oZWFkZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBoZWFkZXIgPSAndW5pZm9ybSAnICsgdGhpcy50eXBlICsgJyAnICsgdGhpcy5uYW1lLFxuICAgICAgICAgICAgICAgIGxlbiA9IDA7XG5cbiAgICAgICAgICAgIGlmKHRoaXMudHlwZSAhPSAnc2FtcGxlcjJEJykge1xuICAgICAgICAgICAgICAgIGxlbiA9IHRoaXMuZGF0YS5sZW5ndGggLyB0aGlzLnNpemU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vVE9ETzogZml4IGRlY2xhcmF0aW9uIGZvciBtYXRyaXhcbiAgICAgICAgICAgIGlmKGxlbiA+IDEgJiYgdHlwZSAhPSAnbWF0NCcpIHtcbiAgICAgICAgICAgICAgICBoZWFkZXIgKz0gJ1snICsgbGVuICsgJ10nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGhlYWRlciArICc7XFxuJztcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gdW5pZm9ybVtuYW1lXTtcbiAgICB9XG5cblxuICAgIHJldHVybiB1bmlmb3JtO1xufVxuIiwiaW1wb3J0IFVuaWZvcm0gZnJvbSBcIi4vdW5pZm9ybVwiO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBUZXh0dXJlKGdsQ29udGV4dCkge1xuXG4gICAgdmFyIHRleHR1cmUgPSAodGhpcyBpbnN0YW5jZW9mIFRleHR1cmUpID8gdGhpcyA6IHt9LFxuICAgICAgICBjdHggPSBnbENvbnRleHQsXG4gICAgICAgIHRleHR1cmVJRCA9IDA7XG5cbiAgICBmdW5jdGlvbiBzZXRUZXh0dXJlKG5hbWUsIHRleERhdGEpIFxuICAgIHtcbiAgICAgICAgdmFyIHR5cGUgPSBjdHhbdGV4dHVyZVtuYW1lXS50eXBlLnRvVXBwZXJDYXNlKCldLFxuICAgICAgICAgICAgZm9ybWF0ID0gY3R4W3RleHR1cmVbbmFtZV0uY2hhbm5lbC50b1VwcGVyQ2FzZSgpXSxcbiAgICAgICAgICAgIHdpZHRoID0gdGV4dHVyZVtuYW1lXS5kaW1bMF0sXG4gICAgICAgICAgICBoZWlnaHQgPSB0ZXh0dXJlW25hbWVdLmRpbVsxXTtcblxuICAgICAgICB0ZXh0dXJlW25hbWVdLmRhdGEgPSB0ZXhEYXRhO1xuXG4gICAgICAgIGN0eC5iaW5kVGV4dHVyZShjdHguVEVYVFVSRV8yRCwgdGV4dHVyZVtuYW1lXS5wdHIpO1xuICAgICAgICBjdHgudGV4SW1hZ2UyRChjdHguVEVYVFVSRV8yRCwgMCwgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCAwLCBmb3JtYXQsIHR5cGUsIHRleERhdGEpO1xuICAgICAgICBjdHgudGV4UGFyYW1ldGVyaShjdHguVEVYVFVSRV8yRCwgY3R4LlRFWFRVUkVfTUlOX0ZJTFRFUiwgY3R4Lk5FQVJFU1QpO1xuICAgICAgICBjdHgudGV4UGFyYW1ldGVyaShjdHguVEVYVFVSRV8yRCwgY3R4LlRFWFRVUkVfTUFHX0ZJTFRFUiwgY3R4Lk5FQVJFU1QpO1xuICAgICAgICBjdHgudGV4UGFyYW1ldGVyaShjdHguVEVYVFVSRV8yRCwgY3R4LlRFWFRVUkVfV1JBUF9TLCBjdHguQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGN0eC50ZXhQYXJhbWV0ZXJpKGN0eC5URVhUVVJFXzJELCBjdHguVEVYVFVSRV9XUkFQX1QsIGN0eC5DTEFNUF9UT19FREdFKTtcbiAgICAgICAgY3R4LmJpbmRUZXh0dXJlKGN0eC5URVhUVVJFXzJELCBudWxsKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVUZXh0dXJlKG5hbWUsIHRleERhdGEsIG9mZnNldCwgZGltKSB7XG4gICAgICAgIHZhciB0eXBlID0gY3R4W3RleHR1cmVbbmFtZV0udHlwZS50b1VwcGVyQ2FzZSgpXSxcbiAgICAgICAgICAgIGZvcm1hdCA9IGN0eFt0ZXh0dXJlW25hbWVdLmNoYW5uZWwudG9VcHBlckNhc2UoKV0sXG4gICAgICAgICAgICB3aWR0aCA9IGRpbVswXSB8fCB0ZXh0dXJlW25hbWVdLmRpbVswXSxcbiAgICAgICAgICAgIGhlaWdodCA9IGRpbVsxXSB8fCB0ZXh0dXJlW25hbWVdLmRpbVsxXTtcblxuICAgICAgICBjdHguYmluZFRleHR1cmUoY3R4LlRFWFRVUkVfMkQsIHRleHR1cmVbbmFtZV0ucHRyKTtcbiAgICAgICAgY3R4LnRleFN1YkltYWdlMkQoY3R4LlRFWFRVUkVfMkQsIDAsIG9mZnNldFswXSwgb2Zmc2V0WzFdLCB3aWR0aCwgaGVpZ2h0LCBmb3JtYXQsIHR5cGUsIHRleERhdGEpO1xuICAgICAgICBjdHguYmluZFRleHR1cmUoY3R4LlRFWFRVUkVfMkQsIG51bGwpO1xuICAgIH1cblxuICAgIC8vIFRPRE86IEFkZCBzdXBwb3J0IGZvciB0ZXh0dXJlIGNvbXByZXNzaW9uXG4gICAgLy8gZnVuY3Rpb24gY29tcHJlc3NUZXh0dXJlKHRleERhdGEpIHtcbiAgICAvL1xuICAgIC8vICAgICB2YXIgZXh0ID0gKFxuICAgIC8vICAgICAgIGN0eC5nZXRFeHRlbnNpb24oXCJXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfczN0Y1wiKSB8fFxuICAgIC8vICAgICAgIGN0eC5nZXRFeHRlbnNpb24oXCJNT1pfV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX3MzdGNcIikgfHxcbiAgICAvLyAgICAgICBjdHguZ2V0RXh0ZW5zaW9uKFwiV0VCS0lUX1dFQkdMX2NvbXByZXNzZWRfdGV4dHVyZV9zM3RjXCIpXG4gICAgLy8gICAgICk7XG4gICAgLy9cbiAgICAvLyAgICAgY3R4LmNvbXByZXNzZWRUZXhJbWFnZTJEKGN0eC5URVhUVVJFXzJELCAwLCBleHQuQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUM19FWFQsIHRleHR1cmVbbmFtZV0uZGltWzBdLCB0ZXh0dXJlW25hbWVdLmRpbVsxXSwgMCwgdGV4RGF0YSk7XG4gICAgLy8gICAgIGN0eC50ZXhQYXJhbWV0ZXJpKGN0eC5URVhUVVJFXzJELCBjdHguVEVYVFVSRV9NQUdfRklMVEVSLCBjdHguTElORUFSKTtcbiAgICAvLyAgICAgY3R4LnRleFBhcmFtZXRlcmkoY3R4LlRFWFRVUkVfMkQsIGN0eC5URVhUVVJFX01JTl9GSUxURVIsIGN0eC5MSU5FQVIpO1xuICAgIC8vIH1cblxuICAgIHRleHR1cmUuY3JlYXRlID0gZnVuY3Rpb24obmFtZSwgdHlwZSwgZGltLCBjaGFubmVsLCBkYXRhLCBzYW1wbGVyKSB7XG4gICAgICAgIHZhciB0ZXhJbmRleCA9ICh0ZXh0dXJlLmhhc093blByb3BlcnR5KG5hbWUpKSA/IHRleHR1cmVbbmFtZV0uaW5kZXggOiB0ZXh0dXJlSUQrKztcbiAgICAgICAgdGV4dHVyZVtuYW1lXSA9IHtcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgICBpbmRleDogdGV4SW5kZXgsXG4gICAgICAgICAgICB0eXBlOiB0eXBlIHx8IFwiZmxvYXRcIixcbiAgICAgICAgICAgIGRpbTogZGltIHx8IFs1MTIsIDUxMl0sXG4gICAgICAgICAgICBjaGFubmVsOiBjaGFubmVsIHx8IFwiYWxwaGFcIixcbiAgICAgICAgICAgIGRhdGE6IG51bGwsXG4gICAgICAgICAgICBsb2NhdGlvbjogbnVsbCxcbiAgICAgICAgICAgIHNhbXBsZXI6IHNhbXBsZXIgfHwgbnVsbCxcbiAgICAgICAgICAgIHB0cjogY3R4LmNyZWF0ZVRleHR1cmUoKVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIGlmKGRhdGEgIT09IG51bGwgJiYgZGF0YS5sZW5ndGgpXG4gICAgICAgIHNldFRleHR1cmUobmFtZSwgZGF0YSk7XG5cbiAgICAgICAgaWYgKHRleHR1cmVbbmFtZV0uc2FtcGxlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGV4dHVyZVtuYW1lXS5zYW1wbGVyID0gVW5pZm9ybShjdHgpLmNyZWF0ZShuYW1lLCAnc2FtcGxlcjJEJywgdGV4dHVyZVtuYW1lXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZXh0dXJlW25hbWVdLnNhbXBsZXIuZGF0YSA9IHRleHR1cmVbbmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICB0ZXh0dXJlW25hbWVdLmxpbmsgPSBmdW5jdGlvbihwcm9ncmFtKSB7XG4gICAgICAgICAgICAvLyBpZiAodGhpcy5kYXRhICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gY3R4LmFjdGl2ZVRleHR1cmUoY3R4LlRFWFRVUkUwICsgdGhpcy5pbmRleCk7XG4gICAgICAgICAgICAgICAgLy8gY3R4LmJpbmRUZXh0dXJlKGN0eC5URVhUVVJFXzJELCB0aGlzLnB0cik7XG4gICAgICAgICAgICAgICAgLy8gdGhpcy5sb2NhdGlvbiA9IGN0eC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgdGhpcy5uYW1lKTtcbiAgICAgICAgICAgICAgICAvLyBjdHgudW5pZm9ybTFpKHRoaXMubG9jYXRpb24sIHRoaXMuaW5kZXgpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YodGhpcy5zYW1wbGVyLmRhdGEpID09ICd1bmRlZmluZWQnIHx8IHRoaXMuc2FtcGxlci5kYXRhID09PSBudWxsKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNhbXBsZXIuZGF0YSA9IHRleHR1cmVbbmFtZV07XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNhbXBsZXIubGluayhwcm9ncmFtKTtcbiAgICAgICAgICAgIC8vIH1lbHNle1xuICAgICAgICAgICAgLy8gICAgIGNvbnNvbGUubG9nKCd0ZXh0dXJlIGRhdGEgaXMgbnVsbCEhIScpXG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHRleHR1cmVbbmFtZV0ubG9hZCA9IGZ1bmN0aW9uKHRleERhdGEpIHtcbiAgICAgICAgICAgIHNldFRleHR1cmUodGhpcy5uYW1lLCB0ZXhEYXRhKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgdGV4dHVyZVtuYW1lXS5jb3B5RnJvbUZCTyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgY3R4LmJpbmRUZXh0dXJlKGN0eC5URVhUVVJFXzJELCB0aGlzLnB0cik7XG4gICAgICAgICAgICBjdHguY29weVRleEltYWdlMkQoXG4gICAgICAgICAgICAgICAgY3R4LlRFWFRVUkVfMkQsXG4gICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICBjdHguUkdCQSxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgdGhpcy5kaW1bMF0sXG4gICAgICAgICAgICAgICAgdGhpcy5kaW1bMV0sXG4gICAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGN0eC5iaW5kVGV4dHVyZShjdHguVEVYVFVSRV8yRCwgbnVsbCk7XG4gICAgICAgIH1cblxuICAgICAgICB0ZXh0dXJlW25hbWVdLnVwZGF0ZSA9IGZ1bmN0aW9uKHRleERhdGEsIG9mZnNldCwgZGltKSB7XG4gICAgICAgICAgICB1cGRhdGVUZXh0dXJlKHRoaXMubmFtZSwgdGV4RGF0YSwgb2Zmc2V0LCBkaW0pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHRleHR1cmVbbmFtZV0ucmVzaXplID0gZnVuY3Rpb24oZGltLCBkYXRhKSB7XG4gICAgICAgICAgICB0aGlzLmRpbSA9IGRpbTtcbiAgICAgICAgICAgIHNldFRleHR1cmUodGhpcy5uYW1lLCBkYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRleHR1cmVbbmFtZV0uZGVsZXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBnbENvbnRleHQuZGVsZXRlVGV4dHVyZSh0aGlzLnB0cik7XG4gICAgICAgIH1cblxuICAgICAgICB0ZXh0dXJlW25hbWVdLmhlYWRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubmFtZSA9PSB0aGlzLnNhbXBsZXIubmFtZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3VuaWZvcm0gc2FtcGxlcjJEICcgKyB0aGlzLnNhbXBsZXIubmFtZSArICc7XFxuJztcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGV4dHVyZVtuYW1lXTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGV4dHVyZTtcbn1cbiIsImltcG9ydCBVbmlmb3JtIGZyb20gJy4vdW5pZm9ybSc7XG5pbXBvcnQgQXR0cmlidXRlIGZyb20gJy4vYXR0cmlidXRlJztcbmltcG9ydCBUZXh0dXJlIGZyb20gJy4vdGV4dHVyZSc7XG5pbXBvcnQgVmFyeWluZyBmcm9tICcuL3ZhcnlpbmcnO1xuaW1wb3J0IFN1YnJvdXRpbmUgZnJvbSAnLi9zdWJyb3V0aW5lJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gUmVzb3VyY2UoZ2xDb250ZXh0KSBcbntcbiAgICB2YXIgcmVzb3VyY2UgPSAodGhpcyBpbnN0YW5jZW9mIFJlc291cmNlKSA/IHRoaXMgOiB7fSxcbiAgICAgICAgZ3B1UmVzb3VyY2VzID0ge307XG5cbiAgICByZXNvdXJjZS51bmlmb3JtID0gbmV3IFVuaWZvcm0oZ2xDb250ZXh0KTtcbiAgICByZXNvdXJjZS5hdHRyaWJ1dGUgPSBuZXcgQXR0cmlidXRlKGdsQ29udGV4dCk7XG4gICAgcmVzb3VyY2UudGV4dHVyZSA9IG5ldyBUZXh0dXJlKGdsQ29udGV4dCk7XG4gICAgcmVzb3VyY2UudmFyeWluZyA9IG5ldyBWYXJ5aW5nKGdsQ29udGV4dCk7XG4gICAgcmVzb3VyY2Uuc3Vicm91dGluZSA9IG5ldyBTdWJyb3V0aW5lKCk7XG5cbiAgICB2YXIgcmVzb3VyY2VUeXBlcyA9IFsndW5pZm9ybScsICdhdHRyaWJ1dGUnLCAndGV4dHVyZScsICd2YXJ5aW5nJywgJ3N1YnJvdXRpbmUnXTtcblxuICAgIHJlc291cmNlLmFsbG9jYXRlID0gZnVuY3Rpb24odHlwZSkgXG4gICAge1xuICAgICAgICBpZiAocmVzb3VyY2VUeXBlcy5pbmRleE9mKHR5cGUpID09PSAtMSkgIHsgdGhyb3cgRXJyb3IoXCJFcnJvcjogSW52YWxpZCByZXNvdXJjZSB0eXBlOiBcIiArIHR5cGUpOyB9XG4gICAgICAgIFxuICAgICAgICB2YXIgcmVzID0gcmVzb3VyY2VbdHlwZV0uY3JlYXRlLmFwcGx5KG51bGwsIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgICAgICByZXMucmVzb3VyY2VUeXBlID0gdHlwZTtcbiAgICAgICAgZ3B1UmVzb3VyY2VzW3Jlcy5uYW1lXSA9IHJlcztcblxuICAgICAgICBpZiAoIWdwdVJlc291cmNlcy5oYXNPd25Qcm9wZXJ0eShyZXMubmFtZSkpIFxuICAgICAgICB7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZ3B1UmVzb3VyY2VzLCByZXMubmFtZSwge1xuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBncHVSZXNvdXJjZXNbcmVzLm5hbWVdO30sXG4gICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihkYXRhKSB7IGdwdVJlc291cmNlc1tyZXMubmFtZV0ubG9hZChkYXRhKTt9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG5cbiAgICByZXNvdXJjZS5saW5rID0gZnVuY3Rpb24ocHJvZ3JhbSwgcmVzb3VyY2VfbmFtZXMpIHtcbiAgICAgICAgdmFyIHJlcXVpcmVkUmVzb3VyY2VOYW1lcyA9IChBcnJheS5pc0FycmF5KHJlc291cmNlX25hbWVzKSkgPyByZXNvdXJjZV9uYW1lcyA6IE9iamVjdC5rZXlzKGdwdVJlc291cmNlcyk7XG4gICAgICAgIHJlcXVpcmVkUmVzb3VyY2VOYW1lcy5mb3JFYWNoKGZ1bmN0aW9uKHJlc291cmNlTmFtZSkge1xuICAgICAgICAgICAgaWYgKGdwdVJlc291cmNlcy5oYXNPd25Qcm9wZXJ0eShyZXNvdXJjZU5hbWUpKSB7XG4gICAgICAgICAgICAgICAgZ3B1UmVzb3VyY2VzW3Jlc291cmNlTmFtZV0ubGluayhwcm9ncmFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICB9O1xuXG4gICAgcmVzb3VyY2UuZ2V0ID0gZnVuY3Rpb24obmFtZSkge1xuICAgICAgICByZXR1cm4gZ3B1UmVzb3VyY2VzW25hbWVdO1xuICAgIH1cbiAgICByZXNvdXJjZS5jcmVhdGUgPSByZXNvdXJjZS5hbGxvY2F0ZTtcblxuICAgIHJldHVybiByZXNvdXJjZTtcbn07XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBBdHRyaWJ1dGUoZ2xDb250ZXh0KSBcbntcbiAgICB2YXIgYXR0cmlidXRlID0gKHRoaXMgaW5zdGFuY2VvZiBBdHRyaWJ1dGUpID8gdGhpcyA6IHt9LFxuICAgICAgICBjdHggPSBnbENvbnRleHQsXG4gICAgICAgIGF0dHJpYnV0ZUlEID0gMDtcblxuICAgIGZ1bmN0aW9uIHNldEF0dHJpYnV0ZShuYW1lLCBkYXRhKSBcbiAgICB7XG4gICAgICAgIGlmKCBBcnJheS5pc0FycmF5KGRhdGEpIHx8IEFycmF5QnVmZmVyLmlzVmlldyhkYXRhKSApXG4gICAgICAgIHtcbiAgICAgICAgICAgIGlmKCFBcnJheUJ1ZmZlci5pc1ZpZXcoZGF0YSkpIFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXR0cmlidXRlW25hbWVdLmRhdGEgPSBkYXRhO1xuICAgICAgICAgICAgY3R4LmJpbmRCdWZmZXIoY3R4LkFSUkFZX0JVRkZFUiwgYXR0cmlidXRlW25hbWVdLnB0cik7XG4gICAgICAgICAgICBjdHguYnVmZmVyRGF0YShjdHguQVJSQVlfQlVGRkVSLCBkYXRhLCBjdHguU1RBVElDX0RSQVcpO1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYXR0cmlidXRlW25hbWVdLnB0ciA9PT0gYXR0cmlidXRlW25hbWVdLm9sZF9wdHIpO1xuICAgICAgICAgICAgLy8gYXR0cmlidXRlW25hbWVdLm9sZF9wdHIgPSBhdHRyaWJ1dGVbbmFtZV0ucHRyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXR0cmlidXRlLmNyZWF0ZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIGRhdGEpIFxuICAgIHtcbiAgICAgICAgYXR0cmlidXRlW25hbWVdID0ge1xuICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgIHR5cGU6IHR5cGUgfHwgJ2Zsb2F0JyxcbiAgICAgICAgICAgIGRhdGE6IG51bGwsXG4gICAgICAgICAgICBsb2NhdGlvbjogYXR0cmlidXRlSUQrKyxcbiAgICAgICAgICAgIHB0cjogY3R4LmNyZWF0ZUJ1ZmZlcigpLFxuICAgICAgICAgICAgc2l6ZTogcGFyc2VJbnQodHlwZS5zbGljZSgzLDQpKSB8fCAxXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYoZGF0YSAhPT0gbnVsbCAmJiBkYXRhLmxlbmd0aCkgXG4gICAgICAgICAgICB7c2V0QXR0cmlidXRlKG5hbWUsIGRhdGEpO31cblxuICAgICAgICBhdHRyaWJ1dGVbbmFtZV0ubGluayA9IGZ1bmN0aW9uKHByb2dyYW0pIFxuICAgICAgICB7XG4gICAgICAgICAgICBjdHguYmluZEJ1ZmZlcihjdHguQVJSQVlfQlVGRkVSLCB0aGlzLnB0cik7XG4gICAgICAgICAgICB0aGlzLmxvY2F0aW9uID0gY3R4LmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIHRoaXMubmFtZSk7XG4gICAgICAgICAgICBjdHgudmVydGV4QXR0cmliUG9pbnRlcih0aGlzLmxvY2F0aW9uLCB0aGlzLnNpemUsIGN0eC5GTE9BVCwgZmFsc2UsIDAsIDApO1xuICAgICAgICAgICAgY3R4LmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KHRoaXMubG9jYXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBhdHRyaWJ1dGVbbmFtZV0ubG9hZCA9IGZ1bmN0aW9uKGFycmF5QnVmZmVyKSBcbiAgICAgICAge1xuICAgICAgICAgICAgc2V0QXR0cmlidXRlKHRoaXMubmFtZSwgYXJyYXlCdWZmZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBhdHRyaWJ1dGVbbmFtZV0uaGVhZGVyID0gZnVuY3Rpb24oKSBcbiAgICAgICAgICAgIHtyZXR1cm4gJ2F0dHJpYnV0ZSAnICsgdGhpcy50eXBlICsgJyAnICsgdGhpcy5uYW1lICsgJztcXG4nO31cbiAgICAgICAgXG5cbiAgICAgICAgYXR0cmlidXRlW25hbWVdLmRlbGV0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgY3R4LmRlbGV0ZUJ1ZmZlcih0aGlzLnB0cik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXR0cmlidXRlW25hbWVdO1xuICAgIH07XG5cbiAgICByZXR1cm4gYXR0cmlidXRlO1xufVxuIiwiZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gVmFyeWluZyhnbENvbnRleHQpIHtcblxuICAgIHZhciB2YXJ5aW5nID0gKHRoaXMgaW5zdGFuY2VvZiBWYXJ5aW5nKSA/IHRoaXMgOiB7fSxcbiAgICAgICAgY3R4ID0gZ2xDb250ZXh0O1xuXG4gICAgdmFyeWluZy5jcmVhdGUgPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBzaXplKSB7XG4gICAgICAgIHZhcnlpbmdbbmFtZV0gPSB7XG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgdHlwZTogdHlwZSB8fCAnZmxvYXQnLFxuICAgICAgICAgICAgc2l6ZTogc2l6ZSB8fCAxLFxuICAgICAgICB9O1xuXG4gICAgICAgIHZhcnlpbmdbbmFtZV0ubGluayA9IGZ1bmN0aW9uKCkge307XG5cbiAgICAgICAgdmFyeWluZ1tuYW1lXS5oZWFkZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBoZWFkZXIgPSAndmFyeWluZyAnICsgdGhpcy50eXBlICsgJyAnICsgdGhpcy5uYW1lO1xuICAgICAgICAgICAgaWYodGhpcy5zaXplID4gMSlcbiAgICAgICAgICAgICAgICBoZWFkZXIgKz0gJ1snICsgdGhpcy5zaXplICsgJ10nO1xuICAgICAgICAgICAgcmV0dXJuIGhlYWRlciArICc7XFxuJztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YXJ5aW5nW25hbWVdO1xuICAgIH1cblxuICAgIHJldHVybiB2YXJ5aW5nO1xufVxuIiwiZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gU3Vicm91dGluZSgpIHtcblxuICAgIHZhciBzdWJyb3V0aW5lID0gKHRoaXMgaW5zdGFuY2VvZiBTdWJyb3V0aW5lKSA/IHRoaXMgOiB7fTtcblxuICAgIHN1YnJvdXRpbmUuY3JlYXRlID0gZnVuY3Rpb24obmFtZSwgdHlwZSwgZm4pIHtcbiAgICAgICAgc3Vicm91dGluZVtuYW1lXSA9IHtcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgICB0eXBlOiB0eXBlIHx8ICdmbG9hdCcsXG4gICAgICAgICAgICBmbjogZm4sXG4gICAgICAgICAgICByZXNvdXJjZVR5cGU6IFwic3Vicm91dGluZVwiXG4gICAgICAgIH07XG5cbiAgICAgICAgc3Vicm91dGluZVtuYW1lXS5saW5rID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBzdWJyb3V0aW5lW25hbWVdLmxvYWQgPSBmdW5jdGlvbihmbikge1xuICAgICAgICAgICAgc3Vicm91dGluZVtuYW1lXS5mbiA9IGZuO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBzdWJyb3V0aW5lW25hbWVdLmhlYWRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm4udG9TdHJpbmcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzdWJyb3V0aW5lW25hbWVdO1xuICAgIH07XG5cbiAgICByZXR1cm4gc3Vicm91dGluZTtcbn1cbiIsImltcG9ydCBTaGFkZXIgZnJvbSAnLi9zaGFkZXInO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBQcm9ncmFtKGdsQ29udGV4dCwgcmVzb3VyY2VzKSB7XG5cbiAgICB2YXIgcHJvZ3JhbSA9IHt9LFxuICAgICAgICBjdHggPSBnbENvbnRleHQsXG4gICAgICAgIGtlcm5lbHMgPSB7fSxcbiAgICAgICAgc2hhZGVyID0gbmV3IFNoYWRlcihnbENvbnRleHQpO1xuXG4gICAgcHJvZ3JhbS5jcmVhdGUgPSBmdW5jdGlvbihuYW1lLCB2cywgZnMpIHtcbiAgICAgICAgdmFyIG5hbWUgPSBuYW1lIHx8IFwiZGVmYXVsdFwiLFxuICAgICAgICAgICAgdnMgPSB2cyB8fCBcImRlZmF1bHRcIixcbiAgICAgICAgICAgIGZzID0gZnMgfHwgXCJkZWZhdWx0XCIsXG4gICAgICAgICAgICBkZXBzID0gW107XG5cbiAgICAgICAgaWYgKGtlcm5lbHMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIHRoaXMuZGVsZXRlKG5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAga2VybmVsc1tuYW1lXSA9IGN0eC5jcmVhdGVQcm9ncmFtKCk7XG4gICAgICAgIGtlcm5lbHNbbmFtZV0udnMgPSB2cztcbiAgICAgICAga2VybmVsc1tuYW1lXS5mcyA9IGZzO1xuXG4gICAgICAgIGN0eC5hdHRhY2hTaGFkZXIoa2VybmVsc1tuYW1lXSwga2VybmVsc1tuYW1lXS52cyk7XG4gICAgICAgIGN0eC5hdHRhY2hTaGFkZXIoa2VybmVsc1tuYW1lXSwga2VybmVsc1tuYW1lXS5mcyk7XG4gICAgICAgIGN0eC5saW5rUHJvZ3JhbShrZXJuZWxzW25hbWVdKTtcbiAgICAgICAgdmFyIGxpbmtlZCA9IGN0eC5nZXRQcm9ncmFtUGFyYW1ldGVyKGtlcm5lbHNbbmFtZV0sIGN0eC5MSU5LX1NUQVRVUyk7XG4gICAgICAgIGlmICghbGlua2VkKSB7XG4gICAgICAgICAgICB2YXIgbGFzdEVycm9yID0gY3R4LmdldFByb2dyYW1JbmZvTG9nKGtlcm5lbHNbbmFtZV0pO1xuICAgICAgICAgICAgdGhyb3cgKFwiRXJyb3IgaW4gcHJvZ3JhbSBsaW5raW5nOlwiICsgbGFzdEVycm9yKTtcbiAgICAgICAgICAgIGN0eC5kZWxldGVQcm9ncmFtKGtlcm5lbHNbbmFtZV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVwcyA9IGRlcHMuY29uY2F0KGtlcm5lbHNbbmFtZV0udnMuZGVwcyk7XG4gICAgICAgIGRlcHMgPSBkZXBzLmNvbmNhdChrZXJuZWxzW25hbWVdLmZzLmRlcHMpO1xuICAgICAgICBrZXJuZWxzW25hbWVdLmRlcHMgPSBkZXBzO1xuXG4gICAgfVxuXG4gICAgcHJvZ3JhbS51c2UgPSBmdW5jdGlvbihuYW1lLCB2ZXJ0ZXhfc2hhZGVyX3NvdXJjZSwgZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSkge1xuICAgICAgICBpZiAoa2VybmVscy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgICAgY3R4LnVzZVByb2dyYW0oa2VybmVsc1tuYW1lXSk7XG4gICAgICAgICAgICByZXNvdXJjZXMubGluayhrZXJuZWxzW25hbWVdLCBrZXJuZWxzW25hbWVdLmRlcHMpO1xuICAgICAgICAgICAgcmV0dXJuIGtlcm5lbHNbbmFtZV07XG4gICAgICAgIH0gXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc2hhZGVyLmNyZWF0ZShuYW1lLCB2ZXJ0ZXhfc2hhZGVyX3NvdXJjZSwgZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZShuYW1lLCBzaGFkZXJbbmFtZV0udnMsIHNoYWRlcltuYW1lXS5mcyk7XG4gICAgICAgICAgICBjdHgudXNlUHJvZ3JhbShrZXJuZWxzW25hbWVdKTtcbiAgICAgICAgICAgIHJlc291cmNlcy5saW5rKGtlcm5lbHNbbmFtZV0sIGtlcm5lbHNbbmFtZV0uZGVwcyk7XG4gICAgICAgICAgICByZXR1cm4ga2VybmVsc1tuYW1lXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb2dyYW0uZGVsZXRlID0gZnVuY3Rpb24obmFtZSkge1xuICAgICAgICBpZiAoa2VybmVscy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgICAgY3R4LmRldGFjaFNoYWRlcihrZXJuZWxzW25hbWVdLCBrZXJuZWxzW25hbWVdLnZzKTtcbiAgICAgICAgICAgIGN0eC5kZXRhY2hTaGFkZXIoa2VybmVsc1tuYW1lXSwga2VybmVsc1tuYW1lXS5mcyk7XG4gICAgICAgICAgICBjdHguZGVsZXRlUHJvZ3JhbShrZXJuZWxzW25hbWVdKTtcbiAgICAgICAgICAgIGRlbGV0ZSBrZXJuZWxzW25hbWVdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2dyYW07XG59XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBTaGFkZXIoZ2xDb250ZXh0KSB7XG4gICAgXG4gICAgdmFyIHNoYWRlciA9ICh0aGlzIGluc3RhbmNlb2YgU2hhZGVyKSA/IHRoaXMgOiB7fSxcbiAgICAgICAgY3R4ID0gZ2xDb250ZXh0O1xuICAgICAgICAvLyByZXNvdXJjZSA9IGdsUmVzb3VyY2UsXG4gICAgICAgIC8vIHBhcmFtZXRlcnMgPSBjdHguX2RpY3QgfHwge307XG5cbiAgICBzaGFkZXIuY3JlYXRlID0gZnVuY3Rpb24obmFtZSwgdmVydGV4X3NoYWRlcl9zb3VyY2UsIGZyYWdtZW50X3NoYWRlcl9zb3VyY2Upe1xuICAgICAgICBzaGFkZXJbbmFtZV0gPSB7XG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgdmVydGV4X3NoYWRlcl9zb3VyY2U6IHZlcnRleF9zaGFkZXJfc291cmNlLCBcbiAgICAgICAgICAgIGZyYWdtZW50X3NoYWRlcl9zb3VyY2U6IGZyYWdtZW50X3NoYWRlcl9zb3VyY2UsIFxuICAgICAgICAgICAgdnM6IGNyZWF0ZVNoYWRlcihjdHgsIGN0eC5WRVJURVhfU0hBREVSLCB2ZXJ0ZXhfc2hhZGVyX3NvdXJjZSksXG4gICAgICAgICAgICBmczogY3JlYXRlU2hhZGVyKGN0eCwgY3R4LkZSQUdNRU5UX1NIQURFUiwgZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSlcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNoYWRlcltuYW1lXS52cyA9IGNyZWF0ZVNoYWRlcihjdHgsIGN0eC5WRVJURVhfU0hBREVSLCB2ZXJ0ZXhfc2hhZGVyX3NvdXJjZSk7XG4gICAgICAgIC8vIHNoYWRlcltuYW1lXS5mcyA9IGNyZWF0ZVNoYWRlcihjdHgsIGN0eC5GUkFHTUVOVF9TSEFERVIsIGZyYWdtZW50X3NoYWRlcl9zb3VyY2UpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhzaGFkZXJbbmFtZV0udnMpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhzaGFkZXJbbmFtZV0uZnMpO1xuXG4gICAgICAgIHNoYWRlcltuYW1lXS52cy5kZXBzID0gW107XG4gICAgICAgIGFkZERlcHModmVydGV4X3NoYWRlcl9zb3VyY2UsIHNoYWRlcltuYW1lXS52cy5kZXBzKTtcbiAgICAgICAgc2hhZGVyW25hbWVdLmZzLmRlcHMgPSBbXTtcbiAgICAgICAgYWRkRGVwcyhmcmFnbWVudF9zaGFkZXJfc291cmNlLCBzaGFkZXJbbmFtZV0udnMuZGVwcyk7XG5cbiAgICAgICAgZnVuY3Rpb24gY3JlYXRlU2hhZGVyKGdsLCB0eXBlLCBzb3VyY2UpIHtcbiAgICAgICAgICAgIHZhciBzaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIodHlwZSk7XG4gICAgICAgICAgICBnbC5zaGFkZXJTb3VyY2Uoc2hhZGVyLCBzb3VyY2UpO1xuICAgICAgICAgICAgZ2wuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICAgICAgdmFyIHN1Y2Nlc3MgPSBnbC5nZXRTaGFkZXJQYXJhbWV0ZXIoc2hhZGVyLCBnbC5DT01QSUxFX1NUQVRVUyk7XG4gICAgICAgICAgICBpZiAoc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIHJldHVybiBzaGFkZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnTk8hJyk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhnbC5nZXRTaGFkZXJJbmZvTG9nKHNoYWRlcikpO1xuICAgICAgICAgICAgZ2wuZGVsZXRlU2hhZGVyKHNoYWRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBhZGREZXBzKHNvdXJjZSwgZGVwcyl7XG4gICAgICAgICAgICB2YXIgcmUgPSAvXFxzKihhdHRyaWJ1dGV8dW5pZm9ybSlcXHMrXFx3K1xccysoXFx3KykvOyAgICAgICAgXG4gICAgICAgICAgICBzb3VyY2Uuc3BsaXQoJ1xcbicpLmZvckVhY2goZnVuY3Rpb24odil7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHJlLmV4ZWModik7XG4gICAgICAgICAgICAgICAgaWYocmVzdWx0KXtcbiAgICAgICAgICAgICAgICAgICAgZGVwcy5wdXNoKHJlc3VsdFsyXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2hhZGVyO1xufVxuIiwiaW1wb3J0IFJlc291cmNlIGZyb20gJy4vcmVzb3VyY2UnO1xuaW1wb3J0IFByb2dyYW0gZnJvbSAnLi9wcm9ncmFtJztcbmltcG9ydCBGcmFtZWJ1ZmZlciBmcm9tICcuL2ZyYW1lYnVmZmVyJztcbi8vIGltcG9ydCBSZWFjdGl2ZSBmcm9tICcuL3JlYWN0aXZlJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gRmxleEdMKGFyZykge1xuXG4gICAgdmFyIGZsZXhnbCA9ICh0aGlzIGluc3RhbmNlb2YgRmxleEdMKSA/IHRoaXMgOiB7fTtcblxuXG4gICAgdmFyIG9wdGlvbnMgPSBhcmcgfHwge30sXG4gICAgICAgIGNvbnRhaW5lciA9IG9wdGlvbnMuY29udGFpbmVyIHx8IG51bGwsXG4gICAgICAgIGNhbnZhcyA9IG9wdGlvbnMuY2FudmFzIHx8IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIiksXG4gICAgICAgIHdpZHRoID0gb3B0aW9ucy53aWR0aCB8fCBudWxsLFxuICAgICAgICBoZWlnaHQgPSBvcHRpb25zLmhlaWdodCB8fCBudWxsLFxuICAgICAgICBwYWRkaW5nID0gb3B0aW9ucy5wYWRkaW5nIHx8IHtcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICByaWdodDogMCxcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIGJvdHRvbTogMFxuICAgICAgICB9LFxuICAgICAgICBjdHggPSBvcHRpb25zLmNvbnRleHQgfHwgb3B0aW9ucy5jdHggfHwgbnVsbCxcbiAgICAgICAga2VybmVscyA9IHt9LFxuICAgICAgICBzaGFyZWRGdW5jdGlvbiA9IG9wdGlvbnMuc2hhcmVkRnVuY3Rpb24gfHwge307XG5cblxuXG4gICAgaWYgKHR5cGVvZihjYW52YXMpID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgaWYgKGNhbnZhc1swXSA9PSBcIiNcIikgY2FudmFzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY2F2bmFzLnN1YnN0cmluZygxKSk7XG4gICAgICAgIGVsc2UgY2FudmFzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY2F2bmFzKTtcbiAgICB9XG4gICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICBjb250YWluZXIgPSAodHlwZW9mKGNvbnRhaW5lcikgPT0gXCJzdHJpbmdcIikgPyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChjb250YWluZXIpIDogY29udGFpbmVyO1xuICAgICAgICBpZiAod2lkdGggPT09IG51bGwpIHdpZHRoID0gY29udGFpbmVyLmNsaWVudFdpZHRoO1xuICAgICAgICBpZiAoaGVpZ2h0ID09PSBudWxsKSBoZWlnaHQgPSBjb250YWluZXIuY2xpZW50SGVpZ2h0O1xuICAgIH1cbiAgICAvLyB3aWR0aCAtPSBwYWRkaW5nLmxlZnQgKyBwYWRkaW5nLnJpZ2h0O1xuICAgIC8vIGhlaWdodCAtPSBwYWRkaW5nLnRvcCArIHBhZGRpbmcuYm90dG9tO1xuICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgY2FudmFzLnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgIGNhbnZhcy5zdHlsZS5tYXJnaW5MZWZ0ID0gcGFkZGluZy5sZWZ0ICsgXCJweFwiO1xuICAgIGNhbnZhcy5zdHlsZS5tYXJnaW5Ub3AgPSBwYWRkaW5nLnRvcCArIFwicHhcIjtcblxuXG4gICAgaWYgKGN0eCA9PT0gbnVsbClcbiAgICAgICAgY3R4ID0gc2V0dXBXZWJHTChjYW52YXMpO1xuICAgIGZsZXhnbC5jdHggPSBjdHg7XG4gICAgZmxleGdsLmNhbnZhcyA9IGNhbnZhcztcbiAgICBmbGV4Z2wucmVzb3VyY2VzID0gcmVzb3VyY2VzO1xuICAgIGN0eC5fZGljdCA9IG9wdGlvbnMuZW52IHx8IG9wdGlvbnMuZGljdCB8fCBvcHRpb25zLmRpY3Rpb25hcnkgfHwge307XG5cbiAgICB2YXIgcmVzb3VyY2VzID0gbmV3IFJlc291cmNlKGN0eCksXG4gICAgICAgIGZyYW1lYnVmZmVycyA9IG5ldyBGcmFtZWJ1ZmZlcihjdHgpLFxuICAgICAgICBwcm9ncmFtID0gbmV3IFByb2dyYW0oY3R4LCByZXNvdXJjZXMpLFxuICAgICAgICByZWFsUHJvZ3JhbSA9IG51bGw7XG5cblxuICAgIHZhciBibGVuZEV4dCA9IGN0eC5nZXRFeHRlbnNpb24oXCJFWFRfYmxlbmRfbWlubWF4XCIpO1xuICAgIGlmIChibGVuZEV4dCkge1xuICAgICAgICBjdHguTUFYX0VYVCA9IGJsZW5kRXh0Lk1BWF9FWFQ7XG4gICAgICAgIGN0eC5NSU5fRVhUID0gYmxlbmRFeHQuTUlOX0VYVDtcbiAgICB9XG4gICAgY3R4LmV4dCA9IGN0eC5nZXRFeHRlbnNpb24oXCJBTkdMRV9pbnN0YW5jZWRfYXJyYXlzXCIpO1xuICAgIGVuYWJsZUV4dGVuc2lvbihbXG4gICAgICAgIFwiT0VTX3RleHR1cmVfZmxvYXRcIixcbiAgICAgICAgXCJPRVNfdGV4dHVyZV9mbG9hdF9saW5lYXJcIixcbiAgICAgICAgLy8gXCJPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0XCIsXG4gICAgICAgIC8vIFwiT0VTX3RleHR1cmVfaGFsZl9mbG9hdF9saW5lYXJcIlxuICAgIF0pO1xuICAgIGlmIChjb250YWluZXIpXG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChjYW52YXMpO1xuXG5cbiAgICBmdW5jdGlvbiBzZXR1cFdlYkdMKGNhbnZhcykge1xuICAgICAgICB2YXIgbmFtZXMgPSBbXCJ3ZWJnbFwiLCBcImV4cGVyaW1lbnRhbC13ZWJnbFwiXTtcbiAgICAgICAgdmFyIGdsID0gbnVsbDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBnbCA9IGNhbnZhcy5nZXRDb250ZXh0KG5hbWVzW2ldKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICBpZiAoZ2wpIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbmFibGVFeHRlbnNpb24oZXh0ZW5zaW9ucykge1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZXh0ZW5zaW9ucykpIGV4dGVuc2lvbnMgPSBbZXh0ZW5zaW9uc107XG4gICAgICAgIGV4dGVuc2lvbnMuZm9yRWFjaChmdW5jdGlvbihleHRlbnNpb24pIHtcbiAgICAgICAgICAgIHZhciBleHRQcm9wcyA9IGN0eC5nZXRFeHRlbnNpb24oZXh0ZW5zaW9uKTtcbiAgICAgICAgICAgIGlmIChleHRQcm9wcyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKGV4dFByb3BzKS5mb3JFYWNoKGZ1bmN0aW9uKGVwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXh0Lmhhc093blByb3BlcnR5KGVwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmV4dFtlcF0gPSBleHRQcm9wc1tlcF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGZsZXhnbC5lbmFibGVFeHRlbnNpb24gPSBlbmFibGVFeHRlbnNpb247XG5cbiAgICAvKipcbiAgICAgKiBBbGxvY2F0ZSBBdHRyaWJ1dGVzIGluIHZlcnRleCBidWZmZXIgYXJyYXkgc3RvcmVkIGluIEdQVSBtZW1vcnlcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IG5hbWUgYXR0cmlidXRlIG5hbWVcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IHR5cGUgYXR0cmlidXRlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gZGF0YSBkYXRhIHZhbHVlc1xuICAgICAqIEByZXR1cm4ge09iamVjdH0gICAgICBGTGV4R0wgb2JqZWN0XG4gICAgICovXG4gICAgZmxleGdsLmF0dHJpYnV0ZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIGRhdGEpIHtcbiAgICAgICAgcmVzb3VyY2VzLmFsbG9jYXRlKFwiYXR0cmlidXRlXCIsIG5hbWUsIHR5cGUsIGRhdGEpO1xuICAgICAgICBpZiAoIWZsZXhnbC5hdHRyaWJ1dGUuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmbGV4Z2wuYXR0cmlidXRlLCBuYW1lLCB7IC8vYWZ0ZXIgYWxsb2NhdGluZywgZmxleGdsIGdldHMgbmV3IGtleSBhdHRyaWJ1dGUsIGhlbHBpbmcgZWFzaWx5IGNoYW5nZSBhdHRyaWJ1dGUgZGF0YS5cbiAgICAgICAgICAgICAgICBnZXQoKXtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc291cmNlcy5hdHRyaWJ1dGVbbmFtZV07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZXQoZGF0YSl7XG4gICAgICAgICAgICAgICAgICAgIHJlc291cmNlcy5hdHRyaWJ1dGVbbmFtZV0ubG9hZChkYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmxleGdsO1xuICAgIH07XG4gICAgLy8gZmxleGdsLmJ1ZmZlciA9IGZsZXhnbC5hdHRyaWJ1dGU7IC8vYWxpYXNcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIFVuaWZvcm0gdmFyaWFibGUgZm9yIFdlYkdMIHNoYWRlciBwcm9ncmFtc1xuICAgICAqIEBwYXJhbSAge1N0cmluZ30gbmFtZSBhdHRyaWJ1dGUgbmFtZVxuICAgICAqIEBwYXJhbSAge1N0cmluZ30gdHlwZSB1bmlmb3JtIHZhcmlhYmxlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gZGF0YSBkYXRhIHZhbHVlc1xuICAgICAqIEByZXR1cm4ge09iamVjdH0gICAgICBGTGV4R0wgb2JqZWN0XG4gICAgICovXG4gICAgZmxleGdsLnVuaWZvcm0gPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBkYXRhKSB7XG4gICAgICAgIHJlc291cmNlcy5hbGxvY2F0ZShcInVuaWZvcm1cIiwgbmFtZSwgdHlwZSwgZGF0YSk7XG4gICAgICAgIGlmICghZmxleGdsLnVuaWZvcm0uaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmbGV4Z2wudW5pZm9ybSwgbmFtZSwge1xuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvdXJjZXMudW5pZm9ybVtuYW1lXTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICByZXNvdXJjZXMudW5pZm9ybVtuYW1lXS5sb2FkKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY3R4LmlzUHJvZ3JhbShyZWFsUHJvZ3JhbSkpICAgICAgICAgICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZXMudW5pZm9ybVtuYW1lXS5saW5rKHJlYWxQcm9ncmFtKTsgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZsZXhnbDtcbiAgICB9O1xuXG4gICAgZmxleGdsLnVuaWZvcm0uc2VyaWFsaXplID0gZnVuY3Rpb24oYW9hKSB7XG4gICAgICAgIHZhciBzYSA9IFtdO1xuICAgICAgICBhb2EuZm9yRWFjaChmdW5jdGlvbihhKSB7XG4gICAgICAgICAgICBzYSA9IHNhLmNvbmNhdChhKTtcbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIHNhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIFVuaWZvcm0gdmFyaWFibGUgZm9yIFdlYkdMIHNoYWRlciBwcm9ncmFtc1xuICAgICAqIEBwYXJhbSAge1N0cmluZ30gbmFtZSBhdHRyaWJ1dGUgbmFtZVxuICAgICAqIEBwYXJhbSAge1N0cmluZ30gdHlwZSB0ZXh0dXJlIHR5cGU6IHVuc2lnbmVkX2J5dGUgb3IgZmxvYXQsIC4uLlxuICAgICAqIEBwYXJhbSAge0FycmF5fSBkYXRhIGRhdGEgdmFsdWVzXG4gICAgICogQHBhcmFtICB7QXJyYXl9IGRpbSBbd2lkdGgsIGhlaWdodF1cbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IFtjaGFubmVsPSdhbHBoYSddIFdlYkdMIGZvcm1hdHMgKHJnYmEsIGFscGhhKVxuICAgICAqIEBwYXJhbSAge09iamVjdH0gW3NhbXBsZXI9bnVsbF0gRkxleEdMIFVuaWZvcm0gT2JqZWN0XG4gICAgICogQHJldHVybiB7T2JqZWN0fSAgICAgIEZMZXhHTCBvYmplY3RcbiAgICAgKi9cbiAgICBmbGV4Z2wudGV4dHVyZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIGRhdGEsIGRpbSwgY2hhbm5lbCwgc2FtcGxlcikge1xuICAgICAgICByZXNvdXJjZXMuYWxsb2NhdGUoXCJ0ZXh0dXJlXCIsIG5hbWUsIHR5cGUsIGRpbSwgY2hhbm5lbCwgZGF0YSwgc2FtcGxlcik7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmbGV4Z2wudGV4dHVyZSwgbmFtZSwge1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb3VyY2VzLnRleHR1cmVbbmFtZV07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICAgICAgcmVzb3VyY2VzLnRleHR1cmVbbmFtZV0ubG9hZChkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBmbGV4Z2w7XG4gICAgfVxuXG4gICAgZmxleGdsLnRleHR1cmUudXBkYXRlID0gZnVuY3Rpb24obmFtZSwgZGF0YSwgb2Zmc2V0LCBkaW0pIHtcbiAgICAgICAgcmVzb3VyY2VzLnRleHR1cmVbbmFtZV0udXBkYXRlKGRhdGEsIG9mZnNldCwgZGltKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBVbmlmb3JtIHZhcmlhYmxlIGZvciBXZWJHTCBzaGFkZXIgcHJvZ3JhbXNcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IG5hbWUgYXR0cmlidXRlIG5hbWVcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IFt0eXBlXSBWYXJ5aW5nIHZhcmlhYmxlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtOdW1iZXJ9IFtzaXplPTFdIGRhdGEgYXJyYXlcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9ICAgICAgRkxleEdMIG9iamVjdFxuICAgICAqL1xuICAgIGZsZXhnbC52YXJ5aW5nID0gZnVuY3Rpb24obmFtZSwgdHlwZSwgc2l6ZSkge1xuICAgICAgICByZXNvdXJjZXMuYWxsb2NhdGUoXCJ2YXJ5aW5nXCIsIG5hbWUsIHR5cGUsIHNpemUpO1xuICAgICAgICByZXR1cm4gZmxleGdsO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBVbmlmb3JtIHZhcmlhYmxlIGZvciBXZWJHTCBzaGFkZXIgcHJvZ3JhbXNcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IG5hbWUgYXR0cmlidXRlIG5hbWVcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IHR5cGUgYXR0cmlidXRlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gZGltIFt3aWR0aCwgaGVpZ2h0XVxuICAgICAqIEBwYXJhbSAge09iamVjdH0gW3RleHR1cmU9bnVsbF0gRkxleEdMIFRleHR1cmUgT2JqZWN0XG4gICAgICogQHJldHVybiB7T2JqZWN0fSAgICAgIEZMZXhHTCBvYmplY3RcbiAgICAgKi9cbiAgICBmbGV4Z2wuZnJhbWVidWZmZXIgPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBkaW0sIHRleHR1cmUpIHtcbiAgICAgICAgdmFyIHRleHR1cmUgPSB0ZXh0dXJlIHx8IHJlc291cmNlcy5hbGxvY2F0ZSgndGV4dHVyZScsIG5hbWUsIHR5cGUsIGRpbSwgJ3JnYmEnLCBudWxsKTtcbiAgICAgICAgZnJhbWVidWZmZXJzLmNyZWF0ZShuYW1lLCB0eXBlLCBkaW0sIHRleHR1cmUpO1xuXG4gICAgICAgIGlmICghZmxleGdsLmZyYW1lYnVmZmVyLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZmxleGdsLmZyYW1lYnVmZmVyLCBuYW1lLCB7XG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZyYW1lYnVmZmVyc1tuYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmxleGdsO1xuICAgIH1cblxuICAgIGZsZXhnbC5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkID0gZnVuY3Rpb24obmFtZSwgcHJvZ3JhbSkge1xuICAgICAgICBmcmFtZWJ1ZmZlcnNbbmFtZV0uZW5hYmxlUmVhZChwcm9ncmFtKTtcbiAgICB9XG5cbiAgICBmbGV4Z2wuYmluZEZyYW1lYnVmZmVyID0gZnVuY3Rpb24oZmJOYW1lKSB7XG4gICAgICAgIGlmIChmYk5hbWUgPT09IG51bGwpXG4gICAgICAgICAgICBjdHguYmluZEZyYW1lYnVmZmVyKGN0eC5GUkFNRUJVRkZFUiwgbnVsbCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGN0eC5iaW5kRnJhbWVidWZmZXIoY3R4LkZSQU1FQlVGRkVSLCBmcmFtZWJ1ZmZlcnNbZmJOYW1lXS5wdHIpO1xuICAgIH1cblxuICAgIGZsZXhnbC5zdWJyb3V0aW5lID0gZnVuY3Rpb24obmFtZSwgdHlwZSwgZm4pIHtcbiAgICAgICAgcmVzb3VyY2VzLmFsbG9jYXRlKFwic3Vicm91dGluZVwiLCBuYW1lLCB0eXBlLCBmbik7XG4gICAgICAgIHJldHVybiBmbGV4Z2w7XG4gICAgfVxuXG4gICAgZmxleGdsLnBhcmFtZXRlciA9IGZ1bmN0aW9uKGtleVZhbHVlUGFpcnMpIHtcbiAgICAgICAgT2JqZWN0LmtleXMoa2V5VmFsdWVQYWlycykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIGN0eC5fZGljdFtrZXldID0ga2V5VmFsdWVQYWlyc1trZXldO1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY3R4Ll9kaWN0W2tleV0pKSB7XG4gICAgICAgICAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdHguX2RpY3QsIGtleSwge1xuICAgICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGtleVZhbHVlUGFpcnNba2V5XVtpKytdO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKG5ld0FycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5fZGljdFtrZXldID0gbmV3QXJyYXk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZih0eXBlb2YoY3R4Ll9kaWN0W2tleV0pID09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpY3RLZXlzID0gT2JqZWN0LmtleXMoY3R4Ll9kaWN0W2tleV0pO1xuICAgICAgICAgICAgICAgIGZ4Z2wudW5pZm9ybSgnZGljdCcra2V5LCAnZmxvYXQnLCBkaWN0S2V5cy5tYXAoZD0+Y3R4Ll9kaWN0W2tleV1bZF0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIGZsZXhnbDtcbiAgICB9XG5cbiAgICBmbGV4Z2wuZGljdGlvbmFyeSA9IGZsZXhnbC5wYXJhbWV0ZXI7XG4gICAgZmxleGdsLnNoYWRlciA9IHByb2dyYW0uc2hhZGVyO1xuXG5cbiAgICBmbGV4Z2wuYXBwID0gZnVuY3Rpb24obmFtZSwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJncyl7XG4gICAgICAgICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG4gICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5yZW5kZXIuY2FsbChmbGV4Z2wsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZmxleGdsLmRpbWVuc2lvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gW2NhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodF07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZsZXhnbDtcbn1cblxuXG5cbiAgICAgICAgLy8gaWYobnVtID09PSAwKXtcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCAxMDI0LCAxKTtcbiAgICAgICAgLy8gICAgIHJlYWxQcm9ncmFtID0gcHJvZ3JhbS51c2UobmFtZSwgb3B0aW9ucy52ZXJ0ZXhfc2hhZGVyX3NvdXJjZSwgb3B0aW9ucy5mcmFnbWVudF9zaGFkZXJfc291cmNlKTtcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKCdmX3N1bV90ZXh0dXJlJyk7XG5cbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3Bvc2l0aW9uJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV90ZXhjb29yZCddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy50ZXh0dXJlWyd1X3RleHR1cmUnXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIC8vIGVsc2UgaWYobnVtID09PSAxKXtcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCBjdHguY2FudmFzLndpZHRoLCBjdHguY2FudmFzLmhlaWdodCk7XG4gICAgICAgIC8vICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG4gICAgICAgICAgICBcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKG51bGwpO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5hdHRyaWJ1dGVbJ2FfcG9zaXRpb24nXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3RleGNvb3JkJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmZyYW1lYnVmZmVyLmVuYWJsZVJlYWQoJ2Zfc3VtX3RleHR1cmUnLCByZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyBlbHNlIGlmKG51bSA9PT0gMil7XG4gICAgICAgIC8vICAgICB0aGlzLmJpbmRGcmFtZWJ1ZmZlcihudWxsKTtcblxuICAgICAgICAvLyAgICAgY3R4LnZpZXdwb3J0KDAsIDAsIDEwMjQsIDEpO1xuICAgICAgICAvLyAgICAgdGhpcy5iaW5kRnJhbWVidWZmZXIoJ2ZfbWVtX3RleHR1cmVfMScpO1xuICAgICAgICAvLyAgICAgcmVhbFByb2dyYW0gPSBwcm9ncmFtLnVzZShuYW1lLCBvcHRpb25zLnZlcnRleF9zaGFkZXJfc291cmNlLCBvcHRpb25zLmZyYWdtZW50X3NoYWRlcl9zb3VyY2UpO1xuXG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV9wb3NpdGlvbiddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5hdHRyaWJ1dGVbJ2FfdGV4Y29vcmQnXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuZnJhbWVidWZmZXIuZW5hYmxlUmVhZCgnZl9tZW1fdGV4dHVyZV8wJywgcmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkKCdmX3N1bV90ZXh0dXJlJywgcmVhbFByb2dyYW0pO1xuICAgICAgICAvLyB9XG5cbiAgICAgICAgLy8gZWxzZSBpZihudW0gPT09IDMpe1xuICAgICAgICAvLyAgICAgdGhpcy5iaW5kRnJhbWVidWZmZXIobnVsbCk7XG5cbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCAxMDI0LCAxKTtcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKCdmX21lbV90ZXh0dXJlXzAnKTtcbiAgICAgICAgLy8gICAgIHJlYWxQcm9ncmFtID0gcHJvZ3JhbS51c2UobmFtZSwgb3B0aW9ucy52ZXJ0ZXhfc2hhZGVyX3NvdXJjZSwgb3B0aW9ucy5mcmFnbWVudF9zaGFkZXJfc291cmNlKTtcblxuICAgICAgICAvLyAgICAgLy8gdGhpcy5hdHRyaWJ1dGVbJ2FfcG9zaXRpb24nXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3RleGNvb3JkJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmZyYW1lYnVmZmVyLmVuYWJsZVJlYWQoJ2ZfbWVtX3RleHR1cmVfMScsIHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuZnJhbWVidWZmZXIuZW5hYmxlUmVhZCgnZl9zdW1fdGV4dHVyZScsIHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIC8vIGVsc2UgaWYobnVtID09PSA0KXtcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKG51bGwpOyBcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCBjdHguY2FudmFzLndpZHRoLCBjdHguY2FudmFzLmhlaWdodCk7XG4gICAgICAgIC8vICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG5cbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3Bvc2l0aW9uJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV90ZXhjb29yZCddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkKCdmX21lbV90ZXh0dXJlXzEnLCByZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyBlbHNlIGlmKG51bSA9PT0gNSl7XG4gICAgICAgIC8vICAgICB0aGlzLmJpbmRGcmFtZWJ1ZmZlcihudWxsKTtcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCBjdHguY2FudmFzLndpZHRoLCBjdHguY2FudmFzLmhlaWdodCk7XG4gICAgICAgIC8vICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG5cbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3Bvc2l0aW9uJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV90ZXhjb29yZCddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkKCdmX21lbV90ZXh0dXJlXzAnLCByZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyB0aGlzLnVuaWZvcm1bJ3VfdGV4dHVyZSddLmxpbmsocmVhbFByb2dyYW0pOyAgICBcbiAgICAgICAgLy8gdmFyIGRyYXcgPSBvcHRpb25zLnJlbmRlciB8fCBvcHRpb25zLmRyYXc7XG5cbiAgICAgICAgLy8gcmV0dXJuIGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgLy8gICAgIC8vIHZhciBnbCA9IGZsZXhnbC5wcm9ncmFtKG5hbWUpO1xuICAgICAgICAvLyAgICAgcmV0dXJuIGRyYXcuY2FsbChjdHgsIGFyZ3MpO1xuICAgICAgICAvLyB9XG5cbiAgICAgICAgLy8gY3R4LmRyYXdBcnJheXMoY3R4LkxJTkVTLCAwLCAyKTsiLCJpbXBvcnQgVGV4dHVyZSBmcm9tICcuL3RleHR1cmUnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBGcmFtZWJ1ZmZlcihnbENvbnRleHQpIHtcblxuICAgIHZhciBmcmFtZWJ1ZmZlciA9ICh0aGlzIGluc3RhbmNlb2YgRnJhbWVidWZmZXIpID8gdGhpcyA6IHt9LFxuICAgICAgICBjdHggPSBnbENvbnRleHQ7XG5cbiAgICBmcmFtZWJ1ZmZlci5jcmVhdGUgPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBkaW0sIHRleHR1cmUpIHtcblxuICAgICAgICBmcmFtZWJ1ZmZlcltuYW1lXSA9IHtcbiAgICAgICAgICAgIHB0cjogY3R4LmNyZWF0ZUZyYW1lYnVmZmVyKCksXG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgdHlwZTogdHlwZSB8fCBcImZsb2F0XCIsXG4gICAgICAgICAgICB3aWR0aDogZGltWzBdIHx8IDEwMjQsXG4gICAgICAgICAgICBoZWlnaHQ6IGRpbVsxXSB8fCAxMDI0LFxuICAgICAgICAgICAgdGV4dHVyZTogdGV4dHVyZSB8fCBudWxsLFxuICAgICAgICAgICAgLy8gcmVuZGVyYnVmZmVyOiBjdHguY3JlYXRlUmVuZGVyYnVmZmVyKCksXG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiAoZnJhbWVidWZmZXJbbmFtZV0udGV4dHVyZSA9PT0gbnVsbCkge1xuICAgICAgICAvLyAgICAgdmFyIGJ1ZiA9ICh0eXBlID09ICdmbG9hdCcpID9cbiAgICAgICAgLy8gICAgICAgICBuZXcgRmxvYXQzMkFycmF5KGRpbVswXSAqIGRpbVsxXSAqIDQpIDpcbiAgICAgICAgLy8gICAgICAgICBuZXcgVWludDhBcnJheShkaW1bMF0gKiBkaW1bMV0gKiA0KTtcbiAgICAgICAgLy8gICAgIGZyYW1lYnVmZmVyW25hbWVdLnRleHR1cmUgPSBUZXh0dXJlKGN0eCkuY3JlYXRlKG5hbWUsIHR5cGUsIGRpbSwgXCJyZ2JhXCIsIGJ1Zik7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyB2YXIgcmVuZGVyYnVmZmVyID0gZnJhbWVidWZmZXJbbmFtZV0ucmVuZGVyYnVmZmVyO1xuICAgICAgICBjdHguYmluZEZyYW1lYnVmZmVyKGN0eC5GUkFNRUJVRkZFUiwgZnJhbWVidWZmZXJbbmFtZV0ucHRyKTtcbiAgICAgICAgLy8gY3R4LmJpbmRSZW5kZXJidWZmZXIoY3R4LlJFTkRFUkJVRkZFUiwgcmVuZGVyYnVmZmVyKTtcbiAgICAgICAgLy8gY3R4LnJlbmRlcmJ1ZmZlclN0b3JhZ2UoXG4gICAgICAgIC8vICAgICBjdHguUkVOREVSQlVGRkVSLFxuICAgICAgICAvLyAgICAgY3R4LkRFUFRIX0NPTVBPTkVOVDE2LFxuICAgICAgICAvLyAgICAgZnJhbWVidWZmZXJbbmFtZV0ud2lkdGgsXG4gICAgICAgIC8vICAgICBmcmFtZWJ1ZmZlcltuYW1lXS5oZWlnaHRcbiAgICAgICAgLy8gKTtcbiAgICAgICAgY3R4LmZyYW1lYnVmZmVyVGV4dHVyZTJEKFxuICAgICAgICAgICAgY3R4LkZSQU1FQlVGRkVSLFxuICAgICAgICAgICAgY3R4LkNPTE9SX0FUVEFDSE1FTlQwLFxuICAgICAgICAgICAgY3R4LlRFWFRVUkVfMkQsXG4gICAgICAgICAgICBmcmFtZWJ1ZmZlcltuYW1lXS50ZXh0dXJlLnB0cixcbiAgICAgICAgICAgIDBcbiAgICAgICAgKTtcbiAgICAgICAgLy8gY3R4LmZyYW1lYnVmZmVyUmVuZGVyYnVmZmVyKFxuICAgICAgICAvLyAgICAgY3R4LkZSQU1FQlVGRkVSLFxuICAgICAgICAvLyAgICAgY3R4LkRFUFRIX0FUVEFDSE1FTlQsXG4gICAgICAgIC8vICAgICBjdHguUkVOREVSQlVGRkVSLFxuICAgICAgICAvLyAgICAgcmVuZGVyYnVmZmVyXG4gICAgICAgIC8vICk7XG4gICAgICAgIC8vIGN0eC5iaW5kUmVuZGVyYnVmZmVyKGN0eC5SRU5ERVJCVUZGRVIsIG51bGwpO1xuICAgICAgICBjdHguYmluZEZyYW1lYnVmZmVyKGN0eC5GUkFNRUJVRkZFUiwgbnVsbCk7XG5cbiAgICAgICAgZnJhbWVidWZmZXJbbmFtZV0uZW5hYmxlUmVhZCA9IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgICAgICAgICAgIGN0eC5hY3RpdmVUZXh0dXJlKGN0eC5URVhUVVJFMCArIHRoaXMudGV4dHVyZS5pbmRleCk7XG4gICAgICAgICAgICBjdHguYmluZFRleHR1cmUoY3R4LlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZS5wdHIpO1xuICAgICAgICAgICAgdGhpcy50ZXh0dXJlLmxvY2F0aW9uID0gY3R4LmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCB0aGlzLnRleHR1cmUubmFtZSk7XG4gICAgICAgICAgICBjdHgudW5pZm9ybTFpKHRoaXMudGV4dHVyZS5sb2NhdGlvbiwgdGhpcy50ZXh0dXJlLmluZGV4KTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBmcmFtZWJ1ZmZlcltuYW1lXS5lbmFibGVSZWFkID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICAgICAgICAvLyAgICAgdGhpcy50ZXh0dXJlLmxpbmsocHJvZ3JhbSk7XG4gICAgICAgIC8vIH07XG5cbiAgICAgICAgZnJhbWVidWZmZXJbbmFtZV0uZGVsZXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjdHguYmluZFJlbmRlcmJ1ZmZlcihnbC5SRU5ERVJCVUZGRVIsIG51bGwpO1xuICAgICAgICAgICAgY3R4LmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgbnVsbCk7XG4gICAgICAgICAgICBjdHguZGVsZXRlUmVuZGVyYnVmZmVyKHRoaXMucmVuZGVyYnVmZmVyKTtcbiAgICAgICAgICAgIGN0eC5kZWxldGVUZXh0dXJlKHRoaXMudGV4dHVyZS5wdHIpXG4gICAgICAgICAgICBjdHguZGVsZXRlRnJhbWVidWZmZXIodGhpcy5wdHIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBmcmFtZWJ1ZmZlcltuYW1lXTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnJhbWVidWZmZXI7XG59XG4iLCJpbXBvcnQgRmxleEdMIGZyb20gJy4vZmxleGdsJztcblxuKGZ1bmN0aW9uIG1ha2VHbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHdpbmRvdy5GbGV4R0wgPSBGbGV4R0w7XG4gIH1cbn0pKCk7XG4iXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dist/flexgl.min.js b/dist/flexgl.min.js new file mode 100644 index 0000000..281e95f --- /dev/null +++ b/dist/flexgl.min.js @@ -0,0 +1,2 @@ +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";function n(e,t,r,i){var a=this instanceof n?this:{},u=e;function o(e){var t=[];return e.forEach(function(e){t=t.concat(e)}),t}return a.create=function(e,t,r){return Array.isArray(r)&&r.filter(function(e){return Array.isArray(e)})&&(r=o(r)),a[e]={type:t,name:e,data:r,location:null,size:parseInt(t.slice(3,4))||parseInt(t.slice(4,5))||1},a[e].link=function(e){return void 0!==this.data&&null!==this.data&&(this.location=u.getUniformLocation(e,this.name),function(){var e,t=this.type,r=this.location,n=this.size,i=this.data;Array.isArray(i)&&i.filter(function(e){return Array.isArray(e)})&&(i=o(i)),"float"!=t&&"int"!=t||Array.isArray(i)||ArrayBuffer.isView(i)||(i=[i]),"vec"==t.slice(0,3)||"float"==t?(e=new Float32Array(i),u["uniform"+n+"fv"](r,e)):"ivec"==t.slice(0,4)||"int"==t?(e=new Int32Array(i),u["uniform"+n+"iv"](r,e)):"mat"==t.slice(0,3)?(e=new Float32Array(i),u["uniformMatrix"+n+"fv"](r,!1,e)):"sampler2D"==t&&i.hasOwnProperty("resourceType")&&"texture"==i.resourceType&&(u.activeTexture(u.TEXTURE0+i.index),u.bindTexture(u.TEXTURE_2D,i.ptr),u.uniform1i(r,i.index))}.call(this)),this},a[e].load=function(e){return this.data=e,this},a[e].header=function(){var e="uniform "+this.type+" "+this.name,r=0;return"sampler2D"!=this.type&&(r=this.data.length/this.size),r>1&&"mat4"!=t&&(e+="["+r+"]"),e+";\n"},a[e]},a}function i(e){var t=this instanceof i?this:{},r={};t.uniform=new n(e),t.attribute=new function e(t){var r=this instanceof e?this:{},n=t,i=0;function a(e,t){(Array.isArray(t)||ArrayBuffer.isView(t))&&(ArrayBuffer.isView(t)||(t=new Float32Array(t)),r[e].data=t,n.bindBuffer(n.ARRAY_BUFFER,r[e].ptr),n.bufferData(n.ARRAY_BUFFER,t,n.STATIC_DRAW))}return r.create=function(e,t,u){return r[e]={name:e,type:t||"float",data:null,location:i++,ptr:n.createBuffer(),size:parseInt(t.slice(3,4))||1},null!==u&&u.length&&a(e,u),r[e].link=function(e){return n.bindBuffer(n.ARRAY_BUFFER,this.ptr),this.location=n.getAttribLocation(e,this.name),n.vertexAttribPointer(this.location,this.size,n.FLOAT,!1,0,0),n.enableVertexAttribArray(this.location),this},r[e].load=function(e){return a(this.name,e),this},r[e].header=function(){return"attribute "+this.type+" "+this.name+";\n"},r[e].delete=function(){n.deleteBuffer(this.ptr)},r[e]},r}(e),t.texture=new function e(t){var r=this instanceof e?this:{},i=t,a=0;function u(e,t){var n=i[r[e].type.toUpperCase()],a=i[r[e].channel.toUpperCase()],u=r[e].dim[0],o=r[e].dim[1];r[e].data=t,i.bindTexture(i.TEXTURE_2D,r[e].ptr),i.texImage2D(i.TEXTURE_2D,0,a,u,o,0,a,n,t),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.NEAREST),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.bindTexture(i.TEXTURE_2D,null)}return r.create=function(e,o,s,f,c,l){var d=r.hasOwnProperty(e)?r[e].index:a++;return r[e]={name:e,index:d,type:o||"float",dim:s||[512,512],channel:f||"alpha",data:null,location:null,sampler:l||null,ptr:i.createTexture()},u(e,c),null===r[e].sampler?r[e].sampler=n(i).create(e,"sampler2D",r[e]):r[e].sampler.data=r[e],r[e].link=function(t){return void 0!==this.sampler.data&&null!==this.sampler.data||(this.sampler.data=r[e]),this.sampler.link(t),this},r[e].load=function(e){return u(this.name,e),this},r[e].copyFromFBO=function(){i.bindTexture(i.TEXTURE_2D,this.ptr),i.copyTexImage2D(i.TEXTURE_2D,0,i.RGBA,0,0,this.dim[0],this.dim[1],0),i.bindTexture(i.TEXTURE_2D,null)},r[e].update=function(e,t,n){return function(e,t,n,a){var u=i[r[e].type.toUpperCase()],o=i[r[e].channel.toUpperCase()],s=a[0]||r[e].dim[0],f=a[1]||r[e].dim[1];i.bindTexture(i.TEXTURE_2D,r[e].ptr),i.texSubImage2D(i.TEXTURE_2D,0,n[0],n[1],s,f,o,u,t),i.bindTexture(i.TEXTURE_2D,null)}(this.name,e,t,n),this},r[e].resize=function(e,t){this.dim=e,u(this.name,t)},r[e].delete=function(){t.deleteTexture(this.ptr)},r[e].header=function(){return this.name==this.sampler.name?"uniform sampler2D "+this.sampler.name+";\n":""},r[e]},r}(e),t.varying=new function e(t){var r=this instanceof e?this:{};return r.create=function(e,t,n){return r[e]={name:e,type:t||"float",size:n||1},r[e].link=function(){},r[e].header=function(){var e="varying "+this.type+" "+this.name;return this.size>1&&(e+="["+this.size+"]"),e+";\n"},r[e]},r}(e),t.subroutine=new function e(){var t=this instanceof e?this:{};return t.create=function(e,r,n){return t[e]={name:e,type:r||"float",fn:n,resourceType:"subroutine"},t[e].link=function(e){return this},t[e].load=function(r){return t[e].fn=r,this},t[e].header=function(){return this.fn.toString()},t[e]},t};var a=["uniform","attribute","texture","varying","subroutine"];return t.allocate=function(e){if(-1===a.indexOf(e))throw Error("Error: Invalid resource type: "+e);var n=t[e].create.apply(null,Array.prototype.slice.call(arguments,1));return n.resourceType=e,r[n.name]=n,r.hasOwnProperty(n.name)||Object.defineProperty(r,n.name,{get:function(){return r[n.name]},set:function(e){r[n.name].load(e)}}),n},t.link=function(e,t){(Array.isArray(t)?t:Object.keys(r)).forEach(function(t){r.hasOwnProperty(t)&&r[t].link(e)})},t.get=function(e){return r[e]},t.create=t.allocate,t}r.r(t),"undefined"!=typeof window&&(window.FlexGL=function e(t){var r=this instanceof e?this:{},n=t||{},a=n.container||null,u=n.canvas||document.createElement("canvas"),o=n.width||null,s=n.height||null,f=n.padding||{left:0,right:0,top:0,bottom:0},c=n.context||n.ctx||null;n.sharedFunction,"string"==typeof u&&(u="#"==u[0]?document.getElementById(cavnas.substring(1)):document.getElementById(cavnas)),a&&(a="string"==typeof a?document.getElementById(a):a,null===o&&(o=a.clientWidth),null===s&&(s=a.clientHeight)),u.width=o,u.height=s,u.style.position="absolute",u.style.marginLeft=f.left+"px",u.style.marginTop=f.top+"px",null===c&&(c=function(e){for(var t=["webgl","experimental-webgl"],r=null,n=0;nl.attribute[e],set(t){l.attribute[e].load(t)}}),r},r.uniform=function(e,t,n){return l.allocate("uniform",e,t,n),r.uniform.hasOwnProperty(e)||Object.defineProperty(r.uniform,e,{get:function(){return l.uniform[e]},set:function(t){l.uniform[e].load(t),c.isProgram(p)&&l.uniform[e].link(p)}}),r},r.uniform.serialize=function(e){var t=[];return e.forEach(function(e){t=t.concat(e)}),t},r.texture=function(e,t,n,i,a,u){return l.allocate("texture",e,t,i,a,n,u),Object.defineProperty(r.texture,e,{get:function(){return l.texture[e]},set:function(t){l.texture[e].load(t)}}),r},r.texture.update=function(e,t,r,n){l.texture[e].update(t,r,n)},r.varying=function(e,t,n){return l.allocate("varying",e,t,n),r},r.framebuffer=function(e,t,n,i){return i=i||l.allocate("texture",e,t,n,"rgba",null),d.create(e,t,n,i),r.framebuffer.hasOwnProperty(e)||Object.defineProperty(r.framebuffer,e,{get:function(){return d[e]}}),r},r.framebuffer.enableRead=function(e,t){d[e].enableRead(t)},r.bindFramebuffer=function(e){null===e?c.bindFramebuffer(c.FRAMEBUFFER,null):c.bindFramebuffer(c.FRAMEBUFFER,d[e].ptr)},r.subroutine=function(e,t,n){return l.allocate("subroutine",e,t,n),r},r.parameter=function(e){return Object.keys(e).forEach(function(t){if(c._dict[t]=e[t],Array.isArray(c._dict[t])){var r=0;Object.defineProperty(c._dict,t,{get:function(){return e[t][r++]},set:function(e){r=0,c._dict[t]=e}})}else if("object"==typeof c._dict[t]){var n=Object.keys(c._dict[t]);fxgl.uniform("dict"+t,"float",n.map(e=>c._dict[t][e]))}}),r},r.dictionary=r.parameter,r.shader=h.shader,r.app=function(e,t){return function(n){return p=h.use(e,t.vertex_shader_source,t.fragment_shader_source),t.render.call(r,n)}},r.dimension=function(){return[u.width,u.height]},r})}]); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vc3JjL3VuaWZvcm0uanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3Jlc291cmNlLmpzIiwid2VicGFjazovLy8uL3NyYy9hdHRyaWJ1dGUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3RleHR1cmUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3ZhcnlpbmcuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3N1YnJvdXRpbmUuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2ZsZXhnbC5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvYnVuZGxlLmpzIiwid2VicGFjazovLy8uL3NyYy9mcmFtZWJ1ZmZlci5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvcHJvZ3JhbS5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvc2hhZGVyLmpzIl0sIm5hbWVzIjpbImluc3RhbGxlZE1vZHVsZXMiLCJfX3dlYnBhY2tfcmVxdWlyZV9fIiwibW9kdWxlSWQiLCJleHBvcnRzIiwibW9kdWxlIiwiaSIsImwiLCJtb2R1bGVzIiwiY2FsbCIsIm0iLCJjIiwiZCIsIm5hbWUiLCJnZXR0ZXIiLCJvIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwiZ2V0IiwiciIsIlN5bWJvbCIsInRvU3RyaW5nVGFnIiwidmFsdWUiLCJ0IiwibW9kZSIsIl9fZXNNb2R1bGUiLCJucyIsImNyZWF0ZSIsImtleSIsImJpbmQiLCJuIiwiZGVmYXVsdCIsIm9iamVjdCIsInByb3BlcnR5IiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJwIiwicyIsImUiLCJVbmlmb3JtIiwiZ2xDb250ZXh0IiwidHlwZSIsImRhdGEiLCJ1bmlmb3JtIiwidGhpcyIsImN0eCIsInNlcmlhbGl6ZUFycmF5IiwiYXJyYXlPZkFycmF5Iiwic2EiLCJmb3JFYWNoIiwiYSIsImNvbmNhdCIsIkFycmF5IiwiaXNBcnJheSIsImZpbHRlciIsImxvY2F0aW9uIiwic2l6ZSIsInBhcnNlSW50Iiwic2xpY2UiLCJsaW5rIiwicHJvZ3JhbSIsImdldFVuaWZvcm1Mb2NhdGlvbiIsImJ1ZiIsIkFycmF5QnVmZmVyIiwiaXNWaWV3IiwiRmxvYXQzMkFycmF5IiwiSW50MzJBcnJheSIsInJlc291cmNlVHlwZSIsImFjdGl2ZVRleHR1cmUiLCJURVhUVVJFMCIsImluZGV4IiwiYmluZFRleHR1cmUiLCJURVhUVVJFXzJEIiwicHRyIiwidW5pZm9ybTFpIiwibG9hZCIsImhlYWRlciIsImxlbiIsImxlbmd0aCIsIlJlc291cmNlIiwicmVzb3VyY2UiLCJncHVSZXNvdXJjZXMiLCJhdHRyaWJ1dGUiLCJBdHRyaWJ1dGUiLCJhdHRyaWJ1dGVJRCIsInNldEF0dHJpYnV0ZSIsImJpbmRCdWZmZXIiLCJBUlJBWV9CVUZGRVIiLCJidWZmZXJEYXRhIiwiU1RBVElDX0RSQVciLCJjcmVhdGVCdWZmZXIiLCJnZXRBdHRyaWJMb2NhdGlvbiIsInZlcnRleEF0dHJpYlBvaW50ZXIiLCJGTE9BVCIsImVuYWJsZVZlcnRleEF0dHJpYkFycmF5IiwiYXJyYXlCdWZmZXIiLCJkZWxldGUiLCJkZWxldGVCdWZmZXIiLCJ0ZXh0dXJlIiwiVGV4dHVyZSIsInRleHR1cmVJRCIsInNldFRleHR1cmUiLCJ0ZXhEYXRhIiwidG9VcHBlckNhc2UiLCJmb3JtYXQiLCJjaGFubmVsIiwid2lkdGgiLCJkaW0iLCJoZWlnaHQiLCJ0ZXhJbWFnZTJEIiwidGV4UGFyYW1ldGVyaSIsIlRFWFRVUkVfTUlOX0ZJTFRFUiIsIk5FQVJFU1QiLCJURVhUVVJFX01BR19GSUxURVIiLCJURVhUVVJFX1dSQVBfUyIsIkNMQU1QX1RPX0VER0UiLCJURVhUVVJFX1dSQVBfVCIsInNhbXBsZXIiLCJ0ZXhJbmRleCIsImNyZWF0ZVRleHR1cmUiLCJjb3B5RnJvbUZCTyIsImNvcHlUZXhJbWFnZTJEIiwiUkdCQSIsInVwZGF0ZSIsIm9mZnNldCIsInRleFN1YkltYWdlMkQiLCJyZXNpemUiLCJkZWxldGVUZXh0dXJlIiwidmFyeWluZyIsIlZhcnlpbmciLCJzdWJyb3V0aW5lIiwiU3Vicm91dGluZSIsImZuIiwidG9TdHJpbmciLCJyZXNvdXJjZVR5cGVzIiwiYWxsb2NhdGUiLCJpbmRleE9mIiwiRXJyb3IiLCJyZXMiLCJhcHBseSIsImFyZ3VtZW50cyIsInNldCIsInJlc291cmNlX25hbWVzIiwia2V5cyIsInJlc291cmNlTmFtZSIsImZsZXhnbCIsIndpbmRvdyIsIkZsZXhHTCIsImFyZyIsIm9wdGlvbnMiLCJjb250YWluZXIiLCJjYW52YXMiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJwYWRkaW5nIiwibGVmdCIsInJpZ2h0IiwidG9wIiwiYm90dG9tIiwiY29udGV4dCIsInNoYXJlZEZ1bmN0aW9uIiwiZ2V0RWxlbWVudEJ5SWQiLCJjYXZuYXMiLCJzdWJzdHJpbmciLCJjbGllbnRXaWR0aCIsImNsaWVudEhlaWdodCIsInN0eWxlIiwicG9zaXRpb24iLCJtYXJnaW5MZWZ0IiwibWFyZ2luVG9wIiwibmFtZXMiLCJnbCIsImdldENvbnRleHQiLCJyZXNvdXJjZXMiLCJfZGljdCIsImVudiIsImRpY3QiLCJkaWN0aW9uYXJ5IiwiZnJhbWVidWZmZXJzIiwiRnJhbWVidWZmZXIiLCJmcmFtZWJ1ZmZlciIsImNyZWF0ZUZyYW1lYnVmZmVyIiwiYmluZEZyYW1lYnVmZmVyIiwiRlJBTUVCVUZGRVIiLCJmcmFtZWJ1ZmZlclRleHR1cmUyRCIsIkNPTE9SX0FUVEFDSE1FTlQwIiwiZW5hYmxlUmVhZCIsImJpbmRSZW5kZXJidWZmZXIiLCJSRU5ERVJCVUZGRVIiLCJkZWxldGVSZW5kZXJidWZmZXIiLCJyZW5kZXJidWZmZXIiLCJkZWxldGVGcmFtZWJ1ZmZlciIsImtlcm5lbHMiLCJzaGFkZXIiLCJTaGFkZXIiLCJ2ZXJ0ZXhfc2hhZGVyX3NvdXJjZSIsImZyYWdtZW50X3NoYWRlcl9zb3VyY2UiLCJjcmVhdGVTaGFkZXIiLCJzb3VyY2UiLCJzaGFkZXJTb3VyY2UiLCJjb21waWxlU2hhZGVyIiwiZ2V0U2hhZGVyUGFyYW1ldGVyIiwiQ09NUElMRV9TVEFUVVMiLCJjb25zb2xlIiwibG9nIiwiZ2V0U2hhZGVySW5mb0xvZyIsImRlbGV0ZVNoYWRlciIsImFkZERlcHMiLCJkZXBzIiwicmUiLCJzcGxpdCIsInYiLCJyZXN1bHQiLCJleGVjIiwicHVzaCIsInZzIiwiVkVSVEVYX1NIQURFUiIsImZzIiwiRlJBR01FTlRfU0hBREVSIiwiY3JlYXRlUHJvZ3JhbSIsImF0dGFjaFNoYWRlciIsImxpbmtQcm9ncmFtIiwiZ2V0UHJvZ3JhbVBhcmFtZXRlciIsIkxJTktfU1RBVFVTIiwiZ2V0UHJvZ3JhbUluZm9Mb2ciLCJ1c2UiLCJ1c2VQcm9ncmFtIiwiZGV0YWNoU2hhZGVyIiwiZGVsZXRlUHJvZ3JhbSIsInJlYWxQcm9ncmFtIiwiYmxlbmRFeHQiLCJnZXRFeHRlbnNpb24iLCJlbmFibGVFeHRlbnNpb24iLCJleHRlbnNpb25zIiwiZXh0ZW5zaW9uIiwiZXh0UHJvcHMiLCJlcCIsImV4dCIsIk1BWF9FWFQiLCJNSU5fRVhUIiwiYXBwZW5kQ2hpbGQiLCJbb2JqZWN0IE9iamVjdF0iLCJpc1Byb2dyYW0iLCJzZXJpYWxpemUiLCJhb2EiLCJmYk5hbWUiLCJwYXJhbWV0ZXIiLCJrZXlWYWx1ZVBhaXJzIiwibmV3QXJyYXkiLCJkaWN0S2V5cyIsImZ4Z2wiLCJtYXAiLCJhcHAiLCJhcmdzIiwicmVuZGVyIiwiZGltZW5zaW9uIl0sIm1hcHBpbmdzIjoiYUFDQSxJQUFBQSxLQUdBLFNBQUFDLEVBQUFDLEdBR0EsR0FBQUYsRUFBQUUsR0FDQSxPQUFBRixFQUFBRSxHQUFBQyxRQUdBLElBQUFDLEVBQUFKLEVBQUFFLElBQ0FHLEVBQUFILEVBQ0FJLEtBQ0FILFlBVUEsT0FOQUksRUFBQUwsR0FBQU0sS0FBQUosRUFBQUQsUUFBQUMsSUFBQUQsUUFBQUYsR0FHQUcsRUFBQUUsS0FHQUYsRUFBQUQsUUFLQUYsRUFBQVEsRUFBQUYsRUFHQU4sRUFBQVMsRUFBQVYsRUFHQUMsRUFBQVUsRUFBQSxTQUFBUixFQUFBUyxFQUFBQyxHQUNBWixFQUFB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R0FtQkEsT0FsQkF4TyxPQUFBZ0ksS0FBQXdHLEdBQUF0TSxRQUFBLFNBQUFyQixHQUVBLEdBREFpQixFQUFBaUksTUFBQWxKLEdBQUEyTixFQUFBM04sR0FDQXdCLE1BQUFDLFFBQUFSLEVBQUFpSSxNQUFBbEosSUFBQSxDQUNBLElBQUF2QixFQUFBLEVBQ0FVLE9BQUFDLGVBQUE2QixFQUFBaUksTUFBQWxKLEdBQ0FWLElBQUEsV0FDQSxPQUFBcU8sRUFBQTNOLEdBQUF2QixNQUVBd0ksSUFBQSxTQUFBMkcsR0FDQW5QLEVBQUEsRUFDQXdDLEVBQUFpSSxNQUFBbEosR0FBQTROLFVBR2Esb0JBQUEzTSxFQUFBaUksTUFBQWxKLEdBQUEsQ0FDYixJQUFBNk4sRUFBQTFPLE9BQUFnSSxLQUFBbEcsRUFBQWlJLE1BQUFsSixJQUNBOE4sS0FBQS9NLFFBQUEsT0FBQWYsRUFBQSxRQUFBNk4sRUFBQUUsSUFBQWhQLEdBQUFrQyxFQUFBaUksTUFBQWxKLEdBQUFqQixRQUdBc0ksR0FHQUEsRUFBQWdDLFdBQUFoQyxFQUFBcUcsVUFDQXJHLEVBQUFnRCxPQUFBckksRUFBQXFJLE9BR0FoRCxFQUFBMkcsSUFBQSxTQUFBaFAsRUFBQXlJLEdBQ0EsZ0JBQUF3RyxHQUVBLE9BREF4QixFQUFBekssRUFBQXFLLElBQUFyTixFQUFBeUksRUFBQThDLHFCQUFBOUMsRUFBQStDLHdCQUNBL0MsRUFBQXlHLE9BQUF0UCxLQUFBeUksRUFBQTRHLEtBSUE1RyxFQUFBOEcsVUFBQSxXQUNBLE9BQUF4RyxFQUFBN0MsTUFBQTZDLEVBQUEzQyxTQUdBcUMiLCJmaWxlIjoiZmxleGdsLm1pbi5qcyIsInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIGhhcm1vbnkgZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGdldHRlciB9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcbiBcdFx0fVxuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gY3JlYXRlIGEgZmFrZSBuYW1lc3BhY2Ugb2JqZWN0XG4gXHQvLyBtb2RlICYgMTogdmFsdWUgaXMgYSBtb2R1bGUgaWQsIHJlcXVpcmUgaXRcbiBcdC8vIG1vZGUgJiAyOiBtZXJnZSBhbGwgcHJvcGVydGllcyBvZiB2YWx1ZSBpbnRvIHRoZSBuc1xuIFx0Ly8gbW9kZSAmIDQ6IHJldHVybiB2YWx1ZSB3aGVuIGFscmVhZHkgbnMgb2JqZWN0XG4gXHQvLyBtb2RlICYgOHwxOiBiZWhhdmUgbGlrZSByZXF1aXJlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnQgPSBmdW5jdGlvbih2YWx1ZSwgbW9kZSkge1xuIFx0XHRpZihtb2RlICYgMSkgdmFsdWUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKHZhbHVlKTtcbiBcdFx0aWYobW9kZSAmIDgpIHJldHVybiB2YWx1ZTtcbiBcdFx0aWYoKG1vZGUgJiA0KSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICYmIHZhbHVlLl9fZXNNb2R1bGUpIHJldHVybiB2YWx1ZTtcbiBcdFx0dmFyIG5zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yKG5zKTtcbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KG5zLCAnZGVmYXVsdCcsIHsgZW51bWVyYWJsZTogdHJ1ZSwgdmFsdWU6IHZhbHVlIH0pO1xuIFx0XHRpZihtb2RlICYgMiAmJiB0eXBlb2YgdmFsdWUgIT0gJ3N0cmluZycpIGZvcih2YXIga2V5IGluIHZhbHVlKSBfX3dlYnBhY2tfcmVxdWlyZV9fLmQobnMsIGtleSwgZnVuY3Rpb24oa2V5KSB7IHJldHVybiB2YWx1ZVtrZXldOyB9LmJpbmQobnVsbCwga2V5KSk7XG4gXHRcdHJldHVybiBucztcbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSAwKTtcbiIsImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIFVuaWZvcm0oZ2xDb250ZXh0LCBuYW1lLCB0eXBlLCBkYXRhKSB7XG5cbiAgICB2YXIgdW5pZm9ybSA9ICh0aGlzIGluc3RhbmNlb2YgVW5pZm9ybSkgPyB0aGlzIDoge30sXG4gICAgICAgIGN0eCA9IGdsQ29udGV4dDtcblxuICAgIGZ1bmN0aW9uIHNlcmlhbGl6ZUFycmF5KGFycmF5T2ZBcnJheSkge1xuICAgICAgICB2YXIgc2EgPSBbXTtcbiAgICAgICAgYXJyYXlPZkFycmF5LmZvckVhY2goZnVuY3Rpb24oYSl7XG4gICAgICAgICAgICBzYSA9IHNhLmNvbmNhdChhKTtcbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIHNhO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldFVuaWZvcm0oKSB7XG4gICAgICAgIHZhciB0eXBlID0gdGhpcy50eXBlLFxuICAgICAgICAgICAgbG9jYXRpb24gPSB0aGlzLmxvY2F0aW9uLFxuICAgICAgICAgICAgc2l6ZSA9IHRoaXMuc2l6ZSxcbiAgICAgICAgICAgIGRhdGEgPSB0aGlzLmRhdGE7XG5cbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgICAgdmFyIGhhc0FycmF5ID0gZGF0YS5maWx0ZXIoZnVuY3Rpb24oZCl7cmV0dXJuIEFycmF5LmlzQXJyYXkoZCk7fSk7XG4gICAgICAgICAgICBpZihoYXNBcnJheSlcbiAgICAgICAgICAgICAgICBkYXRhID0gc2VyaWFsaXplQXJyYXkoZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZigodHlwZSA9PSAnZmxvYXQnIHx8IHR5cGUgPT0gJ2ludCcpICYmICFBcnJheS5pc0FycmF5KGRhdGEpICYmICFBcnJheUJ1ZmZlci5pc1ZpZXcoZGF0YSkpXG4gICAgICAgICAgICBkYXRhID0gW2RhdGFdO1xuXG4gICAgICAgIHZhciBidWY7XG4gICAgICAgIGlmICh0eXBlLnNsaWNlKDAsMykgPT0gJ3ZlYycgfHwgdHlwZSA9PSAnZmxvYXQnKSB7XG4gICAgICAgICAgICBidWYgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEpO1xuICAgICAgICAgICAgY3R4Wyd1bmlmb3JtJyArIHNpemUgKyAnZnYnXShsb2NhdGlvbiwgYnVmKTtcbiAgICAgICAgfSBlbHNlIGlmKHR5cGUuc2xpY2UoMCw0KSA9PSAnaXZlYycgfHwgdHlwZSA9PSAnaW50Jyl7XG4gICAgICAgICAgICBidWYgPSBuZXcgSW50MzJBcnJheShkYXRhKTtcbiAgICAgICAgICAgIGN0eFsndW5pZm9ybScgKyBzaXplICsgJ2l2J10obG9jYXRpb24sIGJ1Zik7XG4gICAgICAgIH0gZWxzZSBpZih0eXBlLnNsaWNlKDAsMykgPT0gJ21hdCcpIHtcbiAgICAgICAgICAgIGJ1ZiA9IG5ldyBGbG9hdDMyQXJyYXkoZGF0YSk7XG4gICAgICAgICAgICBjdHhbJ3VuaWZvcm1NYXRyaXgnICsgc2l6ZSArICdmdiddKGxvY2F0aW9uLCBmYWxzZSwgYnVmKTtcbiAgICAgICAgfSBlbHNlIGlmKHR5cGUgPT0gJ3NhbXBsZXIyRCcpIHtcbiAgICAgICAgICAgIGlmKGRhdGEuaGFzT3duUHJvcGVydHkoJ3Jlc291cmNlVHlwZScpICYmIGRhdGEucmVzb3VyY2VUeXBlID09ICd0ZXh0dXJlJykge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdiaW5kICcgKyBkYXRhLmluZGV4KTtcbiAgICAgICAgICAgICAgICBjdHguYWN0aXZlVGV4dHVyZShjdHguVEVYVFVSRTAgKyBkYXRhLmluZGV4KTtcbiAgICAgICAgICAgICAgICBjdHguYmluZFRleHR1cmUoY3R4LlRFWFRVUkVfMkQsIGRhdGEucHRyKTtcbiAgICAgICAgICAgICAgICBjdHgudW5pZm9ybTFpKGxvY2F0aW9uLCBkYXRhLmluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVuaWZvcm0uY3JlYXRlID0gZnVuY3Rpb24obmFtZSwgdHlwZSwgZGF0YSkge1xuXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgICAgIHZhciBoYXNBcnJheSA9IGRhdGEuZmlsdGVyKGZ1bmN0aW9uKGQpe3JldHVybiBBcnJheS5pc0FycmF5KGQpO30pO1xuICAgICAgICAgICAgaWYoaGFzQXJyYXkpXG4gICAgICAgICAgICAgICAgZGF0YSA9IHNlcmlhbGl6ZUFycmF5KGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgdW5pZm9ybVtuYW1lXSA9IHtcbiAgICAgICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICAgIGxvY2F0aW9uOiBudWxsLFxuICAgICAgICAgICAgc2l6ZTogcGFyc2VJbnQodHlwZS5zbGljZSgzLDQpKSB8fCBwYXJzZUludCh0eXBlLnNsaWNlKDQsNSkpIHx8IDFcbiAgICAgICAgfTtcblxuICAgICAgICB1bmlmb3JtW25hbWVdLmxpbmsgPSBmdW5jdGlvbihwcm9ncmFtKSB7XG4gICAgICAgICAgICBpZih0eXBlb2YgdGhpcy5kYXRhICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLmRhdGEgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2F0aW9uID0gY3R4LmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCB0aGlzLm5hbWUpO1xuICAgICAgICAgICAgICAgIHNldFVuaWZvcm0uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9O1xuXG4gICAgICAgIHVuaWZvcm1bbmFtZV0ubG9hZCA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcblxuICAgICAgICB1bmlmb3JtW25hbWVdLmhlYWRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhlYWRlciA9ICd1bmlmb3JtICcgKyB0aGlzLnR5cGUgKyAnICcgKyB0aGlzLm5hbWUsXG4gICAgICAgICAgICAgICAgbGVuID0gMDtcblxuICAgICAgICAgICAgaWYodGhpcy50eXBlICE9ICdzYW1wbGVyMkQnKSB7XG4gICAgICAgICAgICAgICAgbGVuID0gdGhpcy5kYXRhLmxlbmd0aCAvIHRoaXMuc2l6ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9UT0RPOiBmaXggZGVjbGFyYXRpb24gZm9yIG1hdHJpeFxuICAgICAgICAgICAgaWYobGVuID4gMSAmJiB0eXBlICE9ICdtYXQ0Jykge1xuICAgICAgICAgICAgICAgIGhlYWRlciArPSAnWycgKyBsZW4gKyAnXSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaGVhZGVyICsgJztcXG4nO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB1bmlmb3JtW25hbWVdO1xuICAgIH1cblxuXG4gICAgcmV0dXJuIHVuaWZvcm07XG59XG4iLCJpbXBvcnQgVW5pZm9ybSBmcm9tICcuL3VuaWZvcm0nO1xuaW1wb3J0IEF0dHJpYnV0ZSBmcm9tICcuL2F0dHJpYnV0ZSc7XG5pbXBvcnQgVGV4dHVyZSBmcm9tICcuL3RleHR1cmUnO1xuaW1wb3J0IFZhcnlpbmcgZnJvbSAnLi92YXJ5aW5nJztcbmltcG9ydCBTdWJyb3V0aW5lIGZyb20gJy4vc3Vicm91dGluZSc7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIFJlc291cmNlKGdsQ29udGV4dCkgXG57XG4gICAgdmFyIHJlc291cmNlID0gKHRoaXMgaW5zdGFuY2VvZiBSZXNvdXJjZSkgPyB0aGlzIDoge30sXG4gICAgICAgIGdwdVJlc291cmNlcyA9IHt9O1xuXG4gICAgcmVzb3VyY2UudW5pZm9ybSA9IG5ldyBVbmlmb3JtKGdsQ29udGV4dCk7XG4gICAgcmVzb3VyY2UuYXR0cmlidXRlID0gbmV3IEF0dHJpYnV0ZShnbENvbnRleHQpO1xuICAgIHJlc291cmNlLnRleHR1cmUgPSBuZXcgVGV4dHVyZShnbENvbnRleHQpO1xuICAgIHJlc291cmNlLnZhcnlpbmcgPSBuZXcgVmFyeWluZyhnbENvbnRleHQpO1xuICAgIHJlc291cmNlLnN1YnJvdXRpbmUgPSBuZXcgU3Vicm91dGluZSgpO1xuXG4gICAgdmFyIHJlc291cmNlVHlwZXMgPSBbJ3VuaWZvcm0nLCAnYXR0cmlidXRlJywgJ3RleHR1cmUnLCAndmFyeWluZycsICdzdWJyb3V0aW5lJ107XG5cbiAgICByZXNvdXJjZS5hbGxvY2F0ZSA9IGZ1bmN0aW9uKHR5cGUpIFxuICAgIHtcbiAgICAgICAgaWYgKHJlc291cmNlVHlwZXMuaW5kZXhPZih0eXBlKSA9PT0gLTEpICB7IHRocm93IEVycm9yKFwiRXJyb3I6IEludmFsaWQgcmVzb3VyY2UgdHlwZTogXCIgKyB0eXBlKTsgfVxuICAgICAgICBcbiAgICAgICAgdmFyIHJlcyA9IHJlc291cmNlW3R5cGVdLmNyZWF0ZS5hcHBseShudWxsLCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICAgICAgcmVzLnJlc291cmNlVHlwZSA9IHR5cGU7XG4gICAgICAgIGdwdVJlc291cmNlc1tyZXMubmFtZV0gPSByZXM7XG5cbiAgICAgICAgaWYgKCFncHVSZXNvdXJjZXMuaGFzT3duUHJvcGVydHkocmVzLm5hbWUpKSBcbiAgICAgICAge1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGdwdVJlc291cmNlcywgcmVzLm5hbWUsIHtcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gZ3B1UmVzb3VyY2VzW3Jlcy5uYW1lXTt9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oZGF0YSkgeyBncHVSZXNvdXJjZXNbcmVzLm5hbWVdLmxvYWQoZGF0YSk7fVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuXG4gICAgcmVzb3VyY2UubGluayA9IGZ1bmN0aW9uKHByb2dyYW0sIHJlc291cmNlX25hbWVzKSB7XG4gICAgICAgIHZhciByZXF1aXJlZFJlc291cmNlTmFtZXMgPSAoQXJyYXkuaXNBcnJheShyZXNvdXJjZV9uYW1lcykpID8gcmVzb3VyY2VfbmFtZXMgOiBPYmplY3Qua2V5cyhncHVSZXNvdXJjZXMpO1xuICAgICAgICByZXF1aXJlZFJlc291cmNlTmFtZXMuZm9yRWFjaChmdW5jdGlvbihyZXNvdXJjZU5hbWUpIHtcbiAgICAgICAgICAgIGlmIChncHVSZXNvdXJjZXMuaGFzT3duUHJvcGVydHkocmVzb3VyY2VOYW1lKSkge1xuICAgICAgICAgICAgICAgIGdwdVJlc291cmNlc1tyZXNvdXJjZU5hbWVdLmxpbmsocHJvZ3JhbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgfTtcblxuICAgIHJlc291cmNlLmdldCA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGdwdVJlc291cmNlc1tuYW1lXTtcbiAgICB9XG4gICAgcmVzb3VyY2UuY3JlYXRlID0gcmVzb3VyY2UuYWxsb2NhdGU7XG5cbiAgICByZXR1cm4gcmVzb3VyY2U7XG59O1xuIiwiZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gQXR0cmlidXRlKGdsQ29udGV4dCkgXG57XG4gICAgdmFyIGF0dHJpYnV0ZSA9ICh0aGlzIGluc3RhbmNlb2YgQXR0cmlidXRlKSA/IHRoaXMgOiB7fSxcbiAgICAgICAgY3R4ID0gZ2xDb250ZXh0LFxuICAgICAgICBhdHRyaWJ1dGVJRCA9IDA7XG5cbiAgICBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZSwgZGF0YSkgXG4gICAge1xuICAgICAgICBpZiggQXJyYXkuaXNBcnJheShkYXRhKSB8fCBBcnJheUJ1ZmZlci5pc1ZpZXcoZGF0YSkgKVxuICAgICAgICB7XG4gICAgICAgICAgICBpZighQXJyYXlCdWZmZXIuaXNWaWV3KGRhdGEpKSBcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gbmV3IEZsb2F0MzJBcnJheShkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF0dHJpYnV0ZVtuYW1lXS5kYXRhID0gZGF0YTtcbiAgICAgICAgICAgIGN0eC5iaW5kQnVmZmVyKGN0eC5BUlJBWV9CVUZGRVIsIGF0dHJpYnV0ZVtuYW1lXS5wdHIpO1xuICAgICAgICAgICAgY3R4LmJ1ZmZlckRhdGEoY3R4LkFSUkFZX0JVRkZFUiwgZGF0YSwgY3R4LlNUQVRJQ19EUkFXKTtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGF0dHJpYnV0ZVtuYW1lXS5wdHIgPT09IGF0dHJpYnV0ZVtuYW1lXS5vbGRfcHRyKTtcbiAgICAgICAgICAgIC8vIGF0dHJpYnV0ZVtuYW1lXS5vbGRfcHRyID0gYXR0cmlidXRlW25hbWVdLnB0cjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGF0dHJpYnV0ZS5jcmVhdGUgPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBkYXRhKSBcbiAgICB7XG4gICAgICAgIGF0dHJpYnV0ZVtuYW1lXSA9IHtcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgICB0eXBlOiB0eXBlIHx8ICdmbG9hdCcsXG4gICAgICAgICAgICBkYXRhOiBudWxsLFxuICAgICAgICAgICAgbG9jYXRpb246IGF0dHJpYnV0ZUlEKyssXG4gICAgICAgICAgICBwdHI6IGN0eC5jcmVhdGVCdWZmZXIoKSxcbiAgICAgICAgICAgIHNpemU6IHBhcnNlSW50KHR5cGUuc2xpY2UoMyw0KSkgfHwgMVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmKGRhdGEgIT09IG51bGwgJiYgZGF0YS5sZW5ndGgpIFxuICAgICAgICAgICAge3NldEF0dHJpYnV0ZShuYW1lLCBkYXRhKTt9XG5cbiAgICAgICAgYXR0cmlidXRlW25hbWVdLmxpbmsgPSBmdW5jdGlvbihwcm9ncmFtKSBcbiAgICAgICAge1xuICAgICAgICAgICAgY3R4LmJpbmRCdWZmZXIoY3R4LkFSUkFZX0JVRkZFUiwgdGhpcy5wdHIpO1xuICAgICAgICAgICAgdGhpcy5sb2NhdGlvbiA9IGN0eC5nZXRBdHRyaWJMb2NhdGlvbihwcm9ncmFtLCB0aGlzLm5hbWUpO1xuICAgICAgICAgICAgY3R4LnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5sb2NhdGlvbiwgdGhpcy5zaXplLCBjdHguRkxPQVQsIGZhbHNlLCAwLCAwKTtcbiAgICAgICAgICAgIGN0eC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheSh0aGlzLmxvY2F0aW9uKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgYXR0cmlidXRlW25hbWVdLmxvYWQgPSBmdW5jdGlvbihhcnJheUJ1ZmZlcikgXG4gICAgICAgIHtcbiAgICAgICAgICAgIHNldEF0dHJpYnV0ZSh0aGlzLm5hbWUsIGFycmF5QnVmZmVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgYXR0cmlidXRlW25hbWVdLmhlYWRlciA9IGZ1bmN0aW9uKCkgXG4gICAgICAgICAgICB7cmV0dXJuICdhdHRyaWJ1dGUgJyArIHRoaXMudHlwZSArICcgJyArIHRoaXMubmFtZSArICc7XFxuJzt9XG4gICAgICAgIFxuXG4gICAgICAgIGF0dHJpYnV0ZVtuYW1lXS5kZWxldGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGN0eC5kZWxldGVCdWZmZXIodGhpcy5wdHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZVtuYW1lXTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGF0dHJpYnV0ZTtcbn1cbiIsImltcG9ydCBVbmlmb3JtIGZyb20gXCIuL3VuaWZvcm1cIjtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gVGV4dHVyZShnbENvbnRleHQpIHtcblxuICAgIHZhciB0ZXh0dXJlID0gKHRoaXMgaW5zdGFuY2VvZiBUZXh0dXJlKSA/IHRoaXMgOiB7fSxcbiAgICAgICAgY3R4ID0gZ2xDb250ZXh0LFxuICAgICAgICB0ZXh0dXJlSUQgPSAwO1xuXG4gICAgZnVuY3Rpb24gc2V0VGV4dHVyZShuYW1lLCB0ZXhEYXRhKSBcbiAgICB7XG4gICAgICAgIHZhciB0eXBlID0gY3R4W3RleHR1cmVbbmFtZV0udHlwZS50b1VwcGVyQ2FzZSgpXSxcbiAgICAgICAgICAgIGZvcm1hdCA9IGN0eFt0ZXh0dXJlW25hbWVdLmNoYW5uZWwudG9VcHBlckNhc2UoKV0sXG4gICAgICAgICAgICB3aWR0aCA9IHRleHR1cmVbbmFtZV0uZGltWzBdLFxuICAgICAgICAgICAgaGVpZ2h0ID0gdGV4dHVyZVtuYW1lXS5kaW1bMV07XG5cbiAgICAgICAgdGV4dHVyZVtuYW1lXS5kYXRhID0gdGV4RGF0YTtcblxuICAgICAgICBjdHguYmluZFRleHR1cmUoY3R4LlRFWFRVUkVfMkQsIHRleHR1cmVbbmFtZV0ucHRyKTtcbiAgICAgICAgY3R4LnRleEltYWdlMkQoY3R4LlRFWFRVUkVfMkQsIDAsIGZvcm1hdCwgd2lkdGgsIGhlaWdodCwgMCwgZm9ybWF0LCB0eXBlLCB0ZXhEYXRhKTtcbiAgICAgICAgY3R4LnRleFBhcmFtZXRlcmkoY3R4LlRFWFRVUkVfMkQsIGN0eC5URVhUVVJFX01JTl9GSUxURVIsIGN0eC5ORUFSRVNUKTtcbiAgICAgICAgY3R4LnRleFBhcmFtZXRlcmkoY3R4LlRFWFRVUkVfMkQsIGN0eC5URVhUVVJFX01BR19GSUxURVIsIGN0eC5ORUFSRVNUKTtcbiAgICAgICAgY3R4LnRleFBhcmFtZXRlcmkoY3R4LlRFWFRVUkVfMkQsIGN0eC5URVhUVVJFX1dSQVBfUywgY3R4LkNMQU1QX1RPX0VER0UpO1xuICAgICAgICBjdHgudGV4UGFyYW1ldGVyaShjdHguVEVYVFVSRV8yRCwgY3R4LlRFWFRVUkVfV1JBUF9ULCBjdHguQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIGN0eC5iaW5kVGV4dHVyZShjdHguVEVYVFVSRV8yRCwgbnVsbCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlVGV4dHVyZShuYW1lLCB0ZXhEYXRhLCBvZmZzZXQsIGRpbSkge1xuICAgICAgICB2YXIgdHlwZSA9IGN0eFt0ZXh0dXJlW25hbWVdLnR5cGUudG9VcHBlckNhc2UoKV0sXG4gICAgICAgICAgICBmb3JtYXQgPSBjdHhbdGV4dHVyZVtuYW1lXS5jaGFubmVsLnRvVXBwZXJDYXNlKCldLFxuICAgICAgICAgICAgd2lkdGggPSBkaW1bMF0gfHwgdGV4dHVyZVtuYW1lXS5kaW1bMF0sXG4gICAgICAgICAgICBoZWlnaHQgPSBkaW1bMV0gfHwgdGV4dHVyZVtuYW1lXS5kaW1bMV07XG5cbiAgICAgICAgY3R4LmJpbmRUZXh0dXJlKGN0eC5URVhUVVJFXzJELCB0ZXh0dXJlW25hbWVdLnB0cik7XG4gICAgICAgIGN0eC50ZXhTdWJJbWFnZTJEKGN0eC5URVhUVVJFXzJELCAwLCBvZmZzZXRbMF0sIG9mZnNldFsxXSwgd2lkdGgsIGhlaWdodCwgZm9ybWF0LCB0eXBlLCB0ZXhEYXRhKTtcbiAgICAgICAgY3R4LmJpbmRUZXh0dXJlKGN0eC5URVhUVVJFXzJELCBudWxsKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBBZGQgc3VwcG9ydCBmb3IgdGV4dHVyZSBjb21wcmVzc2lvblxuICAgIC8vIGZ1bmN0aW9uIGNvbXByZXNzVGV4dHVyZSh0ZXhEYXRhKSB7XG4gICAgLy9cbiAgICAvLyAgICAgdmFyIGV4dCA9IChcbiAgICAvLyAgICAgICBjdHguZ2V0RXh0ZW5zaW9uKFwiV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX3MzdGNcIikgfHxcbiAgICAvLyAgICAgICBjdHguZ2V0RXh0ZW5zaW9uKFwiTU9aX1dFQkdMX2NvbXByZXNzZWRfdGV4dHVyZV9zM3RjXCIpIHx8XG4gICAgLy8gICAgICAgY3R4LmdldEV4dGVuc2lvbihcIldFQktJVF9XRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfczN0Y1wiKVxuICAgIC8vICAgICApO1xuICAgIC8vXG4gICAgLy8gICAgIGN0eC5jb21wcmVzc2VkVGV4SW1hZ2UyRChjdHguVEVYVFVSRV8yRCwgMCwgZXh0LkNPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDNfRVhULCB0ZXh0dXJlW25hbWVdLmRpbVswXSwgdGV4dHVyZVtuYW1lXS5kaW1bMV0sIDAsIHRleERhdGEpO1xuICAgIC8vICAgICBjdHgudGV4UGFyYW1ldGVyaShjdHguVEVYVFVSRV8yRCwgY3R4LlRFWFRVUkVfTUFHX0ZJTFRFUiwgY3R4LkxJTkVBUik7XG4gICAgLy8gICAgIGN0eC50ZXhQYXJhbWV0ZXJpKGN0eC5URVhUVVJFXzJELCBjdHguVEVYVFVSRV9NSU5fRklMVEVSLCBjdHguTElORUFSKTtcbiAgICAvLyB9XG5cbiAgICB0ZXh0dXJlLmNyZWF0ZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIGRpbSwgY2hhbm5lbCwgZGF0YSwgc2FtcGxlcikge1xuICAgICAgICB2YXIgdGV4SW5kZXggPSAodGV4dHVyZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgPyB0ZXh0dXJlW25hbWVdLmluZGV4IDogdGV4dHVyZUlEKys7XG4gICAgICAgIHRleHR1cmVbbmFtZV0gPSB7XG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgaW5kZXg6IHRleEluZGV4LFxuICAgICAgICAgICAgdHlwZTogdHlwZSB8fCBcImZsb2F0XCIsXG4gICAgICAgICAgICBkaW06IGRpbSB8fCBbNTEyLCA1MTJdLFxuICAgICAgICAgICAgY2hhbm5lbDogY2hhbm5lbCB8fCBcImFscGhhXCIsXG4gICAgICAgICAgICBkYXRhOiBudWxsLFxuICAgICAgICAgICAgbG9jYXRpb246IG51bGwsXG4gICAgICAgICAgICBzYW1wbGVyOiBzYW1wbGVyIHx8IG51bGwsXG4gICAgICAgICAgICBwdHI6IGN0eC5jcmVhdGVUZXh0dXJlKClcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBpZihkYXRhICE9PSBudWxsICYmIGRhdGEubGVuZ3RoKVxuICAgICAgICBzZXRUZXh0dXJlKG5hbWUsIGRhdGEpO1xuXG4gICAgICAgIGlmICh0ZXh0dXJlW25hbWVdLnNhbXBsZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRleHR1cmVbbmFtZV0uc2FtcGxlciA9IFVuaWZvcm0oY3R4KS5jcmVhdGUobmFtZSwgJ3NhbXBsZXIyRCcsIHRleHR1cmVbbmFtZV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGV4dHVyZVtuYW1lXS5zYW1wbGVyLmRhdGEgPSB0ZXh0dXJlW25hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgdGV4dHVyZVtuYW1lXS5saW5rID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICAgICAgICAgICAgLy8gaWYgKHRoaXMuZGF0YSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIGN0eC5hY3RpdmVUZXh0dXJlKGN0eC5URVhUVVJFMCArIHRoaXMuaW5kZXgpO1xuICAgICAgICAgICAgICAgIC8vIGN0eC5iaW5kVGV4dHVyZShjdHguVEVYVFVSRV8yRCwgdGhpcy5wdHIpO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMubG9jYXRpb24gPSBjdHguZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIHRoaXMubmFtZSk7XG4gICAgICAgICAgICAgICAgLy8gY3R4LnVuaWZvcm0xaSh0aGlzLmxvY2F0aW9uLCB0aGlzLmluZGV4KTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mKHRoaXMuc2FtcGxlci5kYXRhKSA9PSAndW5kZWZpbmVkJyB8fCB0aGlzLnNhbXBsZXIuZGF0YSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zYW1wbGVyLmRhdGEgPSB0ZXh0dXJlW25hbWVdO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5zYW1wbGVyLmxpbmsocHJvZ3JhbSk7XG4gICAgICAgICAgICAvLyB9ZWxzZXtcbiAgICAgICAgICAgIC8vICAgICBjb25zb2xlLmxvZygndGV4dHVyZSBkYXRhIGlzIG51bGwhISEnKVxuICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICB0ZXh0dXJlW25hbWVdLmxvYWQgPSBmdW5jdGlvbih0ZXhEYXRhKSB7XG4gICAgICAgICAgICBzZXRUZXh0dXJlKHRoaXMubmFtZSwgdGV4RGF0YSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHRleHR1cmVbbmFtZV0uY29weUZyb21GQk8gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGN0eC5iaW5kVGV4dHVyZShjdHguVEVYVFVSRV8yRCwgdGhpcy5wdHIpO1xuICAgICAgICAgICAgY3R4LmNvcHlUZXhJbWFnZTJEKFxuICAgICAgICAgICAgICAgIGN0eC5URVhUVVJFXzJELFxuICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgY3R4LlJHQkEsXG4gICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIHRoaXMuZGltWzBdLFxuICAgICAgICAgICAgICAgIHRoaXMuZGltWzFdLFxuICAgICAgICAgICAgICAgIDBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjdHguYmluZFRleHR1cmUoY3R4LlRFWFRVUkVfMkQsIG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGV4dHVyZVtuYW1lXS51cGRhdGUgPSBmdW5jdGlvbih0ZXhEYXRhLCBvZmZzZXQsIGRpbSkge1xuICAgICAgICAgICAgdXBkYXRlVGV4dHVyZSh0aGlzLm5hbWUsIHRleERhdGEsIG9mZnNldCwgZGltKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICB0ZXh0dXJlW25hbWVdLnJlc2l6ZSA9IGZ1bmN0aW9uKGRpbSwgZGF0YSkge1xuICAgICAgICAgICAgdGhpcy5kaW0gPSBkaW07XG4gICAgICAgICAgICBzZXRUZXh0dXJlKHRoaXMubmFtZSwgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICB0ZXh0dXJlW25hbWVdLmRlbGV0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgZ2xDb250ZXh0LmRlbGV0ZVRleHR1cmUodGhpcy5wdHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGV4dHVyZVtuYW1lXS5oZWFkZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm5hbWUgPT0gdGhpcy5zYW1wbGVyLm5hbWUpXG4gICAgICAgICAgICAgICAgcmV0dXJuICd1bmlmb3JtIHNhbXBsZXIyRCAnICsgdGhpcy5zYW1wbGVyLm5hbWUgKyAnO1xcbic7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRleHR1cmVbbmFtZV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRleHR1cmU7XG59XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBWYXJ5aW5nKGdsQ29udGV4dCkge1xuXG4gICAgdmFyIHZhcnlpbmcgPSAodGhpcyBpbnN0YW5jZW9mIFZhcnlpbmcpID8gdGhpcyA6IHt9LFxuICAgICAgICBjdHggPSBnbENvbnRleHQ7XG5cbiAgICB2YXJ5aW5nLmNyZWF0ZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIHNpemUpIHtcbiAgICAgICAgdmFyeWluZ1tuYW1lXSA9IHtcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgICAgICB0eXBlOiB0eXBlIHx8ICdmbG9hdCcsXG4gICAgICAgICAgICBzaXplOiBzaXplIHx8IDEsXG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyeWluZ1tuYW1lXS5saW5rID0gZnVuY3Rpb24oKSB7fTtcblxuICAgICAgICB2YXJ5aW5nW25hbWVdLmhlYWRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhlYWRlciA9ICd2YXJ5aW5nICcgKyB0aGlzLnR5cGUgKyAnICcgKyB0aGlzLm5hbWU7XG4gICAgICAgICAgICBpZih0aGlzLnNpemUgPiAxKVxuICAgICAgICAgICAgICAgIGhlYWRlciArPSAnWycgKyB0aGlzLnNpemUgKyAnXSc7XG4gICAgICAgICAgICByZXR1cm4gaGVhZGVyICsgJztcXG4nO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHZhcnlpbmdbbmFtZV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhcnlpbmc7XG59XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBTdWJyb3V0aW5lKCkge1xuXG4gICAgdmFyIHN1YnJvdXRpbmUgPSAodGhpcyBpbnN0YW5jZW9mIFN1YnJvdXRpbmUpID8gdGhpcyA6IHt9O1xuXG4gICAgc3Vicm91dGluZS5jcmVhdGUgPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBmbikge1xuICAgICAgICBzdWJyb3V0aW5lW25hbWVdID0ge1xuICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgIHR5cGU6IHR5cGUgfHwgJ2Zsb2F0JyxcbiAgICAgICAgICAgIGZuOiBmbixcbiAgICAgICAgICAgIHJlc291cmNlVHlwZTogXCJzdWJyb3V0aW5lXCJcbiAgICAgICAgfTtcblxuICAgICAgICBzdWJyb3V0aW5lW25hbWVdLmxpbmsgPSBmdW5jdGlvbihwcm9ncmFtKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHN1YnJvdXRpbmVbbmFtZV0ubG9hZCA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgICAgICAgICBzdWJyb3V0aW5lW25hbWVdLmZuID0gZm47XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHN1YnJvdXRpbmVbbmFtZV0uaGVhZGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mbi50b1N0cmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHN1YnJvdXRpbmVbbmFtZV07XG4gICAgfTtcblxuICAgIHJldHVybiBzdWJyb3V0aW5lO1xufVxuIiwiaW1wb3J0IFJlc291cmNlIGZyb20gJy4vcmVzb3VyY2UnO1xuaW1wb3J0IFByb2dyYW0gZnJvbSAnLi9wcm9ncmFtJztcbmltcG9ydCBGcmFtZWJ1ZmZlciBmcm9tICcuL2ZyYW1lYnVmZmVyJztcbi8vIGltcG9ydCBSZWFjdGl2ZSBmcm9tICcuL3JlYWN0aXZlJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gRmxleEdMKGFyZykge1xuXG4gICAgdmFyIGZsZXhnbCA9ICh0aGlzIGluc3RhbmNlb2YgRmxleEdMKSA/IHRoaXMgOiB7fTtcblxuXG4gICAgdmFyIG9wdGlvbnMgPSBhcmcgfHwge30sXG4gICAgICAgIGNvbnRhaW5lciA9IG9wdGlvbnMuY29udGFpbmVyIHx8IG51bGwsXG4gICAgICAgIGNhbnZhcyA9IG9wdGlvbnMuY2FudmFzIHx8IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIiksXG4gICAgICAgIHdpZHRoID0gb3B0aW9ucy53aWR0aCB8fCBudWxsLFxuICAgICAgICBoZWlnaHQgPSBvcHRpb25zLmhlaWdodCB8fCBudWxsLFxuICAgICAgICBwYWRkaW5nID0gb3B0aW9ucy5wYWRkaW5nIHx8IHtcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICByaWdodDogMCxcbiAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgIGJvdHRvbTogMFxuICAgICAgICB9LFxuICAgICAgICBjdHggPSBvcHRpb25zLmNvbnRleHQgfHwgb3B0aW9ucy5jdHggfHwgbnVsbCxcbiAgICAgICAga2VybmVscyA9IHt9LFxuICAgICAgICBzaGFyZWRGdW5jdGlvbiA9IG9wdGlvbnMuc2hhcmVkRnVuY3Rpb24gfHwge307XG5cblxuXG4gICAgaWYgKHR5cGVvZihjYW52YXMpID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgaWYgKGNhbnZhc1swXSA9PSBcIiNcIikgY2FudmFzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY2F2bmFzLnN1YnN0cmluZygxKSk7XG4gICAgICAgIGVsc2UgY2FudmFzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY2F2bmFzKTtcbiAgICB9XG4gICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICBjb250YWluZXIgPSAodHlwZW9mKGNvbnRhaW5lcikgPT0gXCJzdHJpbmdcIikgPyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChjb250YWluZXIpIDogY29udGFpbmVyO1xuICAgICAgICBpZiAod2lkdGggPT09IG51bGwpIHdpZHRoID0gY29udGFpbmVyLmNsaWVudFdpZHRoO1xuICAgICAgICBpZiAoaGVpZ2h0ID09PSBudWxsKSBoZWlnaHQgPSBjb250YWluZXIuY2xpZW50SGVpZ2h0O1xuICAgIH1cbiAgICAvLyB3aWR0aCAtPSBwYWRkaW5nLmxlZnQgKyBwYWRkaW5nLnJpZ2h0O1xuICAgIC8vIGhlaWdodCAtPSBwYWRkaW5nLnRvcCArIHBhZGRpbmcuYm90dG9tO1xuICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgY2FudmFzLnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgIGNhbnZhcy5zdHlsZS5tYXJnaW5MZWZ0ID0gcGFkZGluZy5sZWZ0ICsgXCJweFwiO1xuICAgIGNhbnZhcy5zdHlsZS5tYXJnaW5Ub3AgPSBwYWRkaW5nLnRvcCArIFwicHhcIjtcblxuXG4gICAgaWYgKGN0eCA9PT0gbnVsbClcbiAgICAgICAgY3R4ID0gc2V0dXBXZWJHTChjYW52YXMpO1xuICAgIGZsZXhnbC5jdHggPSBjdHg7XG4gICAgZmxleGdsLmNhbnZhcyA9IGNhbnZhcztcbiAgICBmbGV4Z2wucmVzb3VyY2VzID0gcmVzb3VyY2VzO1xuICAgIGN0eC5fZGljdCA9IG9wdGlvbnMuZW52IHx8IG9wdGlvbnMuZGljdCB8fCBvcHRpb25zLmRpY3Rpb25hcnkgfHwge307XG5cbiAgICB2YXIgcmVzb3VyY2VzID0gbmV3IFJlc291cmNlKGN0eCksXG4gICAgICAgIGZyYW1lYnVmZmVycyA9IG5ldyBGcmFtZWJ1ZmZlcihjdHgpLFxuICAgICAgICBwcm9ncmFtID0gbmV3IFByb2dyYW0oY3R4LCByZXNvdXJjZXMpLFxuICAgICAgICByZWFsUHJvZ3JhbSA9IG51bGw7XG5cblxuICAgIHZhciBibGVuZEV4dCA9IGN0eC5nZXRFeHRlbnNpb24oXCJFWFRfYmxlbmRfbWlubWF4XCIpO1xuICAgIGlmIChibGVuZEV4dCkge1xuICAgICAgICBjdHguTUFYX0VYVCA9IGJsZW5kRXh0Lk1BWF9FWFQ7XG4gICAgICAgIGN0eC5NSU5fRVhUID0gYmxlbmRFeHQuTUlOX0VYVDtcbiAgICB9XG4gICAgY3R4LmV4dCA9IGN0eC5nZXRFeHRlbnNpb24oXCJBTkdMRV9pbnN0YW5jZWRfYXJyYXlzXCIpO1xuICAgIGVuYWJsZUV4dGVuc2lvbihbXG4gICAgICAgIFwiT0VTX3RleHR1cmVfZmxvYXRcIixcbiAgICAgICAgXCJPRVNfdGV4dHVyZV9mbG9hdF9saW5lYXJcIixcbiAgICAgICAgLy8gXCJPRVNfdGV4dHVyZV9oYWxmX2Zsb2F0XCIsXG4gICAgICAgIC8vIFwiT0VTX3RleHR1cmVfaGFsZl9mbG9hdF9saW5lYXJcIlxuICAgIF0pO1xuICAgIGlmIChjb250YWluZXIpXG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChjYW52YXMpO1xuXG5cbiAgICBmdW5jdGlvbiBzZXR1cFdlYkdMKGNhbnZhcykge1xuICAgICAgICB2YXIgbmFtZXMgPSBbXCJ3ZWJnbFwiLCBcImV4cGVyaW1lbnRhbC13ZWJnbFwiXTtcbiAgICAgICAgdmFyIGdsID0gbnVsbDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBnbCA9IGNhbnZhcy5nZXRDb250ZXh0KG5hbWVzW2ldKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICBpZiAoZ2wpIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbmFibGVFeHRlbnNpb24oZXh0ZW5zaW9ucykge1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZXh0ZW5zaW9ucykpIGV4dGVuc2lvbnMgPSBbZXh0ZW5zaW9uc107XG4gICAgICAgIGV4dGVuc2lvbnMuZm9yRWFjaChmdW5jdGlvbihleHRlbnNpb24pIHtcbiAgICAgICAgICAgIHZhciBleHRQcm9wcyA9IGN0eC5nZXRFeHRlbnNpb24oZXh0ZW5zaW9uKTtcbiAgICAgICAgICAgIGlmIChleHRQcm9wcyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKGV4dFByb3BzKS5mb3JFYWNoKGZ1bmN0aW9uKGVwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXh0Lmhhc093blByb3BlcnR5KGVwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmV4dFtlcF0gPSBleHRQcm9wc1tlcF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGZsZXhnbC5lbmFibGVFeHRlbnNpb24gPSBlbmFibGVFeHRlbnNpb247XG5cbiAgICAvKipcbiAgICAgKiBBbGxvY2F0ZSBBdHRyaWJ1dGVzIGluIHZlcnRleCBidWZmZXIgYXJyYXkgc3RvcmVkIGluIEdQVSBtZW1vcnlcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IG5hbWUgYXR0cmlidXRlIG5hbWVcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IHR5cGUgYXR0cmlidXRlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gZGF0YSBkYXRhIHZhbHVlc1xuICAgICAqIEByZXR1cm4ge09iamVjdH0gICAgICBGTGV4R0wgb2JqZWN0XG4gICAgICovXG4gICAgZmxleGdsLmF0dHJpYnV0ZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIGRhdGEpIHtcbiAgICAgICAgcmVzb3VyY2VzLmFsbG9jYXRlKFwiYXR0cmlidXRlXCIsIG5hbWUsIHR5cGUsIGRhdGEpO1xuICAgICAgICBpZiAoIWZsZXhnbC5hdHRyaWJ1dGUuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmbGV4Z2wuYXR0cmlidXRlLCBuYW1lLCB7IC8vYWZ0ZXIgYWxsb2NhdGluZywgZmxleGdsIGdldHMgbmV3IGtleSBhdHRyaWJ1dGUsIGhlbHBpbmcgZWFzaWx5IGNoYW5nZSBhdHRyaWJ1dGUgZGF0YS5cbiAgICAgICAgICAgICAgICBnZXQoKXtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc291cmNlcy5hdHRyaWJ1dGVbbmFtZV07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZXQoZGF0YSl7XG4gICAgICAgICAgICAgICAgICAgIHJlc291cmNlcy5hdHRyaWJ1dGVbbmFtZV0ubG9hZChkYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmxleGdsO1xuICAgIH07XG4gICAgLy8gZmxleGdsLmJ1ZmZlciA9IGZsZXhnbC5hdHRyaWJ1dGU7IC8vYWxpYXNcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIFVuaWZvcm0gdmFyaWFibGUgZm9yIFdlYkdMIHNoYWRlciBwcm9ncmFtc1xuICAgICAqIEBwYXJhbSAge1N0cmluZ30gbmFtZSBhdHRyaWJ1dGUgbmFtZVxuICAgICAqIEBwYXJhbSAge1N0cmluZ30gdHlwZSB1bmlmb3JtIHZhcmlhYmxlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gZGF0YSBkYXRhIHZhbHVlc1xuICAgICAqIEByZXR1cm4ge09iamVjdH0gICAgICBGTGV4R0wgb2JqZWN0XG4gICAgICovXG4gICAgZmxleGdsLnVuaWZvcm0gPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBkYXRhKSB7XG4gICAgICAgIHJlc291cmNlcy5hbGxvY2F0ZShcInVuaWZvcm1cIiwgbmFtZSwgdHlwZSwgZGF0YSk7XG4gICAgICAgIGlmICghZmxleGdsLnVuaWZvcm0uaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmbGV4Z2wudW5pZm9ybSwgbmFtZSwge1xuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvdXJjZXMudW5pZm9ybVtuYW1lXTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICByZXNvdXJjZXMudW5pZm9ybVtuYW1lXS5sb2FkKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY3R4LmlzUHJvZ3JhbShyZWFsUHJvZ3JhbSkpICAgICAgICAgICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZXMudW5pZm9ybVtuYW1lXS5saW5rKHJlYWxQcm9ncmFtKTsgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZsZXhnbDtcbiAgICB9O1xuXG4gICAgZmxleGdsLnVuaWZvcm0uc2VyaWFsaXplID0gZnVuY3Rpb24oYW9hKSB7XG4gICAgICAgIHZhciBzYSA9IFtdO1xuICAgICAgICBhb2EuZm9yRWFjaChmdW5jdGlvbihhKSB7XG4gICAgICAgICAgICBzYSA9IHNhLmNvbmNhdChhKTtcbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIHNhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIFVuaWZvcm0gdmFyaWFibGUgZm9yIFdlYkdMIHNoYWRlciBwcm9ncmFtc1xuICAgICAqIEBwYXJhbSAge1N0cmluZ30gbmFtZSBhdHRyaWJ1dGUgbmFtZVxuICAgICAqIEBwYXJhbSAge1N0cmluZ30gdHlwZSB0ZXh0dXJlIHR5cGU6IHVuc2lnbmVkX2J5dGUgb3IgZmxvYXQsIC4uLlxuICAgICAqIEBwYXJhbSAge0FycmF5fSBkYXRhIGRhdGEgdmFsdWVzXG4gICAgICogQHBhcmFtICB7QXJyYXl9IGRpbSBbd2lkdGgsIGhlaWdodF1cbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IFtjaGFubmVsPSdhbHBoYSddIFdlYkdMIGZvcm1hdHMgKHJnYmEsIGFscGhhKVxuICAgICAqIEBwYXJhbSAge09iamVjdH0gW3NhbXBsZXI9bnVsbF0gRkxleEdMIFVuaWZvcm0gT2JqZWN0XG4gICAgICogQHJldHVybiB7T2JqZWN0fSAgICAgIEZMZXhHTCBvYmplY3RcbiAgICAgKi9cbiAgICBmbGV4Z2wudGV4dHVyZSA9IGZ1bmN0aW9uKG5hbWUsIHR5cGUsIGRhdGEsIGRpbSwgY2hhbm5lbCwgc2FtcGxlcikge1xuICAgICAgICByZXNvdXJjZXMuYWxsb2NhdGUoXCJ0ZXh0dXJlXCIsIG5hbWUsIHR5cGUsIGRpbSwgY2hhbm5lbCwgZGF0YSwgc2FtcGxlcik7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmbGV4Z2wudGV4dHVyZSwgbmFtZSwge1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb3VyY2VzLnRleHR1cmVbbmFtZV07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICAgICAgcmVzb3VyY2VzLnRleHR1cmVbbmFtZV0ubG9hZChkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBmbGV4Z2w7XG4gICAgfVxuXG4gICAgZmxleGdsLnRleHR1cmUudXBkYXRlID0gZnVuY3Rpb24obmFtZSwgZGF0YSwgb2Zmc2V0LCBkaW0pIHtcbiAgICAgICAgcmVzb3VyY2VzLnRleHR1cmVbbmFtZV0udXBkYXRlKGRhdGEsIG9mZnNldCwgZGltKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBVbmlmb3JtIHZhcmlhYmxlIGZvciBXZWJHTCBzaGFkZXIgcHJvZ3JhbXNcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IG5hbWUgYXR0cmlidXRlIG5hbWVcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IFt0eXBlXSBWYXJ5aW5nIHZhcmlhYmxlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtOdW1iZXJ9IFtzaXplPTFdIGRhdGEgYXJyYXlcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9ICAgICAgRkxleEdMIG9iamVjdFxuICAgICAqL1xuICAgIGZsZXhnbC52YXJ5aW5nID0gZnVuY3Rpb24obmFtZSwgdHlwZSwgc2l6ZSkge1xuICAgICAgICByZXNvdXJjZXMuYWxsb2NhdGUoXCJ2YXJ5aW5nXCIsIG5hbWUsIHR5cGUsIHNpemUpO1xuICAgICAgICByZXR1cm4gZmxleGdsO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBVbmlmb3JtIHZhcmlhYmxlIGZvciBXZWJHTCBzaGFkZXIgcHJvZ3JhbXNcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IG5hbWUgYXR0cmlidXRlIG5hbWVcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IHR5cGUgYXR0cmlidXRlIHR5cGU6IGZsb2F0LCB2ZWMyLCAuLi5cbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gZGltIFt3aWR0aCwgaGVpZ2h0XVxuICAgICAqIEBwYXJhbSAge09iamVjdH0gW3RleHR1cmU9bnVsbF0gRkxleEdMIFRleHR1cmUgT2JqZWN0XG4gICAgICogQHJldHVybiB7T2JqZWN0fSAgICAgIEZMZXhHTCBvYmplY3RcbiAgICAgKi9cbiAgICBmbGV4Z2wuZnJhbWVidWZmZXIgPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBkaW0sIHRleHR1cmUpIHtcbiAgICAgICAgdmFyIHRleHR1cmUgPSB0ZXh0dXJlIHx8IHJlc291cmNlcy5hbGxvY2F0ZSgndGV4dHVyZScsIG5hbWUsIHR5cGUsIGRpbSwgJ3JnYmEnLCBudWxsKTtcbiAgICAgICAgZnJhbWVidWZmZXJzLmNyZWF0ZShuYW1lLCB0eXBlLCBkaW0sIHRleHR1cmUpO1xuXG4gICAgICAgIGlmICghZmxleGdsLmZyYW1lYnVmZmVyLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZmxleGdsLmZyYW1lYnVmZmVyLCBuYW1lLCB7XG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZyYW1lYnVmZmVyc1tuYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmxleGdsO1xuICAgIH1cblxuICAgIGZsZXhnbC5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkID0gZnVuY3Rpb24obmFtZSwgcHJvZ3JhbSkge1xuICAgICAgICBmcmFtZWJ1ZmZlcnNbbmFtZV0uZW5hYmxlUmVhZChwcm9ncmFtKTtcbiAgICB9XG5cbiAgICBmbGV4Z2wuYmluZEZyYW1lYnVmZmVyID0gZnVuY3Rpb24oZmJOYW1lKSB7XG4gICAgICAgIGlmIChmYk5hbWUgPT09IG51bGwpXG4gICAgICAgICAgICBjdHguYmluZEZyYW1lYnVmZmVyKGN0eC5GUkFNRUJVRkZFUiwgbnVsbCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGN0eC5iaW5kRnJhbWVidWZmZXIoY3R4LkZSQU1FQlVGRkVSLCBmcmFtZWJ1ZmZlcnNbZmJOYW1lXS5wdHIpO1xuICAgIH1cblxuICAgIGZsZXhnbC5zdWJyb3V0aW5lID0gZnVuY3Rpb24obmFtZSwgdHlwZSwgZm4pIHtcbiAgICAgICAgcmVzb3VyY2VzLmFsbG9jYXRlKFwic3Vicm91dGluZVwiLCBuYW1lLCB0eXBlLCBmbik7XG4gICAgICAgIHJldHVybiBmbGV4Z2w7XG4gICAgfVxuXG4gICAgZmxleGdsLnBhcmFtZXRlciA9IGZ1bmN0aW9uKGtleVZhbHVlUGFpcnMpIHtcbiAgICAgICAgT2JqZWN0LmtleXMoa2V5VmFsdWVQYWlycykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIGN0eC5fZGljdFtrZXldID0ga2V5VmFsdWVQYWlyc1trZXldO1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY3R4Ll9kaWN0W2tleV0pKSB7XG4gICAgICAgICAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdHguX2RpY3QsIGtleSwge1xuICAgICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGtleVZhbHVlUGFpcnNba2V5XVtpKytdO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKG5ld0FycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5fZGljdFtrZXldID0gbmV3QXJyYXk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZih0eXBlb2YoY3R4Ll9kaWN0W2tleV0pID09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpY3RLZXlzID0gT2JqZWN0LmtleXMoY3R4Ll9kaWN0W2tleV0pO1xuICAgICAgICAgICAgICAgIGZ4Z2wudW5pZm9ybSgnZGljdCcra2V5LCAnZmxvYXQnLCBkaWN0S2V5cy5tYXAoZD0+Y3R4Ll9kaWN0W2tleV1bZF0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIGZsZXhnbDtcbiAgICB9XG5cbiAgICBmbGV4Z2wuZGljdGlvbmFyeSA9IGZsZXhnbC5wYXJhbWV0ZXI7XG4gICAgZmxleGdsLnNoYWRlciA9IHByb2dyYW0uc2hhZGVyO1xuXG5cbiAgICBmbGV4Z2wuYXBwID0gZnVuY3Rpb24obmFtZSwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJncyl7XG4gICAgICAgICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG4gICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5yZW5kZXIuY2FsbChmbGV4Z2wsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZmxleGdsLmRpbWVuc2lvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gW2NhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodF07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZsZXhnbDtcbn1cblxuXG5cbiAgICAgICAgLy8gaWYobnVtID09PSAwKXtcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCAxMDI0LCAxKTtcbiAgICAgICAgLy8gICAgIHJlYWxQcm9ncmFtID0gcHJvZ3JhbS51c2UobmFtZSwgb3B0aW9ucy52ZXJ0ZXhfc2hhZGVyX3NvdXJjZSwgb3B0aW9ucy5mcmFnbWVudF9zaGFkZXJfc291cmNlKTtcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKCdmX3N1bV90ZXh0dXJlJyk7XG5cbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3Bvc2l0aW9uJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV90ZXhjb29yZCddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy50ZXh0dXJlWyd1X3RleHR1cmUnXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIC8vIGVsc2UgaWYobnVtID09PSAxKXtcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCBjdHguY2FudmFzLndpZHRoLCBjdHguY2FudmFzLmhlaWdodCk7XG4gICAgICAgIC8vICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG4gICAgICAgICAgICBcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKG51bGwpO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5hdHRyaWJ1dGVbJ2FfcG9zaXRpb24nXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3RleGNvb3JkJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmZyYW1lYnVmZmVyLmVuYWJsZVJlYWQoJ2Zfc3VtX3RleHR1cmUnLCByZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyBlbHNlIGlmKG51bSA9PT0gMil7XG4gICAgICAgIC8vICAgICB0aGlzLmJpbmRGcmFtZWJ1ZmZlcihudWxsKTtcblxuICAgICAgICAvLyAgICAgY3R4LnZpZXdwb3J0KDAsIDAsIDEwMjQsIDEpO1xuICAgICAgICAvLyAgICAgdGhpcy5iaW5kRnJhbWVidWZmZXIoJ2ZfbWVtX3RleHR1cmVfMScpO1xuICAgICAgICAvLyAgICAgcmVhbFByb2dyYW0gPSBwcm9ncmFtLnVzZShuYW1lLCBvcHRpb25zLnZlcnRleF9zaGFkZXJfc291cmNlLCBvcHRpb25zLmZyYWdtZW50X3NoYWRlcl9zb3VyY2UpO1xuXG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV9wb3NpdGlvbiddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5hdHRyaWJ1dGVbJ2FfdGV4Y29vcmQnXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuZnJhbWVidWZmZXIuZW5hYmxlUmVhZCgnZl9tZW1fdGV4dHVyZV8wJywgcmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkKCdmX3N1bV90ZXh0dXJlJywgcmVhbFByb2dyYW0pO1xuICAgICAgICAvLyB9XG5cbiAgICAgICAgLy8gZWxzZSBpZihudW0gPT09IDMpe1xuICAgICAgICAvLyAgICAgdGhpcy5iaW5kRnJhbWVidWZmZXIobnVsbCk7XG5cbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCAxMDI0LCAxKTtcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKCdmX21lbV90ZXh0dXJlXzAnKTtcbiAgICAgICAgLy8gICAgIHJlYWxQcm9ncmFtID0gcHJvZ3JhbS51c2UobmFtZSwgb3B0aW9ucy52ZXJ0ZXhfc2hhZGVyX3NvdXJjZSwgb3B0aW9ucy5mcmFnbWVudF9zaGFkZXJfc291cmNlKTtcblxuICAgICAgICAvLyAgICAgLy8gdGhpcy5hdHRyaWJ1dGVbJ2FfcG9zaXRpb24nXS5saW5rKHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3RleGNvb3JkJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmZyYW1lYnVmZmVyLmVuYWJsZVJlYWQoJ2ZfbWVtX3RleHR1cmVfMScsIHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gICAgIC8vIHRoaXMuZnJhbWVidWZmZXIuZW5hYmxlUmVhZCgnZl9zdW1fdGV4dHVyZScsIHJlYWxQcm9ncmFtKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIC8vIGVsc2UgaWYobnVtID09PSA0KXtcbiAgICAgICAgLy8gICAgIHRoaXMuYmluZEZyYW1lYnVmZmVyKG51bGwpOyBcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCBjdHguY2FudmFzLndpZHRoLCBjdHguY2FudmFzLmhlaWdodCk7XG4gICAgICAgIC8vICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG5cbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3Bvc2l0aW9uJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV90ZXhjb29yZCddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkKCdmX21lbV90ZXh0dXJlXzEnLCByZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyBlbHNlIGlmKG51bSA9PT0gNSl7XG4gICAgICAgIC8vICAgICB0aGlzLmJpbmRGcmFtZWJ1ZmZlcihudWxsKTtcbiAgICAgICAgLy8gICAgIGN0eC52aWV3cG9ydCgwLCAwLCBjdHguY2FudmFzLndpZHRoLCBjdHguY2FudmFzLmhlaWdodCk7XG4gICAgICAgIC8vICAgICByZWFsUHJvZ3JhbSA9IHByb2dyYW0udXNlKG5hbWUsIG9wdGlvbnMudmVydGV4X3NoYWRlcl9zb3VyY2UsIG9wdGlvbnMuZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSk7XG5cbiAgICAgICAgLy8gICAgIC8vIHRoaXMuYXR0cmlidXRlWydhX3Bvc2l0aW9uJ10ubGluayhyZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vICAgICAvLyB0aGlzLmF0dHJpYnV0ZVsnYV90ZXhjb29yZCddLmxpbmsocmVhbFByb2dyYW0pO1xuICAgICAgICAvLyAgICAgLy8gdGhpcy5mcmFtZWJ1ZmZlci5lbmFibGVSZWFkKCdmX21lbV90ZXh0dXJlXzAnLCByZWFsUHJvZ3JhbSk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyB0aGlzLnVuaWZvcm1bJ3VfdGV4dHVyZSddLmxpbmsocmVhbFByb2dyYW0pOyAgICBcbiAgICAgICAgLy8gdmFyIGRyYXcgPSBvcHRpb25zLnJlbmRlciB8fCBvcHRpb25zLmRyYXc7XG5cbiAgICAgICAgLy8gcmV0dXJuIGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgLy8gICAgIC8vIHZhciBnbCA9IGZsZXhnbC5wcm9ncmFtKG5hbWUpO1xuICAgICAgICAvLyAgICAgcmV0dXJuIGRyYXcuY2FsbChjdHgsIGFyZ3MpO1xuICAgICAgICAvLyB9XG5cbiAgICAgICAgLy8gY3R4LmRyYXdBcnJheXMoY3R4LkxJTkVTLCAwLCAyKTsiLCJpbXBvcnQgRmxleEdMIGZyb20gJy4vZmxleGdsJztcblxuKGZ1bmN0aW9uIG1ha2VHbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHdpbmRvdy5GbGV4R0wgPSBGbGV4R0w7XG4gIH1cbn0pKCk7XG4iLCJpbXBvcnQgVGV4dHVyZSBmcm9tICcuL3RleHR1cmUnO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBGcmFtZWJ1ZmZlcihnbENvbnRleHQpIHtcblxuICAgIHZhciBmcmFtZWJ1ZmZlciA9ICh0aGlzIGluc3RhbmNlb2YgRnJhbWVidWZmZXIpID8gdGhpcyA6IHt9LFxuICAgICAgICBjdHggPSBnbENvbnRleHQ7XG5cbiAgICBmcmFtZWJ1ZmZlci5jcmVhdGUgPSBmdW5jdGlvbihuYW1lLCB0eXBlLCBkaW0sIHRleHR1cmUpIHtcblxuICAgICAgICBmcmFtZWJ1ZmZlcltuYW1lXSA9IHtcbiAgICAgICAgICAgIHB0cjogY3R4LmNyZWF0ZUZyYW1lYnVmZmVyKCksXG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgdHlwZTogdHlwZSB8fCBcImZsb2F0XCIsXG4gICAgICAgICAgICB3aWR0aDogZGltWzBdIHx8IDEwMjQsXG4gICAgICAgICAgICBoZWlnaHQ6IGRpbVsxXSB8fCAxMDI0LFxuICAgICAgICAgICAgdGV4dHVyZTogdGV4dHVyZSB8fCBudWxsLFxuICAgICAgICAgICAgLy8gcmVuZGVyYnVmZmVyOiBjdHguY3JlYXRlUmVuZGVyYnVmZmVyKCksXG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiAoZnJhbWVidWZmZXJbbmFtZV0udGV4dHVyZSA9PT0gbnVsbCkge1xuICAgICAgICAvLyAgICAgdmFyIGJ1ZiA9ICh0eXBlID09ICdmbG9hdCcpID9cbiAgICAgICAgLy8gICAgICAgICBuZXcgRmxvYXQzMkFycmF5KGRpbVswXSAqIGRpbVsxXSAqIDQpIDpcbiAgICAgICAgLy8gICAgICAgICBuZXcgVWludDhBcnJheShkaW1bMF0gKiBkaW1bMV0gKiA0KTtcbiAgICAgICAgLy8gICAgIGZyYW1lYnVmZmVyW25hbWVdLnRleHR1cmUgPSBUZXh0dXJlKGN0eCkuY3JlYXRlKG5hbWUsIHR5cGUsIGRpbSwgXCJyZ2JhXCIsIGJ1Zik7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyB2YXIgcmVuZGVyYnVmZmVyID0gZnJhbWVidWZmZXJbbmFtZV0ucmVuZGVyYnVmZmVyO1xuICAgICAgICBjdHguYmluZEZyYW1lYnVmZmVyKGN0eC5GUkFNRUJVRkZFUiwgZnJhbWVidWZmZXJbbmFtZV0ucHRyKTtcbiAgICAgICAgLy8gY3R4LmJpbmRSZW5kZXJidWZmZXIoY3R4LlJFTkRFUkJVRkZFUiwgcmVuZGVyYnVmZmVyKTtcbiAgICAgICAgLy8gY3R4LnJlbmRlcmJ1ZmZlclN0b3JhZ2UoXG4gICAgICAgIC8vICAgICBjdHguUkVOREVSQlVGRkVSLFxuICAgICAgICAvLyAgICAgY3R4LkRFUFRIX0NPTVBPTkVOVDE2LFxuICAgICAgICAvLyAgICAgZnJhbWVidWZmZXJbbmFtZV0ud2lkdGgsXG4gICAgICAgIC8vICAgICBmcmFtZWJ1ZmZlcltuYW1lXS5oZWlnaHRcbiAgICAgICAgLy8gKTtcbiAgICAgICAgY3R4LmZyYW1lYnVmZmVyVGV4dHVyZTJEKFxuICAgICAgICAgICAgY3R4LkZSQU1FQlVGRkVSLFxuICAgICAgICAgICAgY3R4LkNPTE9SX0FUVEFDSE1FTlQwLFxuICAgICAgICAgICAgY3R4LlRFWFRVUkVfMkQsXG4gICAgICAgICAgICBmcmFtZWJ1ZmZlcltuYW1lXS50ZXh0dXJlLnB0cixcbiAgICAgICAgICAgIDBcbiAgICAgICAgKTtcbiAgICAgICAgLy8gY3R4LmZyYW1lYnVmZmVyUmVuZGVyYnVmZmVyKFxuICAgICAgICAvLyAgICAgY3R4LkZSQU1FQlVGRkVSLFxuICAgICAgICAvLyAgICAgY3R4LkRFUFRIX0FUVEFDSE1FTlQsXG4gICAgICAgIC8vICAgICBjdHguUkVOREVSQlVGRkVSLFxuICAgICAgICAvLyAgICAgcmVuZGVyYnVmZmVyXG4gICAgICAgIC8vICk7XG4gICAgICAgIC8vIGN0eC5iaW5kUmVuZGVyYnVmZmVyKGN0eC5SRU5ERVJCVUZGRVIsIG51bGwpO1xuICAgICAgICBjdHguYmluZEZyYW1lYnVmZmVyKGN0eC5GUkFNRUJVRkZFUiwgbnVsbCk7XG5cbiAgICAgICAgZnJhbWVidWZmZXJbbmFtZV0uZW5hYmxlUmVhZCA9IGZ1bmN0aW9uKHByb2dyYW0pIHtcbiAgICAgICAgICAgIGN0eC5hY3RpdmVUZXh0dXJlKGN0eC5URVhUVVJFMCArIHRoaXMudGV4dHVyZS5pbmRleCk7XG4gICAgICAgICAgICBjdHguYmluZFRleHR1cmUoY3R4LlRFWFRVUkVfMkQsIHRoaXMudGV4dHVyZS5wdHIpO1xuICAgICAgICAgICAgdGhpcy50ZXh0dXJlLmxvY2F0aW9uID0gY3R4LmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCB0aGlzLnRleHR1cmUubmFtZSk7XG4gICAgICAgICAgICBjdHgudW5pZm9ybTFpKHRoaXMudGV4dHVyZS5sb2NhdGlvbiwgdGhpcy50ZXh0dXJlLmluZGV4KTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBmcmFtZWJ1ZmZlcltuYW1lXS5lbmFibGVSZWFkID0gZnVuY3Rpb24ocHJvZ3JhbSkge1xuICAgICAgICAvLyAgICAgdGhpcy50ZXh0dXJlLmxpbmsocHJvZ3JhbSk7XG4gICAgICAgIC8vIH07XG5cbiAgICAgICAgZnJhbWVidWZmZXJbbmFtZV0uZGVsZXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjdHguYmluZFJlbmRlcmJ1ZmZlcihnbC5SRU5ERVJCVUZGRVIsIG51bGwpO1xuICAgICAgICAgICAgY3R4LmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgbnVsbCk7XG4gICAgICAgICAgICBjdHguZGVsZXRlUmVuZGVyYnVmZmVyKHRoaXMucmVuZGVyYnVmZmVyKTtcbiAgICAgICAgICAgIGN0eC5kZWxldGVUZXh0dXJlKHRoaXMudGV4dHVyZS5wdHIpXG4gICAgICAgICAgICBjdHguZGVsZXRlRnJhbWVidWZmZXIodGhpcy5wdHIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBmcmFtZWJ1ZmZlcltuYW1lXTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnJhbWVidWZmZXI7XG59XG4iLCJpbXBvcnQgU2hhZGVyIGZyb20gJy4vc2hhZGVyJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gUHJvZ3JhbShnbENvbnRleHQsIHJlc291cmNlcykge1xuXG4gICAgdmFyIHByb2dyYW0gPSB7fSxcbiAgICAgICAgY3R4ID0gZ2xDb250ZXh0LFxuICAgICAgICBrZXJuZWxzID0ge30sXG4gICAgICAgIHNoYWRlciA9IG5ldyBTaGFkZXIoZ2xDb250ZXh0KTtcblxuICAgIHByb2dyYW0uY3JlYXRlID0gZnVuY3Rpb24obmFtZSwgdnMsIGZzKSB7XG4gICAgICAgIHZhciBuYW1lID0gbmFtZSB8fCBcImRlZmF1bHRcIixcbiAgICAgICAgICAgIHZzID0gdnMgfHwgXCJkZWZhdWx0XCIsXG4gICAgICAgICAgICBmcyA9IGZzIHx8IFwiZGVmYXVsdFwiLFxuICAgICAgICAgICAgZGVwcyA9IFtdO1xuXG4gICAgICAgIGlmIChrZXJuZWxzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGV0ZShuYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGtlcm5lbHNbbmFtZV0gPSBjdHguY3JlYXRlUHJvZ3JhbSgpO1xuICAgICAgICBrZXJuZWxzW25hbWVdLnZzID0gdnM7XG4gICAgICAgIGtlcm5lbHNbbmFtZV0uZnMgPSBmcztcblxuICAgICAgICBjdHguYXR0YWNoU2hhZGVyKGtlcm5lbHNbbmFtZV0sIGtlcm5lbHNbbmFtZV0udnMpO1xuICAgICAgICBjdHguYXR0YWNoU2hhZGVyKGtlcm5lbHNbbmFtZV0sIGtlcm5lbHNbbmFtZV0uZnMpO1xuICAgICAgICBjdHgubGlua1Byb2dyYW0oa2VybmVsc1tuYW1lXSk7XG4gICAgICAgIHZhciBsaW5rZWQgPSBjdHguZ2V0UHJvZ3JhbVBhcmFtZXRlcihrZXJuZWxzW25hbWVdLCBjdHguTElOS19TVEFUVVMpO1xuICAgICAgICBpZiAoIWxpbmtlZCkge1xuICAgICAgICAgICAgdmFyIGxhc3RFcnJvciA9IGN0eC5nZXRQcm9ncmFtSW5mb0xvZyhrZXJuZWxzW25hbWVdKTtcbiAgICAgICAgICAgIHRocm93IChcIkVycm9yIGluIHByb2dyYW0gbGlua2luZzpcIiArIGxhc3RFcnJvcik7XG4gICAgICAgICAgICBjdHguZGVsZXRlUHJvZ3JhbShrZXJuZWxzW25hbWVdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRlcHMgPSBkZXBzLmNvbmNhdChrZXJuZWxzW25hbWVdLnZzLmRlcHMpO1xuICAgICAgICBkZXBzID0gZGVwcy5jb25jYXQoa2VybmVsc1tuYW1lXS5mcy5kZXBzKTtcbiAgICAgICAga2VybmVsc1tuYW1lXS5kZXBzID0gZGVwcztcblxuICAgIH1cblxuICAgIHByb2dyYW0udXNlID0gZnVuY3Rpb24obmFtZSwgdmVydGV4X3NoYWRlcl9zb3VyY2UsIGZyYWdtZW50X3NoYWRlcl9zb3VyY2UpIHtcbiAgICAgICAgaWYgKGtlcm5lbHMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIGN0eC51c2VQcm9ncmFtKGtlcm5lbHNbbmFtZV0pO1xuICAgICAgICAgICAgcmVzb3VyY2VzLmxpbmsoa2VybmVsc1tuYW1lXSwga2VybmVsc1tuYW1lXS5kZXBzKTtcbiAgICAgICAgICAgIHJldHVybiBrZXJuZWxzW25hbWVdO1xuICAgICAgICB9IFxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNoYWRlci5jcmVhdGUobmFtZSwgdmVydGV4X3NoYWRlcl9zb3VyY2UsIGZyYWdtZW50X3NoYWRlcl9zb3VyY2UpO1xuICAgICAgICAgICAgdGhpcy5jcmVhdGUobmFtZSwgc2hhZGVyW25hbWVdLnZzLCBzaGFkZXJbbmFtZV0uZnMpO1xuICAgICAgICAgICAgY3R4LnVzZVByb2dyYW0oa2VybmVsc1tuYW1lXSk7XG4gICAgICAgICAgICByZXNvdXJjZXMubGluayhrZXJuZWxzW25hbWVdLCBrZXJuZWxzW25hbWVdLmRlcHMpO1xuICAgICAgICAgICAgcmV0dXJuIGtlcm5lbHNbbmFtZV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm9ncmFtLmRlbGV0ZSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgaWYgKGtlcm5lbHMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgICAgIGN0eC5kZXRhY2hTaGFkZXIoa2VybmVsc1tuYW1lXSwga2VybmVsc1tuYW1lXS52cyk7XG4gICAgICAgICAgICBjdHguZGV0YWNoU2hhZGVyKGtlcm5lbHNbbmFtZV0sIGtlcm5lbHNbbmFtZV0uZnMpO1xuICAgICAgICAgICAgY3R4LmRlbGV0ZVByb2dyYW0oa2VybmVsc1tuYW1lXSk7XG4gICAgICAgICAgICBkZWxldGUga2VybmVsc1tuYW1lXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwcm9ncmFtO1xufVxuIiwiZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gU2hhZGVyKGdsQ29udGV4dCkge1xuICAgIFxuICAgIHZhciBzaGFkZXIgPSAodGhpcyBpbnN0YW5jZW9mIFNoYWRlcikgPyB0aGlzIDoge30sXG4gICAgICAgIGN0eCA9IGdsQ29udGV4dDtcbiAgICAgICAgLy8gcmVzb3VyY2UgPSBnbFJlc291cmNlLFxuICAgICAgICAvLyBwYXJhbWV0ZXJzID0gY3R4Ll9kaWN0IHx8IHt9O1xuXG4gICAgc2hhZGVyLmNyZWF0ZSA9IGZ1bmN0aW9uKG5hbWUsIHZlcnRleF9zaGFkZXJfc291cmNlLCBmcmFnbWVudF9zaGFkZXJfc291cmNlKXtcbiAgICAgICAgc2hhZGVyW25hbWVdID0ge1xuICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgIHZlcnRleF9zaGFkZXJfc291cmNlOiB2ZXJ0ZXhfc2hhZGVyX3NvdXJjZSwgXG4gICAgICAgICAgICBmcmFnbWVudF9zaGFkZXJfc291cmNlOiBmcmFnbWVudF9zaGFkZXJfc291cmNlLCBcbiAgICAgICAgICAgIHZzOiBjcmVhdGVTaGFkZXIoY3R4LCBjdHguVkVSVEVYX1NIQURFUiwgdmVydGV4X3NoYWRlcl9zb3VyY2UpLFxuICAgICAgICAgICAgZnM6IGNyZWF0ZVNoYWRlcihjdHgsIGN0eC5GUkFHTUVOVF9TSEFERVIsIGZyYWdtZW50X3NoYWRlcl9zb3VyY2UpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBzaGFkZXJbbmFtZV0udnMgPSBjcmVhdGVTaGFkZXIoY3R4LCBjdHguVkVSVEVYX1NIQURFUiwgdmVydGV4X3NoYWRlcl9zb3VyY2UpO1xuICAgICAgICAvLyBzaGFkZXJbbmFtZV0uZnMgPSBjcmVhdGVTaGFkZXIoY3R4LCBjdHguRlJBR01FTlRfU0hBREVSLCBmcmFnbWVudF9zaGFkZXJfc291cmNlKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coc2hhZGVyW25hbWVdLnZzKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coc2hhZGVyW25hbWVdLmZzKTtcblxuICAgICAgICBzaGFkZXJbbmFtZV0udnMuZGVwcyA9IFtdO1xuICAgICAgICBhZGREZXBzKHZlcnRleF9zaGFkZXJfc291cmNlLCBzaGFkZXJbbmFtZV0udnMuZGVwcyk7XG4gICAgICAgIHNoYWRlcltuYW1lXS5mcy5kZXBzID0gW107XG4gICAgICAgIGFkZERlcHMoZnJhZ21lbnRfc2hhZGVyX3NvdXJjZSwgc2hhZGVyW25hbWVdLnZzLmRlcHMpO1xuXG4gICAgICAgIGZ1bmN0aW9uIGNyZWF0ZVNoYWRlcihnbCwgdHlwZSwgc291cmNlKSB7XG4gICAgICAgICAgICB2YXIgc2hhZGVyID0gZ2wuY3JlYXRlU2hhZGVyKHR5cGUpO1xuICAgICAgICAgICAgZ2wuc2hhZGVyU291cmNlKHNoYWRlciwgc291cmNlKTtcbiAgICAgICAgICAgIGdsLmNvbXBpbGVTaGFkZXIoc2hhZGVyKTtcbiAgICAgICAgICAgIHZhciBzdWNjZXNzID0gZ2wuZ2V0U2hhZGVyUGFyYW1ldGVyKHNoYWRlciwgZ2wuQ09NUElMRV9TVEFUVVMpO1xuICAgICAgICAgICAgaWYgKHN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2hhZGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ05PIScpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coZ2wuZ2V0U2hhZGVySW5mb0xvZyhzaGFkZXIpKTtcbiAgICAgICAgICAgIGdsLmRlbGV0ZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gYWRkRGVwcyhzb3VyY2UsIGRlcHMpe1xuICAgICAgICAgICAgdmFyIHJlID0gL1xccyooYXR0cmlidXRlfHVuaWZvcm0pXFxzK1xcdytcXHMrKFxcdyspLzsgICAgICAgIFxuICAgICAgICAgICAgc291cmNlLnNwbGl0KCdcXG4nKS5mb3JFYWNoKGZ1bmN0aW9uKHYpe1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSByZS5leGVjKHYpO1xuICAgICAgICAgICAgICAgIGlmKHJlc3VsdCl7XG4gICAgICAgICAgICAgICAgICAgIGRlcHMucHVzaChyZXN1bHRbMl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHNoYWRlcjtcbn1cbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/example/example.html b/example/example.html index 881c506..bf1d233 100644 --- a/example/example.html +++ b/example/example.html @@ -1,6 +1,16 @@ - + Refresh + + + + + + + + + + diff --git a/example/simpledraw.js b/example/simpledraw.js index 0b34573..74b6151 100644 --- a/example/simpledraw.js +++ b/example/simpledraw.js @@ -1,33 +1,307 @@ var fxgl = new FlexGL({ container: document.body, - width: 800, - height: 600 }); -//Allocate and manage resources -fxgl.attribute('aVertexPos', 'vec2', [-1, 0, 1, 1, 0, -1.0]) - .uniform('uColor', 'vec4', [0.5, 0.0, 0.5, 1.0]); +var zeroArray = new Float32Array(1024*4); +for(var i = 0; i < zeroArray.length; i++){ + zeroArray[i] = 0.0; +} +fxgl.attribute('a_position', 'vec2', [-1.0, -1.0, 1.0, 1.0]) + .attribute('a_texcoord', 'float', [0.0, 1.0]) + .framebuffer('f_sum_texture', 'float', [1024, 1]) + .texture('f_mem_texture_0', 'float', zeroArray, [1024, 1], 'rgba') + .texture('f_mem_texture_1', 'float', zeroArray, [1024, 1], 'rgba') + .framebuffer('f_mem_texture_0', 'float', [1024, 1], fxgl.texture['f_mem_texture_0']) + .framebuffer('f_mem_texture_1', 'float', [1024, 1], fxgl.texture['f_mem_texture_1']); -//Create Program -var simpleDraw = fxgl.app('drawTriangle', { - vs: function() { - gl_Position = vec4(this.aVertexPos, 0, 1.0); - }, - fs: function() { - gl_FragColor = this.uColor; - }, - render: function(len) { - this.drawArrays(this.TRIANGLES, 0, len); +var sumData = fxgl.app('sumData', { + vertex_shader_source: ` + attribute vec2 a_position; + attribute float a_texcoord; + varying float v_texcoord; + + void main(){ + gl_Position = vec4(a_position, 0, 1.0); + v_texcoord = a_texcoord; + } + `, + fragment_shader_source: ` + precision highp float; + uniform sampler2D u_texture; + varying float v_texcoord; + + void main(){ + float sum = 0.0; + for(float i = 0.0; i < 1024.0; i++){ + sum += texture2D(u_texture, vec2(v_texcoord, (i+0.5)/1024.0)).a; + } + sum /= 1024.0; + gl_FragColor = vec4(sum, 0.0, 0.0, 1.0); + + } + `, + render: function(args){ + this.ctx.viewport(0, 0, 1024, 1); + this.bindFramebuffer('f_sum_texture'); + this.ctx.drawArrays(this.ctx.LINES, 0, 2); + } +}); + +var swingDataA = fxgl.app('swingDataA', { + vertex_shader_source: ` + attribute vec2 a_position; + attribute float a_texcoord; + varying float v_texcoord; + + void main(){ + gl_Position = vec4(a_position, 0, 1.0); + v_texcoord = a_texcoord; + } + `, + fragment_shader_source: ` + precision highp float; + uniform sampler2D f_sum_texture; + uniform sampler2D f_mem_texture_0; + varying float v_texcoord; + + void main(){ + float v0 = texture2D(f_sum_texture, vec2(v_texcoord, 0.5)).x; + float v1 = texture2D(f_mem_texture_0, vec2(v_texcoord, 0.5)).x; + gl_FragColor = vec4(v0+v1, 0.0, 0.0, 1.0); + } + `, + render: function(args){ + this.ctx.viewport(0, 0, 1024, 1); + this.bindFramebuffer('f_mem_texture_1'); + this.ctx.drawArrays(this.ctx.LINES, 0, 2); + } +}); + +var drawDataA = fxgl.app('drawDataA', { + vertex_shader_source: ` + attribute vec2 a_position; + attribute float a_texcoord; + varying float v_texcoord; + + void main(){ + gl_Position = vec4(a_position, 0, 1.0); + v_texcoord = a_texcoord; + } + `, + fragment_shader_source: ` + precision highp float; + uniform sampler2D f_mem_texture_1; + varying float v_texcoord; + + void main(){ + gl_FragColor = texture2D(f_mem_texture_1, vec2(v_texcoord, 0.5)); + } + `, + render: function(args){ + this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); + this.bindFramebuffer(null); + this.ctx.drawArrays(this.ctx.LINES, 0, 2); + } +}); + +var swingDataB = fxgl.app('swingDataB', { + vertex_shader_source: ` + attribute vec2 a_position; + attribute float a_texcoord; + varying float v_texcoord; + + void main(){ + gl_Position = vec4(a_position, 0, 1.0); + v_texcoord = a_texcoord; + } + `, + fragment_shader_source: ` + precision highp float; + uniform sampler2D f_sum_texture; + uniform sampler2D f_mem_texture_1; + varying float v_texcoord; + + void main(){ + float v0 = texture2D(f_sum_texture, vec2(v_texcoord, 0.5)).x; + float v1 = texture2D(f_mem_texture_1, vec2(v_texcoord, 0.5)).x; + gl_FragColor = vec4(v0+v1, 0.0, 0.0, 1.0); + } + `, + render: function(args){ + this.ctx.viewport(0, 0, 1024, 1); + this.bindFramebuffer('f_mem_texture_0'); + this.ctx.drawArrays(this.ctx.LINES, 0, 2); + } +}); + +var drawDataB = fxgl.app('drawDataB', { + vertex_shader_source: ` + attribute vec2 a_position; + attribute float a_texcoord; + varying float v_texcoord; + + void main(){ + gl_Position = vec4(a_position, 0, 1.0); + v_texcoord = a_texcoord; + } + `, + fragment_shader_source: ` + precision highp float; + uniform sampler2D f_mem_texture_0; + varying float v_texcoord; + + void main(){ + gl_FragColor = texture2D(f_mem_texture_0, vec2(v_texcoord, 0.5)); + } + `, + render: function(args){ + this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); + this.bindFramebuffer(null); + this.ctx.drawArrays(this.ctx.LINES, 0, 2); + } +}); + +var total_data = []; +for(var j = 0; j < 100; j++){ + var typedArray = new Float32Array(1024*1024); + for (var i = 0; i < typedArray.length; i++){ + typedArray[i] = Math.random()/100; + } + total_data.push(typedArray); +} + + +var pointer = -1; + +var updateButton = document.querySelector('.update'); +var updateClickStream = Rx.Observable.fromEvent(updateButton, 'click'); + +var requestStream = updateClickStream.startWith('startup click') + .map(function(){ + pointer++; + if(pointer > 99){ + alert('Out of Stack!'); + pointer--; + } + return pointer; + }); + +var responseStream = requestStream + .map(function(p){ + return total_data[pointer]; + }); + + + +var i = 0; +responseStream.subscribe(function(data_chunk){ + if(pointer === 0){ + fxgl.texture('u_texture', 'float', data_chunk, [1024, 1024]); + } + else{ + fxgl.texture['u_texture'] = data_chunk; + } + + sumData(); + if(i%2 === 0){ + swingDataA(); + drawDataA(); } + else{ + swingDataB(); + drawDataB(); + } + i++; }); -simpleDraw(3); // draw triangle -//change vertices and color -fxgl.attribute.aVertexPos = [ - -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, - -0.5, 0.5, 0.5, -0.5, 0.5, 0.5 -]; -fxgl.uniform.uColor = [0.0, 0.5, 0.5, 1.0] +// fxgl.attribute('aVertexPos', 'vec2', [-1, 0, 1, 1, 0, -1.0]) +// .uniform('uColor', 'vec4', [0.1, 1.0, 0.75, 1.0]); + +// //Create Program +// var simpleDraw = fxgl.app('drawTriangle', { +// vs: function() { +// gl_Position = vec4(this.aVertexPos, 0, 1.0); +// }, +// fs: function() { +// gl_FragColor = this.uColor; +// }, +// render: function(len) { +// this.drawArrays(this.TRIANGLES, 0, len); +// } +// }); + +// simpleDraw(3); // draw triangle + +// //change vertices and color +// fxgl.attribute.aVertexPos = [ +// -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, +// -0.5, 0.5, 0.5, -0.5, 0.5, 0.5 +// ]; +// fxgl.uniform.uColor = [1.0, 1.0, 0.5, 1.0] + +// simpleDraw(6); // draw rectangle + + + +//Create Program + + //gl_FragColor = vec4(0.0, texture2D(u_texture, vec2(v_texcoord, (88.0+0.5)/1024.0)).a, 0.0, 1.0); + // gl_FragColor = vec4(sum, 0.0, 0.0, 1.0); + + + + +// fxgl.app('drawLine1', { +// vsource: ` +// attribute vec2 a_position; + +// void main(){ +// gl_Position = vec4(a_position, 0, 1.0); +// } +// `, +// fsource: ` +// precision highp float; + +// void main(){ +// gl_FragColor = vec4(0.5, 0.5, 0.0, 1.0); +// } +// `, +// }); + +// simpleDraw(); // draw triangle +// gl_FragColor = vec4(texture2D(u_texture, vec2(217, 217))[3], texture2D(u_texture, vec2(117, 117))[3], texture2D(u_texture, vec2(0, 0))[3], 1.0); + //uniform float u_color; \ + // gl_FragColor = vec4(u_color, u_color, u_color, 1.0); \ + // gl_FragColor = vec4(texture2D(u_texture, vec2(0.5, 0.5))[0], texture2D(u_texture, vec2(0.2, 0.2))[0], texture2D(u_texture, vec2(0.3, 0.3))[0], 1.0); + + + + // fxgl.app('drawLine1', { + // vsource: ` + // attribute vec2 a_position; + // attribute float a_texcoord; + // varying float v_texcoord; + + // void main(){ + // gl_Position = vec4(a_position, 0, 1.0); + // v_texcoord = a_texcoord; + // } + // `, + // fsource: ` + // precision highp float; + // uniform sampler2D f_sum_texture; + // varying float v_texcoord; + + // void main(){ + // gl_FragColor = texture2D(f_sum_texture, vec2(v_texcoord, 0.5)); + // } + // `, + // }, 1); + + + + + + -simpleDraw(6); // draw rectangle diff --git a/image.png b/image.png new file mode 100644 index 0000000..6774ae1 Binary files /dev/null and b/image.png differ diff --git a/package.json b/package.json index 504108e..e8b48ff 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,12 @@ }, "homepage": "https://github.com/jpkli/flexgl#readme", "devDependencies": { - "uglifyjs-webpack-plugin": "^1.1.8", - "webpack": "^3.10.0" + "uglifyjs-webpack-plugin": "^1.1.6", + "webpack-cli": "^3.1.0", + "webpack-command": "^0.4.1" + }, + "dependencies": { + "npm": "^6.3.0", + "rxjs": "^6.2.2" } } diff --git a/play_framebuffer_1/main.css b/play_framebuffer_1/main.css new file mode 100644 index 0000000..a7f28b9 --- /dev/null +++ b/play_framebuffer_1/main.css @@ -0,0 +1,9 @@ +@import url("https://webglfundamentals.org/webgl/resources/webgl-tutorials.css"); +body { + margin: 0; +} +canvas { + width: 100vw; + height: 100vh; + display: block; +} diff --git a/play_framebuffer_1/main.html b/play_framebuffer_1/main.html new file mode 100644 index 0000000..ef7b1e4 --- /dev/null +++ b/play_framebuffer_1/main.html @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + diff --git a/play_framebuffer_1/main.js b/play_framebuffer_1/main.js new file mode 100644 index 0000000..7a1a1a2 --- /dev/null +++ b/play_framebuffer_1/main.js @@ -0,0 +1,219 @@ +"use strict"; + +function main() { + // Get A WebGL context + /** @type {HTMLCanvasElement} */ + var canvas = document.getElementById("canvas"); + var gl = canvas.getContext("webgl"); + if (!gl) { + return; + } + + // setup GLSL program + var program = webglUtils.createProgramFromScripts(gl, ["3d-vertex-shader", "3d-fragment-shader"]); + + // look up where the vertex data needs to go. + var positionLocation = gl.getAttribLocation(program, "a_position"); + var texcoordLocation = gl.getAttribLocation(program, "a_texcoord"); + + // lookup uniforms + var textureLocation = gl.getUniformLocation(program, "u_texture"); + var flagLocation = gl.getUniformLocation(program, "flag"); + + // Create a buffer for positions + var positionBuffer = gl.createBuffer(); + // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + // Put the positions in the buffer + setGeometry(gl); + + // provide texture coordinates for the rectangle. + var texcoordBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); + // Set Texcoords. + setTexcoords(gl); + + // Create a texture. + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + { + // fill texture with 3x2 pixels + const level = 0; + const internalFormat = gl.LUMINANCE; + const width = 4; + const height = 4; + const border = 0; + const format = gl.LUMINANCE; + const type = gl.UNSIGNED_BYTE; + const data = new Uint8Array([ + 0, 255, 0, 255, + 255, 0, 255, 0, + 0, 255, 0, 255, + 255, 0, 255, 0 + ]); + const alignment = 1; + gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment); + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border, + format, type, data); + + // set the filtering so we don't need mips and it's not filtered + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + + // Create a texture to render to + const targetTextureWidth = 2; + const targetTextureHeight = 2; + const targetTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, targetTexture); + + { + // define size and format of level 0 + const level = 0; + const internalFormat = gl.RGBA; + const border = 0; + const format = gl.RGBA; + const type = gl.UNSIGNED_BYTE; + const data = null; + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + targetTextureWidth, targetTextureHeight, border, + format, type, data); + + // set the filtering so we don't need mips + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + + // Create and bind the framebuffer + const fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + // attach the texture as the first color attachment + const attachmentPoint = gl.COLOR_ATTACHMENT0; + const level = 0; + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, targetTexture, level); + + + requestAnimationFrame(drawScene); + + + function drawCube(flag) { + // Tell it to use our program (pair of shaders) + gl.useProgram(program); + + // Turn on the position attribute + gl.enableVertexAttribArray(positionLocation); + + // Bind the position buffer. + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + + // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) + var size = 3; // 3 components per iteration + var type = gl.FLOAT; // the data is 32bit floats + var normalize = false; // don't normalize the data + var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position + var offset = 0; // start at the beginning of the buffer + gl.vertexAttribPointer( + positionLocation, size, type, normalize, stride, offset); + + // Turn on the teccord attribute + gl.enableVertexAttribArray(texcoordLocation); + + // Bind the position buffer. + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); + + // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) + var size = 2; // 2 components per iteration + var type = gl.FLOAT; // the data is 32bit floats + var normalize = false; // don't normalize the data + var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position + var offset = 0; // start at the beginning of the buffer + gl.vertexAttribPointer( + texcoordLocation, size, type, normalize, stride, offset); + + + // Tell the shader to use texture unit 0 for u_texture + gl.uniform1i(textureLocation, 0); + gl.uniform1i(flagLocation, flag); + + // Draw the geometry. + gl.drawArrays(gl.TRIANGLES, 0, 6); + } + + // Draw the scene. + function drawScene() { + + { + // render to our targetTexture by binding the framebuffer + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + // render cube with our 3x2 texture + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Tell WebGL how to convert from clip space to pixels + gl.viewport(0, 0, targetTextureWidth, targetTextureHeight); + + // Clear the canvas AND the depth buffer. + gl.clearColor(0, 0, 0, 0); // clear to blue + gl.clear(gl.COLOR_BUFFER_BIT); + + drawCube(0); + } + + { + // render to the canvas + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + // render the cube with the texture we just rendered to + gl.bindTexture(gl.TEXTURE_2D, targetTexture); + // gl.bindTexture(gl.TEXTURE_2D, texture); + + // Tell WebGL how to convert from clip space to pixels + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); + + // Clear the canvas AND the depth buffer. + gl.clearColor(0, 0, 0, 0); // clear to white + gl.clear(gl.COLOR_BUFFER_BIT); + + drawCube(1); + } + + requestAnimationFrame(drawScene); + } +} + +// Fill the buffer with the values that define a cube. +function setGeometry(gl) { + var positions = new Float32Array( + [ + -1.0, -1.0, 0.0, + -1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + -1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + ]); + gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); +} + +// Fill the buffer with texture coordinates the cube. +function setTexcoords(gl) { + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array( + [ + 0, 0, + 0, 1, + 1, 0, + 0, 1, + 1, 1, + 1, 0, + ]), + gl.STATIC_DRAW); +} + +main(); diff --git a/play_framebuffer_2/main.css b/play_framebuffer_2/main.css new file mode 100644 index 0000000..a7f28b9 --- /dev/null +++ b/play_framebuffer_2/main.css @@ -0,0 +1,9 @@ +@import url("https://webglfundamentals.org/webgl/resources/webgl-tutorials.css"); +body { + margin: 0; +} +canvas { + width: 100vw; + height: 100vh; + display: block; +} diff --git a/play_framebuffer_2/main.html b/play_framebuffer_2/main.html new file mode 100644 index 0000000..92adfe7 --- /dev/null +++ b/play_framebuffer_2/main.html @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/play_framebuffer_2/main.js b/play_framebuffer_2/main.js new file mode 100644 index 0000000..bf7c58d --- /dev/null +++ b/play_framebuffer_2/main.js @@ -0,0 +1,278 @@ +"use strict"; + +function main() { + // Get A WebGL context + /** @type {HTMLCanvasElement} */ + var canvas = document.getElementById("canvas"); + var gl = canvas.getContext("webgl"); + if (!gl) { + return; + } + + // var blendExt = gl.getExtension("EXT_blend_minmax"); + // if (blendExt) { + // gl.MAX_EXT = blendExt.MAX_EXT; + // gl.MIN_EXT = blendExt.MIN_EXT; + // } + // gl.ext = gl.getExtension("ANGLE_instanced_arrays"); + gl.getExtension("OES_texture_float"); + gl.getExtension("OES_texture_float_linear"); + + // setup GLSL program + var program = webglUtils.createProgramFromScripts(gl, ["3d-vertex-shader", "3d-fragment-shader"]); + + // look up where the vertex data needs to go. + var positionLocation = gl.getAttribLocation(program, "a_position"); + var texcoordLocation = gl.getAttribLocation(program, "a_texcoord"); + + // lookup uniforms + var textureLocation = gl.getUniformLocation(program, "u_texture"); + var flagLocation = gl.getUniformLocation(program, "flag"); + + // Create a buffer for positions + var positionBuffer = gl.createBuffer(); + // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + // Put the positions in the buffer + setGeometry(gl); + + // provide texture coordinates for the rectangle. + var texcoordBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); + // Set Texcoords. + setTexcoords(gl); + + // Create a texture. + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + { + // fill texture with 3x2 pixels + const level = 0; + const internalFormat = gl.ALPHA; + const width = 1024; + const height = 1024; + const border = 0; + const format = gl.ALPHA; + const type = gl.FLOAT; + // const type = gl.UNSIGNED_BYTE; + + // var data = []; + // for(var j = 0; j < 100; j++){ + // var typedArray = new Float32Array(1024*1024); + // for (var i = 0; i < typedArray.length; i++){ + // typedArray[i] = Math.random(); + // } + // data.push(typedArray); + // } + + var data = new Float32Array(1024*1024); + for(var i = 0; i < data.length; i++){ + data[i] = Math.random(); + } + + // var typedArray = new Float32Array(1024*1024); + // var typedArray = new Uint8Array(1024*1024); + + const alignment = 1; + gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment); + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border, + format, type, data); + + // set the filtering so we don't need mips and it's not filtered + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + + // Create a texture to render to + const targetTextureWidth = 1024; + const targetTextureHeight = 1; + const targetTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, targetTexture); + + { + // define size and format of level 0 + const level = 0; + const internalFormat = gl.RGBA; + const border = 0; + const format = gl.RGBA; + const type = gl.FLOAT; + // const type = gl.UNSIGNED_BYTE; + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + targetTextureWidth, targetTextureHeight, border, + format, type, null); + + // set the filtering so we don't need mips + // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + // + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + + // Create and bind the framebuffer + const fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + // attach the texture as the first color attachment + const attachmentPoint = gl.COLOR_ATTACHMENT0; + const level = 0; + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, targetTexture, level); + + + requestAnimationFrame(drawScene); + + + function drawCube(flag) { + // Tell it to use our program (pair of shaders) + gl.useProgram(program); + + // Turn on the position attribute + gl.enableVertexAttribArray(positionLocation); + + // Bind the position buffer. + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + + // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) + var size = 2; // 3 components per iteration + var type = gl.FLOAT; // the data is 32bit floats + var normalize = false; // don't normalize the data + var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position + var offset = 0; // start at the beginning of the buffer + gl.vertexAttribPointer( + positionLocation, size, type, normalize, stride, offset); + + // Turn on the teccord attribute + gl.enableVertexAttribArray(texcoordLocation); + + // Bind the position buffer. + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); + + // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) + var size = 1; // 2 components per iteration + var type = gl.FLOAT; // the data is 32bit floats + var normalize = false; // don't normalize the data + var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position + var offset = 0; // start at the beginning of the buffer + gl.vertexAttribPointer( + texcoordLocation, size, type, normalize, stride, offset); + + + // Tell the shader to use texture unit 0 for u_texture + gl.uniform1i(textureLocation, 0); + gl.uniform1i(flagLocation, flag); + + // Draw the geometry. + gl.drawArrays(gl.LINES, 0, 2); + } + + // Draw the scene. + function drawScene() { + + { + // render to our targetTexture by binding the framebuffer + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + // render cube with our 3x2 texture + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Tell WebGL how to convert from clip space to pixels + gl.viewport(0, 0, targetTextureWidth, targetTextureHeight); + + // Clear the canvas AND the depth buffer. + gl.clearColor(0, 0, 0, 0); // clear to blue + gl.clear(gl.COLOR_BUFFER_BIT); + + drawCube(0); + } + + { + // render to the canvas + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + // render the cube with the texture we just rendered to + gl.bindTexture(gl.TEXTURE_2D, targetTexture); + // gl.bindTexture(gl.TEXTURE_2D, texture); + + // Tell WebGL how to convert from clip space to pixels + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); + + // Clear the canvas AND the depth buffer. + gl.clearColor(0, 0, 0, 0); // clear to white + gl.clear(gl.COLOR_BUFFER_BIT); + + drawCube(1); + } + + requestAnimationFrame(drawScene); + } +} + +// Fill the buffer with the values that define a cube. +// function setGeometry(gl) { +// var positions = new Float32Array( +// [ +// -1.0, -1.0, 0.0, +// -1.0, 1.0, 0.0, +// 1.0, -1.0, 0.0, +// -1.0, 1.0, 0.0, +// 1.0, 1.0, 0.0, +// 1.0, -1.0, 0.0, +// ]); +// gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); +// } +function setGeometry(gl) { + var positions = new Float32Array( + [ + -1.0, -1.0, + 1.0, 1.0, + ]); + gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); +} +// function setTexcoords(gl) { +// gl.bufferData( +// gl.ARRAY_BUFFER, +// new Float32Array( +// [ +// 0, 0, +// 0, 1, +// 1, 0, +// 0, 1, +// 1, 1, +// 1, 0, +// ]), +// gl.STATIC_DRAW); +// } +// Fill the buffer with texture coordinates the cube. +// function setTexcoords(gl) { +// gl.bufferData( +// gl.ARRAY_BUFFER, +// new Float32Array( +// [ +// 0.0, 0.0, +// 1.0, 0.0, +// 0.0, 0.0, +// 1.0, 0.0, +// 1.0, 0.0, +// 0.0, 0.0, +// ]), +// gl.STATIC_DRAW); +// } +function setTexcoords(gl) { + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array( + [ + 0.0, + 1.0, + ]), + gl.STATIC_DRAW); +} + + +main(); diff --git a/src/attribute.js b/src/attribute.js index 6f404d3..51fb398 100644 --- a/src/attribute.js +++ b/src/attribute.js @@ -1,18 +1,27 @@ -export default function Attribute(glContext) { - +export default function Attribute(glContext) +{ var attribute = (this instanceof Attribute) ? this : {}, ctx = glContext, attributeID = 0; - function setAttribute(name, data) { - if(Array.isArray(data) || ArrayBuffer.isView(data)){ - if(!ArrayBuffer.isView(data)) data = new Float32Array(data); + function setAttribute(name, data) + { + if( Array.isArray(data) || ArrayBuffer.isView(data) ) + { + if(!ArrayBuffer.isView(data)) + { + data = new Float32Array(data); + } attribute[name].data = data; ctx.bindBuffer(ctx.ARRAY_BUFFER, attribute[name].ptr); ctx.bufferData(ctx.ARRAY_BUFFER, data, ctx.STATIC_DRAW); + // console.log(attribute[name].ptr === attribute[name].old_ptr); + // attribute[name].old_ptr = attribute[name].ptr; } } - attribute.create = function(name, type, data) { + + attribute.create = function(name, type, data) + { attribute[name] = { name: name, type: type || 'float', @@ -22,9 +31,11 @@ export default function Attribute(glContext) { size: parseInt(type.slice(3,4)) || 1 }; - if(data !== null && data.length) setAttribute(name, data); + if(data !== null && data.length) + {setAttribute(name, data);} - attribute[name].link = function(program) { + attribute[name].link = function(program) + { ctx.bindBuffer(ctx.ARRAY_BUFFER, this.ptr); this.location = ctx.getAttribLocation(program, this.name); ctx.vertexAttribPointer(this.location, this.size, ctx.FLOAT, false, 0, 0); @@ -32,14 +43,15 @@ export default function Attribute(glContext) { return this; } - attribute[name].load = function(arrayBuffer) { + attribute[name].load = function(arrayBuffer) + { setAttribute(this.name, arrayBuffer); return this; } - attribute[name].header = function() { - return 'attribute ' + this.type + ' ' + this.name + ';\n'; - } + attribute[name].header = function() + {return 'attribute ' + this.type + ' ' + this.name + ';\n';} + attribute[name].delete = function() { ctx.deleteBuffer(this.ptr); diff --git a/src/flexgl.js b/src/flexgl.js index ff3db89..913f59f 100644 --- a/src/flexgl.js +++ b/src/flexgl.js @@ -1,12 +1,14 @@ import Resource from './resource'; -import ProgramManager from './program'; -import Shader from './shader'; +import Program from './program'; import Framebuffer from './framebuffer'; +// import Reactive from './reactive'; export default function FlexGL(arg) { - var flexgl = (this instanceof FlexGL) ? this : {}, - options = arg || {}, + var flexgl = (this instanceof FlexGL) ? this : {}; + + + var options = arg || {}, container = options.container || null, canvas = options.canvas || document.createElement("canvas"), width = options.width || null, @@ -19,10 +21,10 @@ export default function FlexGL(arg) { }, ctx = options.context || options.ctx || null, kernels = {}, - program = null, sharedFunction = options.sharedFunction || {}; + if (typeof(canvas) == "string") { if (canvas[0] == "#") canvas = document.getElementById(cavnas.substring(1)); else canvas = document.getElementById(cavnas); @@ -40,25 +42,25 @@ export default function FlexGL(arg) { canvas.style.marginLeft = padding.left + "px"; canvas.style.marginTop = padding.top + "px"; + if (ctx === null) ctx = setupWebGL(canvas); flexgl.ctx = ctx; flexgl.canvas = canvas; - + flexgl.resources = resources; ctx._dict = options.env || options.dict || options.dictionary || {}; - var resources = new Resource(ctx), framebuffers = new Framebuffer(ctx), - programManager = new ProgramManager(ctx, resources), - shaders = new Shader(ctx, resources); + program = new Program(ctx, resources), + realProgram = null; + var blendExt = ctx.getExtension("EXT_blend_minmax"); if (blendExt) { ctx.MAX_EXT = blendExt.MAX_EXT; ctx.MIN_EXT = blendExt.MIN_EXT; } - ctx.ext = ctx.getExtension("ANGLE_instanced_arrays"); enableExtension([ "OES_texture_float", @@ -66,10 +68,10 @@ export default function FlexGL(arg) { // "OES_texture_half_float", // "OES_texture_half_float_linear" ]); - if (container) container.appendChild(canvas); + function setupWebGL(canvas) { var names = ["webgl", "experimental-webgl"]; var gl = null; @@ -95,7 +97,6 @@ export default function FlexGL(arg) { } }); }; - flexgl.enableExtension = enableExtension; /** @@ -107,17 +108,19 @@ export default function FlexGL(arg) { */ flexgl.attribute = function(name, type, data) { resources.allocate("attribute", name, type, data); - Object.defineProperty(flexgl.attribute, name, { - get: function() { - return resources.attribute[name]; - }, - set: function(data) { - resources.attribute[name].load(data); - } - }); + if (!flexgl.attribute.hasOwnProperty(name)) { + Object.defineProperty(flexgl.attribute, name, { //after allocating, flexgl gets new key attribute, helping easily change attribute data. + get(){ + return resources.attribute[name]; + }, + set(data){ + resources.attribute[name].load(data); + } + }); + } return flexgl; }; - flexgl.buffer = flexgl.attribute; //alias + // flexgl.buffer = flexgl.attribute; //alias /** * Create a Uniform variable for WebGL shader programs @@ -135,8 +138,8 @@ export default function FlexGL(arg) { }, set: function(data) { resources.uniform[name].load(data); - if (ctx.isProgram(program)) - resources.uniform[name].link(program); + if (ctx.isProgram(realProgram)) /////////////////// + resources.uniform[name].link(realProgram); ///////////////// } }); } @@ -200,8 +203,8 @@ export default function FlexGL(arg) { */ flexgl.framebuffer = function(name, type, dim, texture) { var texture = texture || resources.allocate('texture', name, type, dim, 'rgba', null); - framebuffers.create(name, type, dim, texture); + if (!flexgl.framebuffer.hasOwnProperty(name)) { Object.defineProperty(flexgl.framebuffer, name, { get: function() { @@ -212,7 +215,7 @@ export default function FlexGL(arg) { return flexgl; } - flexgl.framebuffer.enableRead = function(name) { + flexgl.framebuffer.enableRead = function(name, program) { framebuffers[name].enableRead(program); } @@ -251,31 +254,13 @@ export default function FlexGL(arg) { } flexgl.dictionary = flexgl.parameter; + flexgl.shader = program.shader; - flexgl.shader = programManager.shader; - - flexgl.program = function(name, vs, fs) { - program = programManager.program(name, vs, fs); - return ctx; - } - - flexgl.createProgram = function(name, vs, fs) { - program = programManager.create(name, vs, fs); - return ctx; - } - - flexgl.app = function(name, props) { - var vs = flexgl.shader.vertex(props.vs), - fs = flexgl.shader.fragment(props.fs), - fb = props.framebuffer || null; - - flexgl.program(name, vs, fs); - var draw = props.render || props.draw; - - return function(args) { - var gl = flexgl.program(name); - return draw.call(gl, args); + flexgl.app = function(name, options) { + return function(args){ + realProgram = program.use(name, options.vertex_shader_source, options.fragment_shader_source); + return options.render.call(flexgl, args); } } @@ -283,7 +268,6 @@ export default function FlexGL(arg) { return [canvas.width, canvas.height]; } - flexgl.resources = resources; - return flexgl; } + diff --git a/src/framebuffer.js b/src/framebuffer.js index 2a50cb7..2d2bc97 100644 --- a/src/framebuffer.js +++ b/src/framebuffer.js @@ -14,25 +14,25 @@ export default function Framebuffer(glContext) { width: dim[0] || 1024, height: dim[1] || 1024, texture: texture || null, - renderbuffer: ctx.createRenderbuffer(), + // renderbuffer: ctx.createRenderbuffer(), } - if (framebuffer[name].texture === null) { - var buf = (type == 'float') ? - new Float32Array(dim[0] * dim[1] * 4) : - new Uint8Array(dim[0] * dim[1] * 4); - framebuffer[name].texture = Texture(ctx).create(name, type, dim, "rgba", buf); - } + // if (framebuffer[name].texture === null) { + // var buf = (type == 'float') ? + // new Float32Array(dim[0] * dim[1] * 4) : + // new Uint8Array(dim[0] * dim[1] * 4); + // framebuffer[name].texture = Texture(ctx).create(name, type, dim, "rgba", buf); + // } - var renderbuffer = framebuffer[name].renderbuffer; + // var renderbuffer = framebuffer[name].renderbuffer; ctx.bindFramebuffer(ctx.FRAMEBUFFER, framebuffer[name].ptr); - ctx.bindRenderbuffer(ctx.RENDERBUFFER, renderbuffer); - ctx.renderbufferStorage( - ctx.RENDERBUFFER, - ctx.DEPTH_COMPONENT16, - framebuffer[name].width, - framebuffer[name].height - ); + // ctx.bindRenderbuffer(ctx.RENDERBUFFER, renderbuffer); + // ctx.renderbufferStorage( + // ctx.RENDERBUFFER, + // ctx.DEPTH_COMPONENT16, + // framebuffer[name].width, + // framebuffer[name].height + // ); ctx.framebufferTexture2D( ctx.FRAMEBUFFER, ctx.COLOR_ATTACHMENT0, @@ -40,13 +40,13 @@ export default function Framebuffer(glContext) { framebuffer[name].texture.ptr, 0 ); - ctx.framebufferRenderbuffer( - ctx.FRAMEBUFFER, - ctx.DEPTH_ATTACHMENT, - ctx.RENDERBUFFER, - renderbuffer - ); - ctx.bindRenderbuffer(ctx.RENDERBUFFER, null); + // ctx.framebufferRenderbuffer( + // ctx.FRAMEBUFFER, + // ctx.DEPTH_ATTACHMENT, + // ctx.RENDERBUFFER, + // renderbuffer + // ); + // ctx.bindRenderbuffer(ctx.RENDERBUFFER, null); ctx.bindFramebuffer(ctx.FRAMEBUFFER, null); framebuffer[name].enableRead = function(program) { @@ -56,6 +56,10 @@ export default function Framebuffer(glContext) { ctx.uniform1i(this.texture.location, this.texture.index); }; + // framebuffer[name].enableRead = function(program) { + // this.texture.link(program); + // }; + framebuffer[name].delete = function() { ctx.bindRenderbuffer(gl.RENDERBUFFER, null); ctx.bindFramebuffer(gl.FRAMEBUFFER, null); diff --git a/src/program.js b/src/program.js index 8bb88a9..67271f3 100644 --- a/src/program.js +++ b/src/program.js @@ -2,26 +2,24 @@ import Shader from './shader'; export default function Program(glContext, resources) { - var program, + var program = {}, ctx = glContext, - pm = {}, kernels = {}, - shaders = new Shader(glContext, resources); + shader = new Shader(glContext); - pm.create = function(name, vs, fs) { + program.create = function(name, vs, fs) { var name = name || "default", vs = vs || "default", fs = fs || "default", deps = []; if (kernels.hasOwnProperty(name)) { - pm.delete(name); + this.delete(name); } kernels[name] = ctx.createProgram(); - - kernels[name].vs = (typeof vs == "object") ? vs : shaders.vertex[vs]; - kernels[name].fs = (typeof fs == "object") ? fs : shaders.fragment[fs]; + kernels[name].vs = vs; + kernels[name].fs = fs; ctx.attachShader(kernels[name], kernels[name].vs); ctx.attachShader(kernels[name], kernels[name].fs); @@ -31,28 +29,30 @@ export default function Program(glContext, resources) { var lastError = ctx.getProgramInfoLog(kernels[name]); throw ("Error in program linking:" + lastError); ctx.deleteProgram(kernels[name]); - return null; } deps = deps.concat(kernels[name].vs.deps); deps = deps.concat(kernels[name].fs.deps); kernels[name].deps = deps; - return kernels[name]; } - pm.use = pm.program = function(name, vs, fs) { + program.use = function(name, vertex_shader_source, fragment_shader_source) { if (kernels.hasOwnProperty(name)) { - program = kernels[name]; - ctx.useProgram(program); - resources.link(program, program.deps); - return program; - } else { - return pm.create(name, vs, fs); + ctx.useProgram(kernels[name]); + resources.link(kernels[name], kernels[name].deps); + return kernels[name]; + } + else { + shader.create(name, vertex_shader_source, fragment_shader_source); + this.create(name, shader[name].vs, shader[name].fs); + ctx.useProgram(kernels[name]); + resources.link(kernels[name], kernels[name].deps); + return kernels[name]; } } - pm.delete = function(name) { + program.delete = function(name) { if (kernels.hasOwnProperty(name)) { ctx.detachShader(kernels[name], kernels[name].vs); ctx.detachShader(kernels[name], kernels[name].fs); @@ -61,27 +61,5 @@ export default function Program(glContext, resources) { } } - pm.shader = function(arg, fn) { - var options = arg; - shaders.create(options, fn); - return pm; - } - - pm.shader.vertex = function(fn) { - var options = { - type: "vertex" - }; - if (fn.name) options.name = fn.name; - return shaders.create(options, fn); - } - - pm.shader.fragment = function(fn) { - var options = { - type: "fragment" - }; - if (fn.name) options.name = fn.name; - return shaders.create(options, fn); - } - - return pm; + return program; } diff --git a/src/reactive.js b/src/reactive.js new file mode 100644 index 0000000..c03f55f --- /dev/null +++ b/src/reactive.js @@ -0,0 +1,31 @@ +function Reactive(data, chunk) +{ + var reactive = (this instanceof Reactive) ? this : { + pointer : -1, + size: chunk, + data_all: data + }; + + reactive.updateButton = document.querySelector('.update'); + reactive.updateClickStream = Rx.Observable.fromEvent(reactive.updateButton, 'click'); + + reactive.requestStream = reactive.updateClickStream.startWith('startup click') + .flatMap(function(){ + reactive.pointer++; + return reactive.pointer; + }); + + reactive.responseStream = reactive.requestStream + .flatMap(function(p){ + return reactive.data_all.slice(p*reactive.size, (p+1)*reactive.size); + }); + + reactive.responseStream.subscribe(function(d){ + reactive.data_chunk = d; + reactive.sum += reactive.data_chunk.reduce(function(x,y){ + return x+y; + }) + }); + + return reactive; +} diff --git a/src/resource.js b/src/resource.js index 284219a..02c629f 100644 --- a/src/resource.js +++ b/src/resource.js @@ -4,7 +4,8 @@ import Texture from './texture'; import Varying from './varying'; import Subroutine from './subroutine'; -export default function Resource(glContext) { +export default function Resource(glContext) +{ var resource = (this instanceof Resource) ? this : {}, gpuResources = {}; @@ -16,38 +17,36 @@ export default function Resource(glContext) { var resourceTypes = ['uniform', 'attribute', 'texture', 'varying', 'subroutine']; - resource.allocate = function(type, props) { - if (resourceTypes.indexOf(type) === -1) { - throw Error("Error: Invalid resource type: " + type); - } + resource.allocate = function(type) + { + if (resourceTypes.indexOf(type) === -1) { throw Error("Error: Invalid resource type: " + type); } + var res = resource[type].create.apply(null, Array.prototype.slice.call(arguments, 1)); res.resourceType = type; gpuResources[res.name] = res; - if (!gpuResources.hasOwnProperty(res.name)) { + + if (!gpuResources.hasOwnProperty(res.name)) + { Object.defineProperty(gpuResources, res.name, { - get: function() { - return gpuResources[res.name]; - }, - set: function(data) { - gpuResources[res.name].load(data); - } + get: function() { return gpuResources[res.name];}, + set: function(data) { gpuResources[res.name].load(data);} }); } return res; }; - resource.link = function(program, resources) { - var requiredResources = (Array.isArray(resources)) ? resources : Object.keys(gpuResources); - requiredResources.forEach(function(resourceName) { - if (gpuResources.hasOwnProperty(resourceName)) + resource.link = function(program, resource_names) { + var requiredResourceNames = (Array.isArray(resource_names)) ? resource_names : Object.keys(gpuResources); + requiredResourceNames.forEach(function(resourceName) { + if (gpuResources.hasOwnProperty(resourceName)) { gpuResources[resourceName].link(program); + } }) }; resource.get = function(name) { return gpuResources[name]; } - resource.create = resource.allocate; return resource; diff --git a/src/shader.js b/src/shader.js index 6003c99..9001ae7 100644 --- a/src/shader.js +++ b/src/shader.js @@ -1,227 +1,46 @@ -export default function Shader(glContext, glResource) { +export default function Shader(glContext) { var shader = (this instanceof Shader) ? this : {}, - ctx = glContext, - resource = glResource, - parameters = ctx._dict || {}; - - shader.vertex = {}; - shader.fragment = {}; - - var shaderType = { - vertex: ctx.VERTEX_SHADER, - fragment: ctx.FRAGMENT_SHADER - }; - - // Convert JS functions to GLSL codes - function toGLSL(returnType, name, fn){ - - var glsl = returnType + ' ' + - name + '(' + applyEnvParameters(fn.toString()) - .replace( - /var\s+([\w|\d]+)\s*=\s*new\s+([\w|\d]+)\((.*)\)/g, - function(expr, name, dtype, value){ - var parts; - if(value) - parts = [dtype.toLowerCase(), name, '=', value]; - else - parts = [dtype.toLowerCase(), name]; - - return parts.join(' ') - } - ) - .replace(/for\s*\(\s*var\s+/g, 'for(int ') - .replace(/var\s/g, 'float ') - .replace(/this./g, '') - .replace(/\$(.*)\((.*)\)\s*(=|;)/g, "$1 $2 $3"); - // .replace(/\$(.*?)\./g, "$1 ") - - if(name == "main") { - glsl = glsl.replace(/function.*\(\s*([\s\S]*?)\s*{/, '){') + "\n"; - } else { - var args = glsl.match(/function.*\(\s*([\s\S]*?)\s*\)/)[1]; - - if(args != "") { - args = args.replace(/\$([\w|\d]+)_/g, "$1 "); + ctx = glContext; + // resource = glResource, + // parameters = ctx._dict || {}; + + shader.create = function(name, vertex_shader_source, fragment_shader_source){ + shader[name] = { + name: name, + vertex_shader_source: vertex_shader_source, + fragment_shader_source: fragment_shader_source, + vs: createShader(ctx, ctx.VERTEX_SHADER, vertex_shader_source), + fs: createShader(ctx, ctx.FRAGMENT_SHADER, fragment_shader_source) + } + + shader[name].vs.deps = []; + addDeps(vertex_shader_source, shader[name].vs.deps); + shader[name].fs.deps = []; + addDeps(fragment_shader_source, shader[name].vs.deps); + + function createShader(gl, type, source) { + var shader = gl.createShader(type); + gl.shaderSource(shader, source); + gl.compileShader(shader); + var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + if (success) { + return shader; } - glsl = glsl - .replace(/function.*\(\s*([\s\S]*?)\s*\)/, args+')') + "\n"; - } - return glsl; - } - - //set parameters in JS functions before converting to GLSL codes - function applyEnvParameters(str){ - //find all $(...) and replace them with parameters - var envParam = Object.keys(parameters); - if(envParam.length > 0){ - var re = new RegExp("\\$\\(("+envParam.join("|")+")\\)","g"); - str = str.replace(re, function(matched){ - return parameters[matched.slice(2,matched.length-1)]; - }); - } - - // Make uniforms to be used as parameters in shaders, like $(uniformName) - // var envUniforms = Object.keys(resource.uniform); - // re = new RegExp("\\$\\(("+envUniforms.join("|")+")\\)","g"); - // str = str.replace(re, function(matched){ - // return resource.uniform[matched.slice(2,matched.length-1)].data; - // }); - - return str; - } - - function compile(shaderType, shaderSource) { - if (shaderType !== ctx.VERTEX_SHADER && shaderType !== ctx.FRAGMENT_SHADER) { - throw ("Error: unknown shader type"); - } - var _shader = ctx.createShader(shaderType); - ctx.shaderSource(_shader, shaderSource); - ctx.compileShader(_shader); - - // Check the compile status, get compile error if any - var compiled = ctx.getShaderParameter(_shader, ctx.COMPILE_STATUS); - if (!compiled) { - var lastError = ctx.getShaderInfoLog(_shader); - console.log(shaderSource + '\n ===================================================='); - throw new Error("Error compiling shader '" + _shader + "':" + lastError); - - ctx.deleteShader(_shader); - return null; + // console.log('NO!'); + console.log(gl.getShaderInfoLog(shader)); + gl.deleteShader(shader); } - return _shader; - } - - function getDeps(fn) { - var deps = [], - sourceCode = fn.toString(), - shaderArgs = sourceCode.match(/function\s.*?\(([^)]*)\)/), - args = (shaderArgs !== null && shaderArgs.length) ? shaderArgs[1] : []; - // args = args.replace(/(?:\r\n|\r|\n|\s)/g, ''); - // - if(args.length) { - deps = args.split(',').map(function(arg) { - return arg.replace(/\/\*.*\*\//, '').trim(); - }).filter(function(arg) { - return arg; - }); - } - - var extraDeps = getExtraDeps(sourceCode); - if(extraDeps.length) { - deps = deps.concat(extraDeps - .filter(function(d){ - return deps.indexOf(d) === -1; - })) - } - - return deps; - } - - function getExtraDeps(fnString) { - var extraDeps = fnString.match(/this\.(\w+)/g); - if(extraDeps !== null) { - extraDeps = extraDeps.map(function(d){ - return d.slice(5); - }); - } - return extraDeps || []; - } - - function declareDep(dep) { - var res = resource.get(dep); - if(typeof res === 'undefined') - throw new Error('Resource/dependence "' + dep + '" is not found.'); - if(res.resourceType == 'subroutine') - return toGLSL(res.type, res.name, res.fn); - else - return res.header(); - } - - function uniqueDeps(deps) { - var names = {}; - deps.forEach(function(d, i){ - names[d] = i; - }); - - return Object.keys(names); - } - - shader.create = function(arg, fn){ - var option = arg || {}, - name = option.name || "default", - type = option.type || "vertex", - deps = option.require || option.deps || [], - precision = option.precision || "high", - debug = option.debug || false, - main = option.main || fn || function() {}; - - var shaderSource = 'precision ' + precision + 'p float;\n'; - - if(deps.length === 0) deps = uniqueDeps(getDeps(main)); - - //get dependence from subroutines if any - var extraDeps = [], - subRoutines = []; - - deps.forEach(function(dep){ - var res = resource.get(dep); - if(typeof res == 'undefined') { - console.log(dep); - throw Error ('Error! Undefined variable in shader: '+ dep.name); - } - if(res.resourceType == 'subroutine') { - subRoutines.push(res.name); - var subDeps = getExtraDeps(res.fn.toString()); - if(subDeps.length) { - //TODO: make this recursive to check all subroutine deps - subDeps.forEach(function(sdep){ - var sres = resource.get(sdep); - if(sres.resourceType == 'subroutine') - extraDeps = extraDeps.concat(getExtraDeps(sres.fn.toString())); - }) - - extraDeps = extraDeps.concat(subDeps); + function addDeps(source, deps){ + var re = /\s*(attribute|uniform)\s+\w+\s+(\w+)/; + source.split('\n').forEach(function(v){ + var result = re.exec(v); + if(result){ + deps.push(result[2]); } - } - }) - - if(extraDeps.length) { - var allDeps = extraDeps - // .filter(function(d){ - // return deps.indexOf(d) === -1; - // }) - .concat(deps.filter(function(d){ - return subRoutines.indexOf(d) === -1; - })) - .concat(subRoutines); - - deps = uniqueDeps(allDeps); - } - - - if(Array.isArray(deps)){ - deps.forEach(function(dep){ - shaderSource += declareDep(dep); }); - } else if(typeof(deps) == 'object') { - Object.keys(deps).forEach(function(resourceType){ - deps[resourceType].forEach(function(dep){ - shaderSource += declareDep(dep); - }); - }) } - - shaderSource += toGLSL('void', 'main', main); - if(debug) - console.log(shaderSource); - var _shader = compile(shaderType[type], shaderSource); - _shader._shaderType = shaderType[type]; - _shader.deps = deps; - _shader.source = shaderSource; - shader[type][name] = _shader; - return _shader; } return shader; diff --git a/src/shader_expire.js b/src/shader_expire.js new file mode 100644 index 0000000..03a1a6d --- /dev/null +++ b/src/shader_expire.js @@ -0,0 +1,230 @@ +export default function Shader(glContext, glResource) { + + var shader = (this instanceof Shader) ? this : {}, + ctx = glContext, + resource = glResource, + parameters = ctx._dict || {}; + + shader.vertex = {}; + shader.fragment = {}; + + var shaderType = { + vertex: ctx.VERTEX_SHADER, + fragment: ctx.FRAGMENT_SHADER + }; + + // Convert JS functions to GLSL codes + function toGLSL(returnType, name, fn){ + + var glsl = returnType + ' ' + + name + '(' + applyEnvParameters(fn.toString()) + .replace( + /var\s+([\w|\d]+)\s*=\s*new\s+([\w|\d]+)\((.*)\)/g, + function(expr, name, dtype, value){ + var parts; + if(value) + parts = [dtype.toLowerCase(), name, '=', value]; + else + parts = [dtype.toLowerCase(), name]; + + return parts.join(' ') + } + ) + .replace(/for\s*\(\s*var\s+/g, 'for(int ') + .replace(/var\s/g, 'float ') + .replace(/this./g, '') + .replace(/\$(.*)\((.*)\)\s*(=|;)/g, "$1 $2 $3"); + // .replace(/\$(.*?)\./g, "$1 ") + + if(name == "main") { + glsl = glsl.replace(/function.*\(\s*([\s\S]*?)\s*{/, '){') + "\n"; + } else { + var args = glsl.match(/function.*\(\s*([\s\S]*?)\s*\)/)[1]; + + if(args != "") { + args = args.replace(/\$([\w|\d]+)_/g, "$1 "); + } + glsl = glsl + .replace(/function.*\(\s*([\s\S]*?)\s*\)/, args+')') + "\n"; + } + return glsl; + } + + //set parameters in JS functions before converting to GLSL codes + function applyEnvParameters(str){ + //find all $(...) and replace them with parameters + var envParam = Object.keys(parameters); + if(envParam.length > 0){ + var re = new RegExp("\\$\\(("+envParam.join("|")+")\\)","g"); + str = str.replace(re, function(matched){ + return parameters[matched.slice(2,matched.length-1)]; + }); + } + + // Make uniforms to be used as parameters in shaders, like $(uniformName) + // var envUniforms = Object.keys(resource.uniform); + // re = new RegExp("\\$\\(("+envUniforms.join("|")+")\\)","g"); + // str = str.replace(re, function(matched){ + // return resource.uniform[matched.slice(2,matched.length-1)].data; + // }); + + return str; + } + + function compile(shaderType, shaderSource) { + if (shaderType !== ctx.VERTEX_SHADER && shaderType !== ctx.FRAGMENT_SHADER) { + throw ("Error: unknown shader type"); + } + var _shader = ctx.createShader(shaderType); + ctx.shaderSource(_shader, shaderSource); + ctx.compileShader(_shader); + + // Check the compile status, get compile error if any + var compiled = ctx.getShaderParameter(_shader, ctx.COMPILE_STATUS); + if (!compiled) { + var lastError = ctx.getShaderInfoLog(_shader); + console.log(shaderSource + '\n ===================================================='); + throw new Error("Error compiling shader '" + _shader + "':" + lastError); + + ctx.deleteShader(_shader); + return null; + } + + return _shader; + } + + function getDeps(fn) { + var deps = [], + sourceCode = fn.toString(), + shaderArgs = sourceCode.match(/function\s.*?\(([^)]*)\)/), + args = (shaderArgs !== null && shaderArgs.length) ? shaderArgs[1] : []; + // args = args.replace(/(?:\r\n|\r|\n|\s)/g, ''); + // + if(args.length) { + deps = args.split(',').map(function(arg) { + return arg.replace(/\/\*.*\*\//, '').trim(); + }).filter(function(arg) { + return arg; + }); + } + + var extraDeps = getExtraDeps(sourceCode); + if(extraDeps.length) { + deps = deps.concat(extraDeps + .filter(function(d){ + return deps.indexOf(d) === -1; + })) + } + + return deps; + } + + function getExtraDeps(fnString) { + var extraDeps = fnString.match(/this\.(\w+)/g); + if(extraDeps !== null) { + extraDeps = extraDeps.map(function(d){ + return d.slice(5); + }); + } + return extraDeps || []; + } + + function declareDep(dep) { + var res = resource.get(dep); + if(typeof res === 'undefined') + throw new Error('Resource/dependence "' + dep + '" is not found.'); + if(res.resourceType == 'subroutine') + return toGLSL(res.type, res.name, res.fn); + else + return res.header(); + } + + function uniqueDeps(deps) { + var names = {}; + deps.forEach(function(d, i){ + names[d] = i; + }); + + return Object.keys(names); + } + + shader.create = function(arg, fn){ + var option = arg || {}, + name = option.name || "default", + type = option.type || "vertex", + deps = option.require || option.deps || [], + precision = option.precision || "high", + debug = option.debug || false, + main = option.main || fn || function() {}; + + var shaderSource = 'precision ' + precision + 'p float;\n'; + + if(deps.length === 0) deps = uniqueDeps(getDeps(main)); + + //get dependence from subroutines if any + var extraDeps = [], + subRoutines = []; + + deps.forEach(function(dep){ + var res = resource.get(dep); + if(typeof res == 'undefined') { + console.log(dep); + throw Error ('Error! Undefined variable in shader: '+ dep.name); + } + if(res.resourceType == 'subroutine') { + subRoutines.push(res.name); + var subDeps = getExtraDeps(res.fn.toString()); + if(subDeps.length) { + //TODO: make this recursive to check all subroutine deps + subDeps.forEach(function(sdep){ + var sres = resource.get(sdep); + if(sres.resourceType == 'subroutine') + extraDeps = extraDeps.concat(getExtraDeps(sres.fn.toString())); + }) + + extraDeps = extraDeps.concat(subDeps); + } + } + }) + + if(extraDeps.length) { + var allDeps = extraDeps + // .filter(function(d){ + // return deps.indexOf(d) === -1; + // }) + .concat(deps.filter(function(d){ + return subRoutines.indexOf(d) === -1; + })) + .concat(subRoutines); + + deps = uniqueDeps(allDeps); + } + + + if(Array.isArray(deps)){ + deps.forEach(function(dep){ + shaderSource += declareDep(dep); + }); + } else if(typeof(deps) == 'object') { + Object.keys(deps).forEach(function(resourceType){ + deps[resourceType].forEach(function(dep){ + shaderSource += declareDep(dep); + }); + }) + } + + shaderSource += toGLSL('void', 'main', main); + + if(debug) + console.log(shaderSource); + + var _shader = compile(shaderType[type], shaderSource); + _shader._shaderType = shaderType[type]; + _shader.deps = deps; + _shader.source = shaderSource; + shader[type][name] = _shader; + return _shader; + } + + return shader; +} diff --git a/src/texture.js b/src/texture.js index dc9fc92..5c3f245 100644 --- a/src/texture.js +++ b/src/texture.js @@ -6,7 +6,8 @@ export default function Texture(glContext) { ctx = glContext, textureID = 0; - function setTexture(name, texData) { + function setTexture(name, texData) + { var type = ctx[texture[name].type.toUpperCase()], format = ctx[texture[name].channel.toUpperCase()], width = texture[name].dim[0], @@ -72,7 +73,7 @@ export default function Texture(glContext) { } texture[name].link = function(program) { - if (this.data !== null) { + // if (this.data !== null) { // ctx.activeTexture(ctx.TEXTURE0 + this.index); // ctx.bindTexture(ctx.TEXTURE_2D, this.ptr); // this.location = ctx.getUniformLocation(program, this.name); @@ -81,7 +82,9 @@ export default function Texture(glContext) { this.sampler.data = texture[name]; this.sampler.link(program); - } + // }else{ + // console.log('texture data is null!!!') + // } return this; } @@ -109,7 +112,7 @@ export default function Texture(glContext) { updateTexture(this.name, texData, offset, dim); return this; } - + texture[name].resize = function(dim, data) { this.dim = dim; setTexture(this.name, data); diff --git a/src/uniform.js b/src/uniform.js index c2803b2..9afa972 100644 --- a/src/uniform.js +++ b/src/uniform.js @@ -38,6 +38,7 @@ export default function Uniform(glContext, name, type, data) { ctx['uniformMatrix' + size + 'fv'](location, false, buf); } else if(type == 'sampler2D') { if(data.hasOwnProperty('resourceType') && data.resourceType == 'texture') { + // console.log('bind ' + data.index); ctx.activeTexture(ctx.TEXTURE0 + data.index); ctx.bindTexture(ctx.TEXTURE_2D, data.ptr); ctx.uniform1i(location, data.index);